sync generated header (1138 entries) before G3 merge
This commit is contained in:
parent
5d01c7c7de
commit
6d5713ecc4
1 changed files with 37 additions and 1 deletions
|
|
@ -1,5 +1,5 @@
|
|||
// GENERATED — do not edit. Facts about Sword of the Stars.exe (GOG 1.8.1).
|
||||
// Source: sots-re ghidra/addresses.json @ b77a611, generated 2026-09-08 by tools/gen_addresses.py
|
||||
// Source: sots-re ghidra/addresses.json @ d4f9404, generated 2026-09-08 by tools/gen_addresses.py
|
||||
// Runtime address = (uintptr_t)GetModuleHandle(NULL) + RVA (the exe is ASLR-relocated).
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
|
@ -1657,6 +1657,8 @@ constexpr uint32_t ServerSystem_OnExploredChanged = 0x003480b0;
|
|||
constexpr uint32_t StarSystem_PlaceEncounter = 0x003887c0;
|
||||
// fastcall 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 [mapped]
|
||||
constexpr uint32_t StrategyServer_RebuildPlayerViews = 0x003cf560;
|
||||
// none the three-test gate that guards EVENT_NO_RESEARCH; the post itself is ServerPlayer_ProcessTurn_PostEventNoResearch 0x0089168c. Read byte for byte (ReVa read-memory 0x00891600+160, decoded by hand): cmp [esi+0x294],ebx / jne past the whole block -> test 1, ResT == NULL. Then a 12-byte stack vector is zeroed at [ebp-0x28] and TechTree::CollectResearchedTechs 0x00584e50 is called as ecx = this->TechTree(+0xf4), push 1 (sort), push 0x7fffffff (maxTurn), push [[esi+8]+8] (the SERVER TURN -- the same word the post below hands PostEvent as its turn argument), push &out; then cmp [ebp-0x28],[ebp-0x24] / jne past -> test 2, THE LIST CAME BACK EMPTY, i.e. NO TECH WAS RESEARCHED ON THIS TURN OR LATER. Then ecx = this->TechTree again, call TechTree::FindFirstAvailableTech 0x0057da90, test eax,eax / setne al / cmp al,bl / je past -> test 3, at least one node is in state 2. CORRECTION to the note on ServerPlayer_ProcessTurn_PostEventNoResearch, which reads 0x00584e50 as a ListAvailableTechs and the gate as 'no tech is available': it is TechTree::CollectResearchedTechs (lane T's reading, confirmed here from the call site's argument order) and the gate is about what was RESEARCHED, not about what is available -- test 3 is the availability half. The turn argument is passed as CollectResearchedTechs' minTurn, so the range is [turn, INT_MAX] over node->turnResearched(+0x24) [mapped]
|
||||
constexpr uint32_t ServerPlayer_ProcessTurn_NoResearchGate = 0x0049162a;
|
||||
// cdecl void (const char* gamename) /* GameSpy SDK gsAvailable. sprintf("%s.available.gamespy.com"), inet_addr/gethostbyname, UDP socket, sendto port 27900 (htons 0x6cfc) with '\x09\0\0\0\0' + gamename + NUL, len = strlen(gamename)+6. Overridable hostname buffer at 0x00b085b0. Leaves socket = -1 on DNS failure. */ [verified]
|
||||
constexpr uint32_t GameSpy_GSIStartAvailableCheck = 0x0000a060;
|
||||
// cdecl int (void) /* returns 0=waiting 1=available 2=unavailable 3=temporarily-unavailable. Socket==-1 (start failed) => returns 1. Retries once after 2000 ms then returns 1. */ [verified]
|
||||
|
|
@ -1743,6 +1745,40 @@ constexpr uint32_t g_LanScanPortRange = 0x00713c70;
|
|||
constexpr uint32_t g_GameSpyAvailableHostOverride = 0x007085b0;
|
||||
// data const char* /* when non-NULL, replaces "<gamename>.ms<N>.gamespy.com" in SBServerListConnect */ [mapped]
|
||||
constexpr uint32_t g_GameSpyMasterHostOverride = 0x00709440;
|
||||
// thiscall void (ServerSystem* sys) // plain `ret`, REAL END 0x00754b59 -- the body is a loop over group types 0,1,2 whose back edge is at 0x00754b2e (`inc esi; cmp esi,3; jl 0x7543e9`) and lies outside every decompiler `if`, so the function reads as straight-line code if you stop at the first `ret`. Returns immediately when the system has no owner. Per group type: skip when Population::TotalOfType(Pop2, t) <= 0, then skip unless t == 1 -- so only CIVILIANS grow here. Per species: delta = PopGrowthDelta(1, sp); cur = Count(Pop2,1,sp) + Count(pbon2,1,sp); cap = MaxPopGeneric(1, sp, PID, NULL); soft = CivilianSettleLimit(sp); limit = soft < cap ? soft : cap (and soft < cap with cur+delta > soft raises a per-species settle flag); applied = min(delta, limit - cur); haltv[1] with applied > 0 zeroes both. The SYSTEM TOTAL is then clamped into [-50,000,000 (a literal here), POPTYPE[1]+0x08 = 20,000,000] and, when the clamp bit, every entry of the clamp's own sign is rescaled by trunc(applied x (clamped / total)) with NO renormalisation. Write-back is Population::SetCount(Pop2, 1, sp, Count(Pop2,1,sp) + applied) -- note the headroom counted pbon2 and the write does not. THE 20,000,000 CLAMP IS WHAT DECIDES THE VALUE on both reference pairs: the uncapped delta is 7.5x it and the capacity headroom 25x it [verified]
|
||||
constexpr uint32_t ServerSystem_GrowCivilianPops_G3 = 0x00354220;
|
||||
// thiscall int64 (ServerSystem* sys, int species) // `ret 4`, ends 0x0074aa2d. Returns 0 without an owner. Otherwise min( MaxPopGeneric(1, sp, PID, &StrategyServer::IdealSuit(server, sp)) , Population::Count(sys->dcs /*+0x104*/, 1, sp) ). The first term is the capacity the colony would have if the planet were perfectly suited; the second is the system's own `dcs` Population, which is on the wire. On Gamma Cephei `dcs` = 1e9 and it is the binding limit, not either capacity [verified]
|
||||
constexpr uint32_t ServerSystem_CivilianSettleLimit = 0x0034a9a0;
|
||||
// thiscall int64 (ServerSystem* sys, int groupType, int species, ServerPlayer* p, float* suitOverride) // `ret 0x10`, REAL END 0x0074a6cd -- 0x0074a6d0 is a DIFFERENT function (lane N and E1 both cite 0x0074a6d0 for the capacity-surplus pair; that is the next one along, not this). Returns 0 when species == 4; when the OWNER species' SpeciesDef+0x168[groupType] is not > 0 (which is why Zuul have no civilians); when groupType != 0 and the owner is RebAI; when groupType == 1 and bit 3 of ServerPlayer+0x348[species] is clear; and when groupType == 2 and 0x0082bdf0(p, species) is false. Otherwise ftoi64( (int64)Size x 1e8 x [ hazard x (POPTYPE[t]+0x20 x SpeciesDef(sp)+0x168[t] x (crossSpecies ? SpeciesDef(sp)+0x174[t] : 1)) ] ) via 0x00535eb0, plus the arcology flat bonus 0x0080dd30(p, t), then clamped to the int64 at POPTYPE[t]+0x28 -- see PopTypeTableStaticInit, that clamp is always a no-op -- and finally, for groupType 0 ONLY, scaled by INDSYS_IMPERIAL_POPULATION_MOD when the owner species is 4 [verified]
|
||||
constexpr uint32_t ServerSystem_MaxPopGeneric_G3 = 0x0034a4a0;
|
||||
// thiscall float (SpeciesDef* d, int groupType) // `ret 4`, 15 bytes. Returns d->float[0x168 + groupType*4]. The per-species, per-population-group capacity factor -- a DATA FILE value. Its imperial entry for Human is pinned at exactly 1.0 by the corpus (Gamma Cephei's pbon never drains and its Pop never shrinks, which bracket the imperial capacity at Size x 1e8); the civilian entry is bounded below at 0.27 by the observed growth and is otherwise unmeasured [verified]
|
||||
constexpr uint32_t SpeciesDef_GroupCapacityFactor = 0x0013bb00;
|
||||
// thiscall float (SpeciesDef* d, int groupType) // `ret 4`, 15 bytes. Returns d->float[0x174 + groupType*4]; applied by MaxPopGeneric only when the system owner's species differs from the population species and is not 4 [verified]
|
||||
constexpr uint32_t SpeciesDef_GroupCrossSpeciesMod = 0x0013bb20;
|
||||
// thiscall bool (SpeciesDef* d, int groupType) // `ret 4`. Returns `0.0 < d->float[0x168 + groupType*4]` -- the SAME array SpeciesDef_GroupCapacityFactor reads, so 'this species has this population group' and 'its capacity factor is positive' are one fact. MaxPopGeneric asks it about the system OWNER's species, not the population's [verified]
|
||||
constexpr uint32_t SpeciesDef_HasPopulationGroup = 0x0013bb40;
|
||||
// cdecl float (ServerPlayer* p, int species, float suit) // ends 0x00536f8b. Returns 20.0 and logs when p is null; 0.0 when p->RebAI (+0xfc) -- the 'accommodated' case; otherwise min( float32(|float32(StrategyServer::IdealSuit(p->server /*+0x8*/, species) - clamp(suit, 0, 20))|) , p->SuitTol /*+0xb4*/ ). The ideal is the SERVER's per-species baseline (the save's ISsu array), NOT the player's own IdealSuit field [verified]
|
||||
constexpr uint32_t PopGrowthSuitabilityDistance = 0x00136eb0;
|
||||
// cdecl int64 (ServerPlayer* p, int groupType, int species, float suit, float factor, int64 pop) // `add esp,0x1c`, 7 dwords of arguments, ends 0x005371ca. Returns 0 unless pop > 0; g = PopGrowthFraction(p, groupType, species, suit, factor); returns 0 when g == 0 (an fucomp against zero, so a NaN g also proceeds); d = ftoi64(g x pop); returns d, or exactly 1 when d == 0 and g is strictly positive, or 0 when d == 0 and g is negative [verified]
|
||||
constexpr uint32_t PopGrowthDeltaHelper = 0x00137140;
|
||||
// cdecl void () // the CRT static initialiser for the population-type table at 0x00b104e8, and THE ONLY WRITER of the group-ceiling field. It sets every row's +0x28 to 0xffffffff and +0x2c to 0x7fffffff -- the int64 INT64_MAX -- along with +0x00/+0x04/+0x08/+0x0c to -1/1.0/-1/-1 and the float columns to 1.0. InitPopTypeTable 0x00535ca0 runs later and overwrites +0x00 through +0x20 but NEVER touches +0x24/+0x28/+0x2c. So MaxPopGeneric's group-ceiling clamp is present, always enabled, and always a no-op; a reader who opens only InitPopTypeTable sees zero there and would cap every carrying capacity in the game at nothing [verified]
|
||||
constexpr uint32_t PopTypeTableStaticInit = 0x005abe20;
|
||||
// thiscall int (StarShip* sh, bool useAllowance) // `ret 4`, REAL END 0x008151b7 (0x008151ba..0x008151bf is int3). max(0, design->+0xcc - (sh->ConCap /*+0x68*/ + (useAllowance ? design->+0xd0 : 0))). No floating point, no clamp but the floor at zero. Its only caller, RepairShipsInOrbit, always passes 1. UNEXERCISED on the corpus, and that is a measurement rather than an absence: the independent colony's fleet sits over Koa'Vo on both reference pairs and that player's Sav closes exactly with the demand taken as zero [verified]
|
||||
constexpr uint32_t Ship_RepairCost_G3 = 0x00415180;
|
||||
// thiscall void (StarShip* sh, int points) // `ret 4`, ends 0x00815221. Does NOTHING unless the ship's cached role word (+0x18, not on the wire) carries bit 0x400000 -- a different bit from the one RepairShipsInOrbit's candidate filter tests, so a ship can be charged points that never reach it. Otherwise sh->ConCap += max(points, 0) and then ConCap = min(max(ConCap, 0), design->+0xcc). THIS IS WHAT NAMES THE TWO FIELDS: ConCap is the construction invested in the hull so far -- not a per-turn capacity, despite the save-format name -- and design+0xcc is its ceiling [verified]
|
||||
constexpr uint32_t Ship_ApplyRepair_G3 = 0x004151c0;
|
||||
// cdecl-through-register int (ServerPlayer* owner) /* the system arrives in EBX */ // ends 0x0074615a. CORRECTION to output-turn-path.md, which names this SystemRepairDemandForOwner: it is NOT a repair function. It walks the fleets at the system through the system's own vtable slots 2 and 3, skips a fleet whose owner is not the argument or whose +0x78 byte is clear, and sums 0x0081f8c0 over each ship -- and 0x0081f8c0 gates on the design's CARRIED-POPULATION bit (design->+0xb8 & 0x04000000) and computes GroupIncome over the ship's Population at ship+0x9c. So ComputeOutput's out[6] is the income of population carried in slaver/colony hulls in orbit, which is a slot the engine's BudgetInputs already has, and it feeds no save leaf [verified]
|
||||
constexpr uint32_t ServerSystem_ShipCarriedPopIncome = 0x003460b0;
|
||||
// thiscall int (StarShip* sh) // returns 0 unless design->+0xb8 & 0x04000000 (the carried-population bit lane B6 named); otherwise sums GroupIncome over the ship's `hsp` Population at ship+0x9c for group types 0 and 1. Body read to the second GroupIncome call only [unverified]
|
||||
constexpr uint32_t ShipCarriedPopIncomePerShip = 0x0041f8c0;
|
||||
// data double 0.009999999776482582 = (double)0.01f -- the savings-interest multiplier ComputeBudget uses at 0x008631ce, then truncated by _ftol2. It is a WIDENED FLOAT, not the exact decimal, and the difference is not cosmetic: a treasury of exactly 50,000 earns 499, not 500. That one money was the whole residual on the human's Sav after civilian growth landed [verified]
|
||||
constexpr uint32_t g_SavingsInterestRate = 0x005e31c0;
|
||||
// data double 0.15000000596046448 = (double)0.15f -- the debt-interest multiplier ComputeBudget uses at 0x008631b0. The same constant lane E1 already carries, negated, as the bankruptcy-elimination divisor [verified]
|
||||
constexpr uint32_t g_DebtInterestRate = 0x005ed188;
|
||||
// data float 1.5 -- the per-call growth factor PopGrowthDelta 0x00748100 substitutes for 1.0 when the system's GFlags (+0xdc) carries the owner's PlyrIdx bit. It is a BONUS, not a penalty. UNEXERCISED: GFlags is 0 for the growing player on every corpus system [verified]
|
||||
constexpr uint32_t g_FlaggedSystemGrowthFactor = 0x0061b000;
|
||||
// data float 0.25 -- POPTYPE[1]+0x04, the civilian growth column, read out of InitPopTypeTable's six-register fxch rotation. Independently re-derived this lane; lane N's whole table is reproduced (imperial +0x04 = 1.0 from 0x009e2ea0's neighbours, civilian +0x10/+0x14 = 0.33f from 0x009f8d48, civilian +0x1c = 0.5, civilian +0x20 = 2.0 from 0x009e5840) [verified]
|
||||
constexpr uint32_t g_PopTypeCivilianGrowthMod = 0x005e5ac0;
|
||||
// thiscall int (void* this, int, int) // the ONE callee through which Game::ServerSpyManager vftable 0x00a3073c slot 13 (0x008877b0) reaches the strategic generator. Exactly ONE incoming reference in the image: an unconditional call at 0x00887af2 inside that slot. Real body 0x008408e0..0x00840a59, 370 bytes. Contains three of lane V2's eight draw sites -- Chance 0x00840929, NextInt 0x008409c7, Chance 0x00840a3c -- all loading the generator as [reg+0x16c]. Named for the verified relationship (which slot reaches it, and that it draws), NOT for any semantics: its body was not read. Lane H hooks it with a register-transparent entry counter so that 'the spy path never fired' can be split into 'slot 13 was not entered' and 'slot 13 was entered and gated above this call' [mapped]
|
||||
constexpr uint32_t SpyManager_Slot13RngCallee = 0x004408e0;
|
||||
// thiscall uint (void* fleet, char) // first of the two callees through which Game::ServerTradeManagerImpl vftable 0x00a31b74 slot 13 (0x0088ef80) reaches the strategic generator. Exactly ONE incoming reference: an unconditional call at 0x0088f036. Real body 0x00820ca0..0x00820e53, 436 bytes, containing lane V2's NextFloat site 0x00820e18. Its own body loops the vector at arg+0xa4/+0xa8 testing per-element flags, and its boolean result is what gates the call to TradeManager_Slot13RngCalleeB one instruction later. THE CALLER'S LOOP IS OVER THE FLEETS VECTOR at GetServer()+0x64/+0x68, not over a trade-route list -- which is why 'the tail draws nothing because we have no trade routes' does not explain this slot [mapped]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue