Sword of the Stars (2006) reverse-engineering worklog. Infra docs live in trikilli services/re-lab.md.
Find a file
alex 232397aa12 lane AI2: the AI's task selection loop, the priority table, and the order-method -> TurnCommands map
The strategic AI does not search or score. Once a turn (Process Turn phase 20, 0x006cf630) it
rebuilds a candidate task list -- which families it builds at all is a switch on the player's
SPECIES, four arms, and the NPC arm builds nothing -- sorts it by a per-task-type priority, and
walks it twice calling each task's Execute(agent, pass) with pass 0 then 1.

Closed from lane AI1's open list:
  * the selection loop (its item 2) and the whole ordering policy: a 33-entry priority table at
    0x00691f00 plus five named overrides;
  * IAITask's unnamed pure virtuals (item 1) -- seven, not eight: GetTypeId, GetTargetA/B,
    Execute, IsFinished, GetTypeName, Describe;
  * the order-method -> list mapping (item 5): all 27 of lane Q's lists and all six prologue
    gates now have a named producer, and list 14 -- lane Q's "observed but not understood" --
    is the AI's fleet order, two elements per fleet;
  * g_CurrentClientIndex (item 6): a stack pointer with exactly two writers, pushed around the
    whole AI turn by StrategyAIAgent::OnEvent;
  * the think-time throttle (item 7): AIProcessMinTime is a trailing Sleep, not a compute
    budget. Every pending AI player's turn runs back-to-back inside one Update. The clean
    "all AI orders in before the human's End Turn" ordering HOLDS, and Rung B is not at risk;
  * Broadcast -> OnAIPacket, read to the call -- AI1's one inferred hop is now verified.

Corrections: 31 concrete task classes, not 34; 26 order methods, not 21; seven pure virtuals,
not eight. lane-ai1.json's Broadcast and g_CurrentClientIndex entries upgraded in place.

Open and said so: slots 11/12/13 unnamed, the nine goal tasks' bodies unread, the two-pass
meaning inferred, the StrategyApp pending-AI enqueue site not found, nothing run under an
instrument. Four predictions in section 9, P1 being a ModCount prediction.

ghidra/addresses.d/lane-ai2.json: 25 entries, 1031 -> 1056, no duplicates.
2026-09-08 14:43:41 -04:00
campaign board: VM140 holder = lane W2 2026-09-08 14:14:49 -04:00
findings lane AI2: the AI's task selection loop, the priority table, and the order-method -> TurnCommands map 2026-09-08 14:43:41 -04:00
ghidra lane AI2: the AI's task selection loop, the priority table, and the order-method -> TurnCommands map 2026-09-08 14:43:41 -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 H: five live probes, the oracle restored, and a harness perturbation bisected to one hook 2026-09-08 13:53:36 -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.