Sword of the Stars (2006) reverse-engineering worklog. Infra docs live in trikilli services/re-lab.md.
Find a file
alex 49fa5501ba lane T2: the treaty-turn stamp, and Player.Status's real writer
findings/subsystems/treaty-turn-stamp.md. Briefed on the post-combat tail, ranked its
phases by leaves-closed-per-effort against the standalone's 158-leaf residual, and found
that every tail phase which moves a leaf in this corpus is blocked on another lane
(ship construction, the budget) or on the tail's vtable blind spot. Section 5 lists that
ranking with the numbers. The two items below are what a lane holding no VM could close.

1. StrategyServer_StampTreatyTurns 0x007898c0, read as instructions. The diplomacy
   ledger's per-turn stamp over every ordered pair of players holding a treaty, creating
   the entry on demand. Sole caller is ApplyTurnCommands, so it is a HOST step and not a
   tail phase. Three corrections to strategic-turn-internals.md 5.2, which is flagged in
   place: the relation codes are 3=ally / 2=NAP / 1=cease-fire and not the reverse (which
   combat-done-tail.md 2A already implied independently); the stamped value is Frame, not
   ModCount; and the bit is the PlyrIdx field, not the player's vector position -- the
   opposite convention from the shared-vision mask.

   Modelled in sots-engine as host phase H02. Predicted 26 leaves on the reference pair
   and 14 on pair 2 before building; measured exactly 26 and 14, 0 regressed, and +12 on
   each of three further pairs from a different game at turns 2, 15 and 16 that the model
   was never fitted to. 76 closed / 0 regressed over five pairs, 0 RNG words. The rule
   also reproduces the ledger of ten of the eleven corpus saves entry for entry.

2. Player.Status. backlog.md item 6 has it blocked on "the writer between tail 31 and the
   autosave -- watchpoint". There is no such writer. A whole-image scan for immediate
   stores to ServerPlayer+0x164 finds exactly three: ProcessTurn's encounter loop writes
   1, ResumePlaying writes 0 on load (the 4 -> 0 the determinism note recorded), and
   StrategyServer_MarkPlayerTurnEnded 0x00821a40 writes 4 from the three End Turn
   SUBMISSION paths, which run before the turn is processed. Item 6 needs one predicate,
   not a watchpoint -- and an entry probe on that function names the set directly.

   NOT written. The only two saves in the corpus with a non-zero Status agree with
   Species != 4 on all eight players, and that is eight observations on a 1-bit predicate
   that nine of the eleven saves do not exercise at all. Evaluated and reported.

Seven addresses in ghidra/addresses.d/lane-t2.json, validated to a scratch path against
the merged set (1,095 entries, no duplicate). verify/results/standalone/{report,status}
deliberately untouched: lane C3 published into them minutes before this run.
2026-09-08 14:52:44 -04:00
campaign dashboard refresh 2026-09-08 14:48:59 -04:00
findings lane T2: the treaty-turn stamp, and Player.Status's real writer 2026-09-08 14:52:44 -04:00
ghidra lane T2: the treaty-turn stamp, and Player.Status's real writer 2026-09-08 14:52:44 -04:00
guides rules 19-20: the instrument can perturb the measurement; a count cannot separate did-not-fire from fired-and-found-nothing 2026-09-08 13:56:06 -04:00
notes init commit 2026-09-07 12:31:56 -04:00
objects regenerate both headers (669 addresses); track objects/generated so the shared clone stops sitting dirty 2026-09-08 07:36:16 -04:00
scripts lane V2: vtable inversion — resolve indirect call edges image-wide 2026-09-08 12:05:05 -04:00
tools lane H: five live probes, the oracle restored, and a harness perturbation bisected to one hook 2026-09-08 13:53:36 -04:00
verify lane C3: ComputeOutput on the turn path -- the money ComputeBudget actually sums 2026-09-08 14:50:50 -04:00
.gitignore lane D: automated struct recovery from the IStreamable serializers 2026-09-08 05:51:37 -04:00
README.md guides: RE how-to for 2000s MSVC/DX9 games (98 sources); queue replay-checksum, class recovery, apitrace/TTD 2026-09-07 18:05:58 -04:00

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 (labels status/* are the kanban columns; type/*, conf/*). campaign/board.md is the editable mirror — publish with scripts/forgejo_campaign.py bootstrap (needs FORGEJO_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.