#!/usr/bin/env python3 """Golden layouts for `tools/serializers.py --validate`. Transcribed by hand from the layouts this campaign had already recovered and cross-checked against real saves *before* this tool existed: * `findings/objects/struct-recovery.md` sections 1-4 (member tables read out of the decompiled `Write`/`Read` pairs, COL offsets from RTTI) * `findings/subsystems/observedtech-append.md` section 4 + 9 (`ObservedTech`, `sizeof` pinned three independent ways) * `verify/save-reader/SAVE_FORMAT.md` / `save_reader.py` (on-disk tag order, `--strict` clean against three real saves, 36 tests) Offsets are **absolute** (object base), i.e. the decompiled `this`-relative offset plus the IStreamable COL offset. Kinds use the tool's vocabulary. Nothing here is derived from the tool: it is the independent answer the tool has to reproduce. """ # tag, absolute offset, kind GOLDEN = { "Game::ObservedTech": { "write": 0x00817CF0, "sizeof": 0x2C, "fields": [("otnF", 0x04, "int16"), ("otnL", 0x06, "int16"), ("odet", 0x08, "bool"), ("otch", 0x0C, "string"), ("owith", 0x28, "int")], }, "Game::ObservedWeapon": { "write": 0x00817BC0, "sizeof": 0x2C, "fields": [("otnF", 0x04, "int16"), ("otnL", 0x06, "int16"), ("odet", 0x08, "bool"), ("owep", 0x0C, "string"), ("owith", 0x28, "int")], }, "Game::StarSystem::OutputRates": { "write": 0x00745190, "sizeof": 0x1C, "fields": [("SRt", 0x00, "float"), ("SRsc", 0x04, "float"), ("SRtf", 0x08, "float"), ("SRi", 0x0C, "float"), ("SRoh", 0x10, "float"), ("SRs", 0x14, "float"), ("SRnr", 0x18, "int")], }, "Game::ServerSystem": { "write": 0x00749630, "sizeof": None, "fields": [ ("Pos", 0x18, "object"), ("R", 0x4C, "float"), ("G", 0x50, "float"), ("B", 0x54, "float"), ("A", 0x58, "float"), ("Idx", 0x5C, "int"), ("Size", 0x60, "int"), ("Suit", 0x64, "float"), ("Res", 0x68, "int"), ("ARes2", 0x6C, "int"), ("MRes", 0x70, "int"), ("TRes", 0x74, "int"), ("haltv", 0x78, "bool"), ("OutMod", 0x7C, "float"), ("TAcq", 0x80, "int"), ("TFAcq", 0x84, "int"), ("Rts", 0x88, "object"), ("BQ", 0xA4, "object"), ("Name", 0xA8, "string"), ("Abdn", 0xC4, "bool"), ("Dstyd", 0xC5, "bool"), ("vnh", 0xC6, "bool"), ("vnd", 0xC7, "bool"), ("vnex3", 0xC8, "bool"), ("vnpex3", 0xC9, "bool"), ("VFlags", 0xCC, "int"), ("EFlags", 0xD0, "int"), ("AFlags", 0xD4, "int"), ("FFlags", 0xD8, "int"), ("GFlags", 0xDC, "int"), ("MnRFlags", 0xE0, "int"), ("RfRFlags", 0xE4, "int"), ("ClkFlags", 0xE8, "int"), ("Bats2", 0xF0, "int64"), ("rcex", 0xF8, "int64"), ("PID", 0x100, "handle"), ("dcs", 0x104, "object"), ("dsu", 0x118, "float"), ("cm", 0x11C, "object"), ("cme2", 0x13C, "vector"), ("PvCM", 0x14C, "object"), ("NumFlts", 0x16C, "vector"), ("RepCur", 0x17C, "float"), ("RepMax", 0x180, "float"), ("EggScio", 0x184, "int"), ("NoRebAI", 0x188, "bool"), ("PvNoRebAI", 0x189, "bool"), ("Pop", 0x18C, "int"), ("Infra", 0x190, "float"), ("pbon", 0x194, "int"), ("ibon", 0x198, "float"), ("TerrFl", 0x19C, "int"), ("Pop2", 0x1A0, "object"), ("pbon2", 0x1B4, "object"), ("indi", 0x1C8, "object"), ("spies2", 0x1CC, "vector"), ("rbfl", 0x1DC, "int"), ("hsrg", 0x1E0, "bool"), ("adt", 0x1E4, "int"), ("PvPop", 0x200, "int"), ("PvInfra", 0x204, "float"), ("PvSuit", 0x208, "float"), ("PvRes", 0x20C, "int"), ("PvARes2", 0x210, "int"), ("PvMRes", 0x214, "int"), ("PvPop2", 0x218, "object"), ("DefF", 0x238, "handle"), ("DefSF", 0x23C, "handle"), ("NumGFs", 0x240, "vector"), ("NumSnF", 0x250, "vector"), ("NumMnF", 0x260, "vector"), ("NumPlgs2", 0x2A8, "vector"), ("TnsOH", 0x2B8, "int"), ("TDst", 0x2BC, "int"), ("ntdev", 0x2C4, "int"), ("ltis", 0x2C8, "int"), ("rbtn", 0x2CC, "int"), ("rbfr", 0x2D0, "int"), ("rbwn", 0x2D4, "int"), ], }, "Game::StarSystem::PlayerView": { "write": 0x007492D0, "sizeof": None, "fields": [("VTrn", 0x08, "int"), ("Pop", 0x0C, "int"), ("Pop2", 0x10, "object"), ("Infra", 0x24, "float"), ("Suit", 0x28, "float"), ("Res", 0x2C, "int"), ("ARes2", 0x30, "int"), ("MRes", 0x34, "int"), ("NoRebAI", 0x38, "bool"), ("pbon", 0x3C, "int"), ("pbon2", 0x40, "object"), ("ibon", 0x54, "float"), ("TerrFl", 0x58, "int")], }, "Game::PopulationGroup": { "write": 0x00536AF0, "sizeof": 0x18, "fields": [("PopT", 0x04, "int"), ("PopS", 0x08, "int"), ("PopC", 0x10, "int64")], }, "Game::IndependenceInfo": { "write": 0x00748EE0, "sizeof": 0x70, "fields": [("indsp", 0x04, "int"), ("indcl", 0x08, "object"), ("indnm", 0x1C, "string"), ("indav", 0x38, "string"), ("indba", 0x54, "string")], }, "Game::MoraleEvent": { "write": 0x007491B0, "sizeof": 0x50, "fields": [("mid", 0x04, "int"), ("mtr", 0x08, "int"), ("mn", 0x0C, "int"), ("mtp", 0x10, "int"), ("mfx", 0x14, "object"), ("mdsc", 0x34, "string")], }, "Game::ShipBuildOrder": { "write": 0x00813800, "sizeof": None, "fields": [("desID", 0x04, "int"), ("con", 0x08, "int"), ("sav", 0x0C, "int"), ("conleft", 0x10, "int"), ("ordID", 0x14, "int")], }, "Game::DiplomacyStats": { "write": 0x00818CB0, "sizeof": 0x24, "fields": [("other", 0x04, "int"), ("lastnap", 0x08, "int16"), ("lastnapbty", 0x0A, "int16"), ("bknnap", 0x0C, "int16"), ("btynap", 0x0E, "int16"), ("lastally", 0x10, "int16"), ("lastallybty", 0x12, "int16"), ("bknally", 0x14, "int16"), ("btyally", 0x16, "int16"), ("lastcf", 0x18, "int16"), ("lastcfbty", 0x1A, "int16"), ("bkncf", 0x1C, "int16"), ("btycf", 0x1E, "int16"), ("deadhome", 0x20, "int16")], }, "Game::PlayerReport": { "write": 0x00817480, "sizeof": 0x30, "fields": [("oid", 0x04, "int"), ("pid", 0x08, "int"), ("flds", 0x0C, "int"), ("sav", 0x10, "int"), ("home", 0x14, "int"), ("ncol", 0x18, "int"), ("mpwr", 0x1C, "int"), ("mcls", 0x20, "int"), ("mmsl", 0x24, "int"), ("nshp", 0x28, "int"), ("nsat", 0x2C, "int")], }, "Game::FlightPlan": { "write": 0x00700F60, "sizeof": 0x38, "fields": [("wpts", 0x04, "vector"), ("FPsp2", 0x14, "float"), ("FPeta2", 0x18, "int"), ("FPogn2", 0x1C, "object"), ("FPdpos", 0x28, "object"), ("pnd", 0x34, "int")], }, "Game::FlightPlan::Waypoint": { "write": 0x00700ED0, "sizeof": None, "fields": [("Wpt", 0x04, "int"), ("Tp", 0x08, "int"), ("nrt", 0x0C, "object")], }, "Game::NodeRoute": { "write": 0x006E22E0, "sizeof": None, "fields": [("nrp", 0x04, "int"), ("nrf", 0x08, "int"), ("nrt", 0x0C, "int")], }, "Game::StarFleet": { "write": 0x00701070, "sizeof": None, "fields": [("Pos", 0x18, "object"), ("PrvPos", 0x4C, "object"), ("PID", 0x58, "handle"), ("FtName", 0x5C, "string"), ("Perm", 0x78, "bool"), ("Lay", 0x7C, "object"), ("LocID", 0xA0, "handle"), ("NShips", 0xA4, "vector"), ("FPlan", 0xC4, "object"), ("FtTrans", 0xFC, "int"), ("FtOrig", 0x100, "object"), ("FtFlg", 0x10C, "int"), ("Ftae", 0x110, "int"), ("Ftpae", 0x114, "int"), ("FtEnc", 0x118, "int"), ("FtMS", 0x11C, "int")], }, "Game::StarShip": { "write": 0x008291F0, "sizeof": None, "fields": [("PlrID", 0x10, "handle"), ("DesID", 0x14, "int"), ("Range", 0x20, "float"), ("Health", 0x24, "object"), ("MineCap", 0x34, "int"), ("NTH", 0x38, "vector"), ("Plg", 0x48, "int"), ("Act", 0x4C, "int"), ("Dep", 0x50, "bool"), ("Atq", 0x51, "bool"), ("LCT", 0x5C, "int"), ("tsd", 0x60, "int"), ("FltID", 0x64, "handle"), ("ConCap", 0x68, "int"), ("RefCap", 0x6C, "float"), ("RepCap", 0x70, "float"), ("EncID", 0x7C, "int"), ("PrisH", 0x80, "object"), ("BQ2", 0x98, "object"), ("pop", 0x9C, "object"), ("ppop", 0xA0, "object"), ("atsp", 0xA8, "int"), ("tblt", 0xAC, "int")], }, "Game::ServerPlayer": { "write": 0x008563E0, "sizeof": None, "fields": [ ("PlyrIdx", 0x28, "int"), ("HomeSys", 0x2C, "handle"), ("NumOwn", 0x30, "vector"), ("PlryName", 0x40, "string"), ("Species", 0x5C, "int"), ("ClrID", 0x60, "object"), ("Bdg", 0x74, "string"), ("Avt", 0x90, "string"), ("Team", 0xAC, "int"), ("IdealSuit", 0xB0, "float"), ("SuitTol", 0xB4, "float"), ("MaxOH", 0xB8, "float"), ("ResRate", 0xBC, "float"), ("ResMod", 0xC0, "float"), ("ResScl", 0xC4, "float"), ("TRM", 0xD0, "float"), ("TRA", 0xD4, "int"), ("TRP", 0xD8, "int"), ("NumDes", 0xE4, "vector"), ("TechTree", 0xF4, "object"), ("Elim", 0xF8, "bool"), ("NPC", 0xFB, "bool"), ("RebAI", 0xFC, "bool"), ("ReqCL", 0xFD, "bool"), ("AIBn", 0xFE, "bool"), ("CnTrd", 0xFF, "bool"), ("CnRad", 0x100, "bool"), ("CnVItl", 0x101, "bool"), ("hgs", 0x102, "bool"), ("hadvs", 0x103, "bool"), ("harcc", 0x104, "bool"), ("pddm", 0x108, "float"), ("OutMod", 0x124, "float"), ("RebOutMod", 0x128, "float"), ("ScOutMod", 0x12C, "float"), ("PopMod", 0x130, "float"), ("TerraMod", 0x134, "float"), ("AMine", 0x138, "bool"), ("MinPure", 0x13C, "float"), ("MinRate", 0x140, "float"), ("NGts", 0x144, "int"), ("PrGtTrf", 0x148, "int"), ("GTraf", 0x14C, "int"), ("CstR", 0x150, "float"), ("CstE", 0x154, "float"), ("CstT", 0x158, "float"), ("Maint", 0x15C, "int"), ("shrm", 0x160, "float"), ("Status", 0x164, "int"), ("Team", 0x168, "object"), ("NumLeg", 0x178, "vector"), ("PvSav", 0x188, "int"), ("PvMA", 0x18C, "bool"), ("HasDisc", 0x19C, "int"), ("HasDiscSp", 0x1A0, "int"), ("HasDiscCl", 0x1A4, "int"), ("HasEnc", 0x1A8, "int"), ("HasEng", 0x1AC, "int"), ("ShipRecs", 0x1B0, "object"), ("Ojvs", 0x1F4, "vector"), ("Nexp", 0x204, "vector"), ("NWeapXcl", 0x214, "vector"), ("dipstats", 0x230, "vector"), ("comms", 0x240, "object"), ("preps", 0x244, "vector"), ("odes", 0x254, "vector"), ("owep", 0x264, "vector"), ("otch", 0x274, "vector"), ("Sav", 0x284, "int"), ("HasImm", 0x288, "int"), ("HasVac", 0x28C, "int"), ("NPTrk", 0x290, "int"), ("ResTNm", 0x294, "object"), ("FNG", 0x298, "object"), ("Events", 0x29C, "object"), ("BnkWrn", 0x2C4, "int"), ("BnkTrn", 0x2C8, "int"), ("BnkEl", 0x2CC, "int"), ("BnkPr", 0x2D0, "int"), ("plcy", 0x2D8, "int"), ("pswd", 0x2DC, "string"), ("Srn", 0x2F8, "bool"), ("SrnTo", 0x2FC, "handle"), ("lboid", 0x300, "int"), ("lcid2", 0x304, "int"), ("IncMod", 0x30C, "float"), ("aid", 0x310, "vector"), ("ndeflay", 0x320, "vector"), ("cdp", 0x330, "bool"), ("spy2", 0x334, "object"), ("rdtc", 0x338, "vector"), ("aidf", 0x368, "int"), ("civr", 0x370, "object"), ("tnc", 0x39C, "int"), ("NumPR", 0x3A4, "vector"), ("ResErrRoll", 0x3B4, "bool"), ("cta", 0x3B5, "bool"), ("AIR", 0x3B8, "object"), ("AIEnf", 0x3BC, "object"), ("NSprj", 0x3C0, "vector"), ("NextPrjID", 0x3D0, "int"), ("lret", 0x3D4, "int"), ("nmeid", 0x3DC, "int"), ], }, } # sizeof values the campaign pinned independently of any serializer walk GOLDEN_SIZEOF = { "Game::ObservedTech": 0x2C, # magic divide + imul + search stride "Game::ObservedWeapon": 0x2C, "Game::PopulationGroup": 0x18, # Population's own vector stride "Game::MoraleEvent": 0x50, "Game::PlayerReport": 0x30, "Game::DiplomacyStats": 0x24, "Game::StarSystem::OutputRates": 0x1C, } # on-disk tag order, from save_reader.py shapes -> the serializer that writes it DISK_ORDER = { 0x00829960: "Summary", # StrategyGameInfo::Write 0x008276D0: "Slot", # SlotDef::Write 0x0082AE40: "CreateParams", # StrategyGameCreateParams::Write 0x0082AD40: "Scrp", # StrategyScriptParams::Write 0x0056EC00: "PrisonerHold", 0x008189A0: "SystemEvent", 0x0082C290: "PlayerTurnStats", 0x0082C4A0: "PlayerTurnHistory", 0x0082C5A0: "TurnStats", 0x0079FA70: "Sim", # StrategyServer::Write 0x00749630: "Sys", # ServerSystem::Write 0x008563E0: "Player", # ServerPlayer::Write 0x00701070: "Flt", # StarFleet::Write 0x008291F0: "Ship", # StarShip::Write 0x00700F60: "FlightPlan", 0x00817CF0: "Otch", 0x00817BC0: "Owep", 0x00745190: "Rts", 0x00748EE0: "IndependenceInfo", 0x00813800: "BuildOrder", 0x00817480: "Prep", 0x00818CB0: "DipStat", 0x007492D0: "PlayerView", }