{ "entries": [ { "name": "StrategyServer_Write_ModCountFrameTags", "addr": "0x0079fb2f", "convention": "site", "prototype": "site in StrategyServer::Write (0x0079fa70, already in addresses.json with the same address -- AGREEMENT, this lane's duplicate entry was dropped). THE DECISIVE EVIDENCE FOR THE ModCount / Frame NAMING: 0x0079fb2f `lea edx,[edi+0x08]; push \"ModCount\"` and 0x0079fb40 `lea eax,[edi+0x0c]; push \"Frame\"`, with edi = this. The frame is confirmed inside the same function by 0x0079fb90 `mov eax,[edi+0x16c]` under the tag \"RNG\", which is StrategyServer_off_RNGPtr (0x168 in the S+4 frame) -- so edi is S, not S+4. Tag order after the six id lists is ModCount, Frame, GameID ([edi+0x14] at 0x0079fb4f)", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2 (lane A2 2026-09-08, instruction stream 0x0079fa70-0x0079fc70)" }, { "name": "StrategySim_off_ModCount", "offset": "0x4", "convention": "field", "prototype": "int ModCount, in the S+4 (Game::StrategySim sub-object) frame == S+0x8. THIS IS THE WIRE'S /Sim/ModCount. CORRECTION, and it matters: addresses.json's `StrategyServer_off_ModCount` puts that name on offset 0x8 of this frame (== S+0xc), which StrategyServer::Write tags \"Frame\". Lane T's `StrategyServer_off_PhaseCounter` -- 'nobody has named this one' -- is this word, and it IS ModCount. Written by an unconditional increment on ENTRY to every StrategySim command-application method (26 sites), plus once by StrategyServer::ProcessTurn's first instruction, once by OnAllCombatDone_Tail's first instruction, and once per call of the abandon/chaos check. It is a modification counter: not a turn number, not a phase counter, and not constant per turn (12-44 on measured turns)", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2 (lane A2 2026-09-08); named first by lane Z in combat-done-tail.md §7.1, independently re-derived here from StrategyServer::Write" }, { "name": "StrategySim_off_Frame", "offset": "0x8", "convention": "field", "prototype": "int Frame, in the S+4 frame == S+0xc. THIS IS THE WIRE'S /Sim/Frame -- the turn number. Incremented once per turn by StrategyServer::BeginProcessTurn 0x007d990a; stamped into node.turnResearched by TechTree::SetResearched; used as minTurn by the EVENT_NO_RESEARCH sweep; and it is the KEY the turn-record archive is written under (FinalizeTurnRecords passes S->+0xc). The entry addresses.json calls `StrategyServer_off_ModCount` is this word, and the name is wrong on it", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2 (lane A2 2026-09-08)" }, { "name": "StrategyServer_ProcessTurn_AllianceMaskPass", "addr": "0x007dc871", "convention": "site", "prototype": "site in StrategyServer::ProcessTurn, phase 4, 0x007dc871-0x007dc8c7, byte-for-byte: `for (i = 0; i < (Players.end - Players.begin) >> 2; ++i) { p = Players[i]; rec = p->+0x3d8; rec->+0x8 = 0; rec->+0x8 |= 1 << i; if (p->+0x168 != -1) rec->+0x8 |= p->+0x16c; }`. THREE separate stores to the same word (`mov [edx+8],ebx` with ebx=0, then two `or`), which is why it is an OR and not an assignment; the turn-record pointer is RELOADED from p->+0x3d8 before each. The shift is `mov edi,1; shl edi,cl` with cl = the loop counter, so the bit is the player's POSITION IN THE VECTOR and x86's 5-bit shift mask applies above 31 players. Loop guard is `test edx,0xfffffffc; jle` on the byte count", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §1 (lane A2 2026-09-08). AGREES with lane T's ServerPlayer_off_TurnRecord / _off_AllianceId / _off_AllianceMask, which are kept and not duplicated here" }, { "name": "StrategySim_ApplyTurnCommandBatch", "addr": "0x0088f9b0", "convention": "thiscall", "prototype": "void (StrategySim* this /* S+4 */, Game::TurnCommands* first, int count) // applies a run of per-player command blocks: `last = first + count*0x1b4; for (b = first; b != last; b += 0x1b4) `. The 0x1b4 stride is sizeof(Game::TurnCommands) and independently confirms lane Q's layout (27 std::list members at 0x70..0x1a8, stride 0xc, so the class ends at 0x1b4). SIX command handlers are INLINED here and each bumps ModCount once (0x0088fe0a, 0x008902fe, 0x008903b9, 0x0089046c, 0x008905c8, 0x008907bc), each followed by `lea ecx,[base+0x80]; call HandleMap::Resolve` -- which is what proves the base is the StrategySim and not the block", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2.2 (lane A2 2026-09-08)" }, { "name": "StrategyServer_ApplyAllTurnCommands", "addr": "0x0078f6a0", "convention": "thiscall", "prototype": "void (StrategyServer* this /* S frame */) // the End-Turn command flush: computes `count = (this->+0x178 - this->+0x174) / 0x1b4` (signed magic 0x964fda6d, sar 8 -- the reciprocal of 436) and calls StrategySim::ApplyTurnCommandBatch(this+4, this->+0x174, count). The `lea ecx,[esi+4]` at 0x0078f6de is a third independent sighting of the two-bases split. Called from StrategyNetworkClient::OnMessage 0x00784904, immediately before that handler calls StrategyServer::ProcessTurn at 0x0078491c", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2.2 (lane A2 2026-09-08)" }, { "name": "StrategyServer_off_TurnCommandQueue", "offset": "0x174", "convention": "field", "prototype": "std::vector in the S frame (begin @+0x174, end @+0x178), element stride 0x1b4. One block per player; the End-Turn flush applies every command in every block, and each application bumps ModCount. This is the wire's `Player..TurnCommands_v5` custom-data block in memory", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2.2 (lane A2 2026-09-08)" }, { "name": "TurnCommands_sizeof", "offset": "0x1b4", "convention": "field", "prototype": "sizeof(Game::TurnCommands) = 436, recovered from the container stride in StrategyServer::ApplyAllTurnCommands (`imul ebx,ebx,0x1b4`) and from the signed-division reciprocal 0x964fda6d/sar 8 in the same function. Independent of, and agreeing with, lane Q's field walk, whose last list member sits at 0x1a8 with stride 0xc", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2.2 (lane A2 2026-09-08); layout from findings/objects/turncommands-block.md (lane Q)" }, { "name": "StrategyNetworkClient_OnMessage", "addr": "0x00784640", "convention": "thiscall", "prototype": "void (StrategyNetworkClient* this, Message* m) // vftable 0x00a229f4 slot 6. THE END-TURN DISPATCHER: it is the only direct caller of StrategyServer::ProcessTurn (0x0078491c), of OnAllCombatDone_Tail (0x00784d07) and of StrategyServer::ApplyAllTurnCommands (0x00784904), and it loads the server with `mov ecx,[esi+0x54]` before the first two. NOTE: this class's own `this` is NOT a StrategySim -- its entity hash is at +0x84, not +0x80 -- so the three `inc [reg+4]` sites in this body (0x007850d5, 0x0078514b, 0x00785224) are NOT ModCount and are listed as unresolved rather than counted", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2.2 (lane A2 2026-09-08)" }, { "name": "StrategyNetworkClient_off_Server", "offset": "0x54", "convention": "field", "prototype": "StrategyServer* in the S frame (the base ProcessTurn receives, not S+4). Read at 0x00784901 and 0x00784919 immediately before the command flush and the turn driver", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2.2 (lane A2 2026-09-08)" }, { "name": "StrategyServer_AbandonChaosCheck", "addr": "0x007b9df0", "convention": "thiscall", "prototype": "void (StrategyServer* this /* S frame */, ServerSystem* sys, int mode, std::vector* out) // the abandon/chaos check called once per system from ProcessTurn phase 1. ITS FOURTH INSTRUCTION IS A ModCount BUMP: `inc [esi+0x8]` @0x007b9e20 with esi = this = S, so this is the only per-system ModCount writer in the turn. The phase-1 loop gate is `cmp BYTE [sys+0xc4],0; je` -- ServerSystem_off_Abdn -- so the call, and the bump, happen only for systems already flagged abandoned. Abdn is FALSE on all 28 systems of all 11 corpus saves, so this writer contributes 0 on every measured turn and is a rule-6 hypothesis for any turn where it does not", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2.3 (lane A2 2026-09-08)" }, { "name": "StrategySim_MoveFleetCommand", "addr": "0x00865780", "convention": "thiscall", "prototype": "void (StrategySim* this /* S+4 */, ...) // the fleet-move command handler; logs \"StrategySim: Fleet not found.\", \"StrategySim: Waypoint %d(id) not found.\" and \"StrategySim: (see above) cannot move fleet %d(id).\" Bumps ModCount at 0x008657aa. THE ONLY ModCount WRITER OTHER THAN THE ABANDON CHECK THAT IS DIRECT-CALL REACHABLE FROM EITHER TURN DRIVER (from OnAllCombatDone_Tail's 1369-function closure; not from ProcessTurn's 1382)", "status": "verified", "source": "findings/control-flow/alliance-mask-and-modcount.md §2.2 (lane A2 2026-09-08)" } ] }