sync header after ID merge

This commit is contained in:
alex 2026-09-08 20:27:40 -04:00
parent bd48e80e6e
commit e2296c5270

View file

@ -1,5 +1,5 @@
// GENERATED — do not edit. Facts about Sword of the Stars.exe (GOG 1.8.1). // GENERATED — do not edit. Facts about Sword of the Stars.exe (GOG 1.8.1).
// Source: sots-re ghidra/addresses.json @ 975c19a, generated 2026-09-08 by tools/gen_addresses.py // Source: sots-re ghidra/addresses.json @ c60ee36, generated 2026-09-08 by tools/gen_addresses.py
// Runtime address = (uintptr_t)GetModuleHandle(NULL) + RVA (the exe is ASLR-relocated). // Runtime address = (uintptr_t)GetModuleHandle(NULL) + RVA (the exe is ASLR-relocated).
#pragma once #pragma once
#include <cstdint> #include <cstdint>
@ -2135,6 +2135,18 @@ constexpr uint32_t TurnCommands_WriteColonizeList = 0x00422960;
constexpr uint32_t StrategySim_ApplyTurnCommandBatch_GateLoopB = 0x004907b1; constexpr uint32_t StrategySim_ApplyTurnCommandBatch_GateLoopB = 0x004907b1;
// label the THIRD and last per-player gate loop inside StrategySim::ApplyTurnCommandBatch. `esi = block+0x24`; it tests the group-4 gate at +0x2c and applies its {bool, int} payload through 0x00821b90. It is the final step of the whole batch. Together with the loop-A head at 0x0088fdb0 and the loop-B head at 0x008907b1, and the six inlined ModCount bump sites, this gives nine positions of the thirty-step apply schedule an address-monotonicity check -- the only part of the sequence that can be re-derived rather than inherited from the read of the `add edi, imm` chain [verified] // label the THIRD and last per-player gate loop inside StrategySim::ApplyTurnCommandBatch. `esi = block+0x24`; it tests the group-4 gate at +0x2c and applies its {bool, int} payload through 0x00821b90. It is the final step of the whole batch. Together with the loop-A head at 0x0088fdb0 and the loop-B head at 0x008907b1, and the six inlined ModCount bump sites, this gives nine positions of the thirty-step apply schedule an address-monotonicity check -- the only part of the sequence that can be re-derived rather than inherited from the read of the `add edi, imm` chain [verified]
constexpr uint32_t StrategySim_ApplyTurnCommandBatch_GateLoopC = 0x0049080a; constexpr uint32_t StrategySim_ApplyTurnCommandBatch_GateLoopC = 0x0049080a;
// custom int (ECX: StrategyAIAgent* agent, EDX: SectionContext parts[3], STACK: DesignRequest* req, STACK: char costOnly) /* ECX+EDX in registers, TWO stack arguments, and the CALLER cleans them (`add esp,0x8` at 0x006ae719) -- neither cdecl nor MSVC __fastcall, but the private convention MSVC gives a static function whose address never escapes. Returns 0 on success and 1..8 for eight distinct bail-outs: 1 over budget, 2 no hull candidate, 3 no command section, 4 no engine section, 5/6/7 a forced-tech lookup failed for request-flag bit 4/8/0x10, 8 no weapon matched a bank. `req` = {int hullSize; float budget; int role; uint flags}. `parts` is the same 0x124-stride three-section array lane D2 found on the other side of the pipeline at Game::ShipDesign::AggregateSectionStats: +0 ShipSectionDef*, +4.. one weapon id per weapon BANK, +0xcc the bank count (min(hull banks, 0x32)). `costOnly` non-zero returns right after pricing, having already drawn at sites A/B/C -- which is why one AI design request can cost two composer calls */ [verified]
constexpr uint32_t AIComposeShipBlueprint = 0x002ad700;
// custom void (ECX: ?, EDX: StrategyAIAgent* agent, STACK: ..., DesignRequest* req, char costOnly) /* the composer's ONLY caller. Builds a list of 1..3 hull sizes from req.hullSize and request-flag bits 0 and 1 (bit 0 adds size-1, bit 1 adds size+1 when size<2), clears both bits, then calls AIComposeShipBlueprint once per size and BREAKS ON THE FIRST SUCCESS. So one design request costs 1..3 composer calls, and every failed attempt has already spent the RNG words it reached before failing. Three call sites: 0x006cdaa6 and 0x006cdb1c in 0x006cda40 (the real design pass) and 0x006b7ecb in 0x006b7e40, which passes costOnly=1 */ [verified]
constexpr uint32_t AIComposeShipDesign = 0x002ae620;
// custom void* (EAX: int count, STACK: void** array) /* 0x1f bytes whole: `if (!count) return 0; return array[cl_RandRange(0, count-1)];`. The count arrives in EAX. This is a LIVE DRAW SITE that lane PAR's 23-row table does not list -- PAR measured it live at return address 0x00691ea0 (2 calls, 2 words on turn 1) without adding it to the static inventory, so the AI turn has 22 live sites, not 21. The composer calls it once, at 0x006ada61, to pick the command section */ [verified]
constexpr uint32_t AIPickRandomElement = 0x00291e90;
// offset size -- one entry of the three-section design context array the composer fills and Game::ShipDesign::AggregateSectionStats 0x00826af0 consumes. +0x000 ShipSectionDef* (null = empty slot), +0x004..+0x0cb up to 0x32 weapon ids, ONE PER BANK, which is exactly the DGbnk2 list the design record carries on the wire (SHIP_DESIGN_RULES B1: one weapon per bank{} block, in file order); +0x0cc the bank count = min((def+0x320 - def+0x31c)/0x30, 0x32); +0x0d0..+0x11f up to 20 candidate weapon ids gathered for that section; +0x120 that candidate count, capped at 20 -- the cap the string "AIComposeShipBlueprint: SectionBlueprint::MAX_OPTIONS" names. Slot order in memory is mission, command, engine (verify/design-rules/SHIP_DESIGN_RULES.md 1), NOT the on-disk order. Live: on turn 1 a Human destroyer design gives bank counts 3 / 1 / 2 for DEExtendedRange / DECommand / DEFission [verified]
constexpr uint32_t AIShipSectionContext_stride = 0x00000124;
// offset std::vector<Bank> begin -- weapon-bank descriptors on a Game::ShipSectionDef, stride 0x30, end pointer at +0x320. Bank+0x00 = turretclass index (0 = `standard`, the class 1,533 of the 3,721 shipped banks carry; 0xc and 0x17 are two others the composer's large-bank pass also accepts), Bank+0x04 = turretsize index (1 = `small`, 3 = `large`). The composer's only loop-carried draw fires once per (class 0, size 1) bank -- a small standard bank -- and its job is to overwrite a fraction of them with a point-defence weapon [verified]
constexpr uint32_t ShipSectionDef_off_Banks = 0x0000031c;
// offset Mars::String -- the section's file name on a Game::ShipSectionDef; capacity word at +0x1c8, so the payload is the inline buffer when capacity < 0x10 and *(char**)(def+0x1b4) otherwise. The composer compares it case-insensitively against "DEPointDefence" and "CRPointDefence" at 0x006ae4e6/0x006ae4fd: a section whose name matches gets a point-defence weapon in EVERY qualifying bank instead of every D'-th one [verified]
constexpr uint32_t ShipSectionDef_off_Name = 0x000001b4;
// thiscall int (Game::SVScriptObject* this, int evt, void* arg) // the script-object event bus. Calls this->vft[0x10](evt, arg) -- the GENERIC handler every object sees -- then `cmp evt,0x20; ja done; jmp dword [evt*4 + SVScriptObject_EventSlotJumpTable]`, which dispatches to ONE event-specific vtable slot with the argument shape that event carries. Every hand-written `vft[0x10](id,0); vft[slot]()` pair in the two turn drivers is this same two-step done on the root object [verified] // thiscall int (Game::SVScriptObject* this, int evt, void* arg) // the script-object event bus. Calls this->vft[0x10](evt, arg) -- the GENERIC handler every object sees -- then `cmp evt,0x20; ja done; jmp dword [evt*4 + SVScriptObject_EventSlotJumpTable]`, which dispatches to ONE event-specific vtable slot with the argument shape that event carries. Every hand-written `vft[0x10](id,0); vft[slot]()` pair in the two turn drivers is this same two-step done on the root object [verified]
constexpr uint32_t SVScriptObject_DispatchEvent = 0x003a60d0; constexpr uint32_t SVScriptObject_DispatchEvent = 0x003a60d0;
// data void* [33] // evt (0..0x20) -> the vtable slot SVScriptObject_DispatchEvent calls. Slot byte offsets in evt order: 0x14 0x18 0x1c 0x20 0x24 0x28 0x2c 0x30 0x34 0x38 0x3c 0x40 0x44 0x48 0x4c 0x50 0x54 0x58 0x5c 0x60 0x64 0x6c 0x70 0x74 0x68 0x7c 0x80 0x84 0x78 0x88 0x8c 0x90 0x94. Note 0x15->+0x6c, 0x16->+0x70, 0x17->+0x74, 0x18->+0x68 and 0x1c->+0x78 are NOT in slot order [verified] // data void* [33] // evt (0..0x20) -> the vtable slot SVScriptObject_DispatchEvent calls. Slot byte offsets in evt order: 0x14 0x18 0x1c 0x20 0x24 0x28 0x2c 0x30 0x34 0x38 0x3c 0x40 0x44 0x48 0x4c 0x50 0x54 0x58 0x5c 0x60 0x64 0x6c 0x70 0x74 0x68 0x7c 0x80 0x84 0x78 0x88 0x8c 0x90 0x94. Note 0x15->+0x6c, 0x16->+0x70, 0x17->+0x74, 0x18->+0x68 and 0x1c->+0x78 are NOT in slot order [verified]