Lane SV recovered the script-object subsystem statically and predicted that SVSOSwarmQueen::RegisterHives takes one strategic-generator word per new hive inside StrategyServer::BeginProcessTurn, which runs inside lane Z's autosave bracket and outside both turn drivers. Nothing had ever been hooked in that interval. Measured on VM140, and it is right. turn 1 -> 2 (hives created) BeginProcessTurn 2 ProcessTurn 20 residual 2 turn 2 -> 3 (hives exist) BeginProcessTurn 0 ProcessTurn 19 residual 0 Two instruments that share no code path agree: the region ledger reads 170 -> 172 across RegisterHives, and the return-address draw-site table gains a row at 0x00527714 (NextInt, 2 calls / 2 words) which is absent on the next turn. The draws produce NextQ 30/28, TickHives' slip takes them to 31/29 -- exactly turn2-state.sav -- and the next turn's slip gives 32/30, exactly turn3-state.sav. So tail-rng-ledger.md's "all of it inside ProcessTurn, residual exactly zero" is correct for every turn it measured and false as a statement about the code. The interval a standalone must reproduce starts at BeginProcessTurn. Also closed or corrected: * LO/HI read live rather than fitted: NextQ = frame + 20 + NextInt(10), inclusive; the TickHives gates are 10 (a frame floor), 5 and 3, so no queen can spawn before frame 11 on any save. * CDiff's threshold scan re-read independently: the tier can only ever be 0 or 1, and "entered and stored nothing" was observed live and distinguished from "did not run" (method rule 20). * SnLv measured for the first time: Spica reads AFlags 0 with SnLv 0x200, so the sensor branch is what refreshes it -- nvo-tshn-visible-owner.md §6 goes [H] to [V]. ComputeContactLevel's documented "else 1" names one of four return tails; the observed non-visible level is 2. * Rule 19: the oracle reproduced byte for byte with all five new detours live, and again with four watchpoints armed on top. * turn1-state -> turn2 is not deterministic (lane L5 owns this). Two more runs here make it four distinct outcomes over six runs, including two DIFFERENT hooks=off results, and the strategic generator is provably not what varies. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ARBgSooAfokKUy6wKUKEyZ |
||
|---|---|---|
| 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.