sots-re/ghidra/addresses.d/lane-e3.json
alex 58c2cd14b4 lane E3: ten addresses for the visibility record, and the standalone's new distance
The NVE writer 0x00756300 and its four siblings, `ltis`'s writer 0x00743ec0, the
encounter-placement routine whose unserialised field feeds Eid, the tail phase that
calls the writer, and the resolution of an indirect edge lane B5 left open --
ServerSystem primary vftable 0x00a2044c slot 7 is 0x007480b0, and it writes only a
runtime mask, so it never reaches the wire.

None of the ten collides with an address already in the DB (checked against all 714
addressed entries across addresses.json and every fragment); gen_addresses.py
validated to a scratch path at 1019 entries, no duplicate names.

Standalone report regenerated from the lane worktree:
  turn1 -> turn2   209 -> 158   closed 51, regressed 0
  turn2 -> turn3   108 ->  87   closed 21, regressed 0

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ARBgSooAfokKUy6wKUKEyZ
2026-09-08 13:38:57 -04:00

84 lines
6.8 KiB
JSON

{
"entries": [
{
"name": "ServerSystem_RecordObservation",
"addr": "0x00756300",
"convention": "thiscall",
"prototype": "void (ServerSystem* this, ServerPlayer* p, int encounterId) // 75 B, ret 8. THE NVE WRITER. if (!p) return; s = (int16)this->owner(+0x10)->Frame(+0x8); rec = NVE_map_at(&this->NVE(+0x284), &p->PlyrIdx(+0x28)); rec[0] = (s<<16)|s; rec[1] = encounterId. The map value is 8 bytes at node+0x10: an UNSERIALISED int16 touch stamp at +0, the saved ETS int16 at +2, the saved Eid int32 at +4 -- so ETS and the touch stamp are both set to the frame here, and only the writer at 0x007536a0 makes them differ. Sole caller is the tail's PlayerView-rebuild phase 0x007cf560, under the gate (AFlags >> PlyrIdx) & 1",
"status": "mapped",
"source": "findings/subsystems/system-visibility-record.md (lane E3 2026-09-08); closes 32+8 leaves in sots-engine on the reference pairs"
},
{
"name": "ServerSystem_CopyObservationTo",
"addr": "0x007536a0",
"convention": "thiscall",
"prototype": "void (ServerSystem* this, ServerPlayer* p, NveValue* src) // 70 B, ret 8. Intel sharing. rec = NVE_map_at(&this->NVE, &p->PlyrIdx(+0x28)); rec[0] = (hi16(src[0]) << 16) | (int16)this->owner(+0x10)->Frame(+0x8); rec[1] = src[1]. i.e. the receiver gets the DONOR's sighting turn (ETS) and encounter id unchanged, and only the unserialised touch stamp becomes the current frame. Never executed by any save in the corpus: no save has two players in an alliance",
"status": "mapped",
"source": "findings/subsystems/system-visibility-record.md (lane E3 2026-09-08)"
},
{
"name": "ServerSystem_ShareObservation",
"addr": "0x00754d90",
"convention": "cdecl",
"prototype": "bool (ServerSystem* sys, ServerPlayer* from, ServerPlayer* to) // 96 B. Null-guards all three and from != to; a = FindObservation(from); b = FindObservation(to); if (a && (!b || b->ETS(+2) < a->ETS(+2))) { CopyObservationTo(to, a); return true; } return false. NEWER SIGHTING WINS, compared as a signed int16",
"status": "mapped",
"source": "findings/subsystems/system-visibility-record.md (lane E3 2026-09-08)"
},
{
"name": "ServerSystem_FindObservation",
"addr": "0x0074d360",
"convention": "thiscall",
"prototype": "NveValue* (ServerSystem* this, ServerPlayer* p) // 58 B, ret 4. Map find on p->PlyrIdx(+0x28); returns node+0x10 (the 8-byte value) or null when the search ended at this->NVE head (+0x284)",
"status": "mapped",
"source": "findings/subsystems/system-visibility-record.md (lane E3 2026-09-08)"
},
{
"name": "ServerSystem_LastSeenEncounterId",
"addr": "0x0074f830",
"convention": "thiscall",
"prototype": "int (ServerSystem* this, ServerPlayer* p) // 64 B, ret 4. Same map find; returns node+0x14 (Eid) or -1. The extra `!= -0x10` guard is the null-node case reached through node+0x10",
"status": "mapped",
"source": "findings/subsystems/system-visibility-record.md (lane E3 2026-09-08)"
},
{
"name": "ServerSystem_IsVisibleTo",
"addr": "0x00743fb0",
"convention": "thiscall",
"prototype": "bool (ServerSystem* this, ServerPlayer* p) // 34 B, ret 4. return ((1 << (p->PlyrIdx(+0x28) & 0x1f)) & this->AFlags(+0xd4)) != 0. THE gate on the observation record, on the explored sweep and on the PlayerView rebuild -- AFlags, the DERIVED non-sticky union, not VFlags. 19 callers",
"status": "verified",
"source": "instruction-verified body; combat-retreat-pipeline.md already had AFlags = FFlags|GFlags|isOwner"
},
{
"name": "ServerSystem_UpdateLastObservedTurn",
"addr": "0x00743ec0",
"convention": "fastcall",
"prototype": "void (ServerSystem* this) // 41 B, WHOLE BODY. if (this->AFlags(+0xd4) != 0) this->ltis(+0x2c8) = this->owner(+0x10)->Frame(+0x8). This is `ltis`'s writer, which board.md recorded as unnamed; it is driver phase 29 (0x007dcbd6, per system). TShn's writer is still unnamed and is demonstrably a DIFFERENT rule: Spica in turn1-state has AFlags == 0 and its TShn moves anyway",
"status": "mapped",
"source": "findings/subsystems/system-visibility-record.md (lane E3 2026-09-08); closes 8 leaves per pair in sots-engine"
},
{
"name": "ServerSystem_OnExploredChanged",
"addr": "0x007480b0",
"convention": "thiscall",
"prototype": "void (ServerSystem* this, ServerPlayer* p, bool wasSet, bool on) // 71 B, WHOLE BODY. Game::ServerSystem primary vftable 0x00a2044c SLOT 7 -- this RESOLVES the indirect edge lane B5 flagged in SetExploredBy's tail (vft[0x1c]). if (!wasSet && on && this->owner(+0x10)->Frame(+0x8) > 1) { FUN_00747a20(p->PlyrIdx(+0x28), 1); if (p->PlyrIdx < 0xf) this->+0x2a4 |= 1 << (PlyrIdx & 0x1f); } -- +0x2a4 sits past NVs and is NOT in the serialised table, so this edge writes no save state. Note the Frame > 1 guard: turn 1 is special-cased",
"status": "mapped",
"source": "tools/vtable_map.py vt 0xa2044c + decompile (lane E3 2026-09-08); resolves an open item in ghidra/addresses.d/lane-b5.json"
},
{
"name": "StarSystem_PlaceEncounter",
"addr": "0x007887c0",
"convention": "cdecl",
"prototype": "bool (StarSystem* sys, int encounterId) // 129 B. Refuses unless the system is unowned (FUN_007437e0 == 0), has no planets, sys->+0x184 == -1 and two further tests pass; then sys->+0x184 = encounterId and ORs a mask from the encounter def into sys->+0x19c. sys->+0x184 is the field ServerSystem_RecordObservation copies into Eid. It is constructed to -1 (StarSystem ctor 0x00752ea0, member index 0x61) and IS NOT ON THE WIRE, so a reimplementation has to recover it from the encounter fleet's FtEnc -- which agrees on all six encounter fleets in the corpus and which no save can separate from the real field",
"status": "mapped",
"source": "findings/subsystems/system-visibility-record.md (lane E3 2026-09-08)"
},
{
"name": "StrategyServer_RebuildPlayerViews",
"addr": "0x007cf560",
"convention": "fastcall",
"prototype": "void (StrategyServer* S) // 948 B, tail phase 17. Four passes: (1) walk the per-(system, player) view tree at S+0x228 and drop entries whose player can no longer see the system, then clear the tree and reset S+0x22c = 0; (2) per player x per system, if IsVisibleTo, FUN_0075f550; (3) per player x per system, if IsVisibleTo, ServerSystem_RecordObservation(sys, player, sys->+0x184) -- byte-decoded at 0x007cf7a7..0x007cf7ce, this is the ONLY caller of the NVE writer outside intel sharing; (4) per system x per player, if IsExploredBy and a colony exists, build a PlayerView via 0x00755ab0/0x007561d0 and apply it. Draw-free",
"status": "mapped",
"source": "findings/subsystems/system-visibility-record.md (lane E3 2026-09-08)"
}
]
}