saved-state writer under combat FUN_007d5a00's six callees, read from the instruction stream to the next function start, plus 18 helpers. Lane J named this "the real per-phase combat pipeline"; the identification of it as the most tractable target was right and the characterisation was not. It is one subsystem -- destinations, group, classify, split, execute, destroy -- and it is StarFleet retreat. Seven saved fields or containers move on this path: ship->fleet membership, StarFleet objects created and destroyed in the master list, the system fleet lists, fleet position/location/flight plan/flags, the ServerSystem presence and explored masks, the per-player PlayerView, and ServerPlayer.GTraf. Closes struct-recovery.md section 7's open "OID allocation (R2's x16)": the allocator is at 0x008b8ae0, the counter lives per network node at IDMap->+0x08 + node*0x14 + 0x10, it is pre-incremented and never issues 0, and an id is (counter << 4) | (node & 0xF). R2's x16 is the shl 4. A partial retreat mints one id per group, and that counter is almost certainly the save's NMnx tag -- labelled hypothesis, with a falsifiable prediction written down before any run. New rule: retreating from a system you had not explored marks it explored for you, writing EFlags and refreshing the PlayerView. New diplomacy rule: a system whose owner captured it on the current turn loses that owner's ceasefire cover in the hostile-presence test. RNG recomputed independently from a different root and with a different tool: 327 functions in the closure once E9 tail-call thunks are followed (the first pass missed an 8-byte jmp thunk and with it the whole id-allocator chain), zero calls to the four primitives, zero inlined MT tempering immediates, and one false-positive 0x11c stride that is StarFleet.FtMS being initialised to -1. Bound, not proof: 152 indirect call sites in 91 of the 327, four of them on the main line and flagged for the vtable lane. Corrects my own first reading of the fleet-creation call: a ret-N tail-call thunk in the middle of an argument list makes three pushes look like they belong to the wrong call. Checking ret N against the push count catches it. The honest limit stands: none of this has ever executed under an instrument. combat-resolver.md section 10.3's workload now needs a second condition -- the battle must produce a retreat, or all six phases are no-ops. |
||
|---|---|---|
| .. | ||
| lane-a.json | ||
| lane-b5.json | ||
| lane-i.json | ||
| lane-j.json | ||
| lane-k.json | ||
| lane-o.json | ||
| lane-q.json | ||
| lane-t.json | ||
| lane-u.json | ||
| lane-w.json | ||
| lane-z.json | ||
| README.md | ||
Per-lane address fragments
addresses.json is a single shared file. When several lanes run concurrently they edit the
same lines, and three times on 2026-09-08 one lane's git add swept another's in-flight
entries into the wrong commit. Nothing was lost, but authorship and atomicity were.
A lane may instead drop its own file here:
{ "entries": [ { "name": "...", "addr": "0x...", "convention": "...",
"prototype": "...", "status": "verified", "source": "findings/..." } ] }
Name it after the lane (lane-d.json). tools/gen_addresses.py merges every fragment in
sorted order after addresses.json. A duplicate name across files is a hard error, not
last-wins — two lanes disagreeing about an address is exactly the thing we must not paper over.
The integrator folds fragments back into addresses.json once the lane's work is merged.