Lane W recovered what the type is; this is what moves it. Nothing in the turn calls a method on a child script object directly. A driver notifies the root with an integer event id, the root fans the delivery out to every child, and each delivery is a generic handler plus one event-specific vtable slot chosen from a 33-entry jump table at 0x007a6480. That table is what proves the hand-written pairs lane K read in the tail are event deliveries and not ad-hoc calls, and five of its rows are not in slot order. Six deliveries in a turn, from five functions, with the ids they send. Three handlers write the eight leaves that diverged: the slavers' difficulty tier (a three-record stack table against the frame, and at frame >= 100 the scan runs off the end and stores nothing, so the tier can never reach 2), the refugees' one-shot latch at turn begin, and the swarm queen's hives -- registered on the systems whose EggScio equals the SWARM's scenario tag, which the queen's constructor stores at +0x4 while its own encounter id sits at +0x8. The hive target turn slips forward by one every turn the spawn gates fail. That single `inc` is the whole explanation of a field that reads 31 after turn 1 and 32 after turn 2, which no re-roll can produce on two hives at once. Corrects combat-done-tail.md: the tail has a FOURTH script-hook site, at 0x007d9820, and it sends event 0x1c -- the same id ProcessTurn sends, which lane K attributed to that driver alone. Two leaves stay blocked, and not on a workload: the refugees' design id needs handle allocation and data-file instantiation, and the hive target turn needs one MT draw plus two config constants behind pointers no reference initialises in a form this lane could follow. Fitting them from a single two-hive observation would have been fitting, not derivation, so it was not done. An RNG claim for the next lane to falsify cheaply: lane Z's "residual outside the two turn drivers is exactly zero" was measured on turns where the hives already existed. Hive creation draws inside BeginProcessTurn, outside both drivers and before either. 13 addresses in ghidra/addresses.d/lane-sv.json; validated to a scratch path, merges to 1,204 with no duplicate name. A fourteenth was dropped: this lane reached 0x004271c0 independently and would have filed it as RNG_NextIntInclusive, but addresses.json already carries it as RNG_NextInt with the same convention and four lanes depend on that name. The merger only detects duplicate NAMES, so a second name for one address would have merged silently and forked the vocabulary for the campaign's most-used RNG primitive. |
||
|---|---|---|
| campaign | ||
| findings | ||
| ghidra | ||
| guides | ||
| notes | ||
| objects | ||
| scripts | ||
| tools | ||
| verify | ||
| .gitignore | ||
| README.md | ||
sots-re
Reverse-engineering worklog for Sword of the Stars (2006, SOTS1) — the 32-bit DX9 original + expansions. The nitty-gritty: static/dynamic analysis notes, Ghidra & ReVa scripts, function/struct maps, D3D9 call traces, decomp progress, findings.
Where this runs
Analysis lab on spicy (PVE, 192.168.3.201):
- CT111
sots-re— Linux workspace: Ghidra + headless ReVa server, radare2/rizin/cutter, binwalk. Hosts the Samba share and this repo's working tree at/srv/re-lab/notes. - VM140
sots-re-win10— Win10 runtime + dynamic analysis (x64dbg, Cheat Engine, RenderDoc/apitrace, DXVK→CPU-Vulkan for GPU-less rendering).
Infra (guests, storage, network, share, ReVa endpoint) is documented from the
system-maintainer POV in trikilli → services/re-lab.md. This repo is everything else.
Layout
findings/— the running findings log (append-only), one file per subsystem.ghidra/— exported scripts, data-type archives, struct definitions.traces/— D3D9 / Win32 API call captures + analysis.scripts/— helper tooling (loaders, extractors, parsers).notes/— session notes, scratch, hypotheses.
Ownership / legality
Game binaries come from the owner's own GOG/Steam copy. RE is for personal
interoperability, bug-fixing, and preservation. Binaries themselves are not committed
here (see .gitignore) — they live on the lab's Samba share /srv/re-lab/samples.
Campaign (how this repo is run)
A 4-agent crew (defined in ~/.claude/agents/re-*.md) runs the exploration:
re-quartermaster (backlog + board) → re-analyst (maps via ReVa) →
re-verifier (proves vs real data; old-vs-new differential once reimpl starts) →
re-scribe (files the note, links it, commits).
campaign/board.md— live status board (start here).- Live tracking = Forgejo issues on
alex/sots-re(labelsstatus/*are the kanban columns;type/*,conf/*).campaign/board.mdis the editable mirror — publish withscripts/forgejo_campaign.py bootstrap(needsFORGEJO_TOKEN). campaign/backlog.md— prioritized target queue.campaign/open-questions.md— unresolved threads.findings/_template.md— the record format every finding follows.findings/{objects,control-flow,subsystems}/— the growing engine map.verify/{parsers,traces,harness,results}/— validation: struct parsers now, golden-trace replay + shim compare-mode for reimplementation.ghidra/— exported scripts + datatype archives.
Approach & north star: findings/00-strategy.md. Binary facts: findings/01-fingerprint.md.
Sibling repo
alex/sots-engine — the from-scratch engine source (clean-room, public-capable). This repo keeps the
evidence + planning for both; binary facts cross over only via ghidra/addresses.json → tools/gen_addresses.py.
guides/re-windows-2000s-howto.md— annotated bibliography + how-to for RE of mid-2000s MSVC/DX9 Windows games, with our-experience call-outs.