From ead46e2608fd0aacc4792e9c0c75e46e2f7daf32 Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 7 Sep 2026 23:52:51 -0400 Subject: [PATCH] M2 verified live (weapons); section compare crash recorded as a gap --- campaign/DASHBOARD.md | 26 +++++++++++++------------- campaign/board.md | 5 +++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/campaign/DASHBOARD.md b/campaign/DASHBOARD.md index 072cf55..d0309e1 100644 --- a/campaign/DASHBOARD.md +++ b/campaign/DASHBOARD.md @@ -1,19 +1,19 @@ # SotS RE campaign — coverage dashboard -Generated 2026-09-08 03:26 UTC · `sots-re` @ 3a3e167,2026-09-07 · `sots-engine` @ 9cd997d,2026-09-07 (49 commits) · regenerate with `tools/dashboard.py` +Generated 2026-09-08 03:52 UTC · `sots-re` @ 906858f,2026-09-07 · `sots-engine` @ b791392,2026-09-07 (51 commits) · regenerate with `tools/dashboard.py` > **North star:** A functional reimplementation of the engine — behavior-equivalent, NOT byte-for-byte ## 1. Map coverage (campaign/board.md) -57 targets · mapped-or-better **44/57** `[████████░░] 77%` · verified **28/57** `[█████░░░░░] 49%` +58 targets · mapped-or-better **45/58** `[████████░░] 78%` · verified **29/58** `[█████░░░░░] 50%` | Status | Count | % | |---|---:|---:| -| verified | 28 | 49% | +| verified | 29 | 50% | | mapped | 16 | 28% | -| in-progress | 4 | 7% | -| backlog | 8 | 14% | +| in-progress | 3 | 5% | +| backlog | 9 | 16% | | blocked | 1 | 2% | | Type | verified | mapped | in-progress | backlog | blocked | total | @@ -22,15 +22,15 @@ Generated 2026-09-08 03:26 UTC · `sots-re` @ 3a3e167,2026-09-07 · `sots-engine | control-flow | 0 | 2 | 0 | 0 | 0 | 2 | | subsystems | 2 | 6 | 1 | 3 | 1 | 13 | | engine | 10 | 0 | 0 | 0 | 0 | 10 | -| verify | 4 | 2 | 0 | 2 | 0 | 8 | -| phase2 | 3 | 0 | 3 | 2 | 0 | 8 | +| verify | 4 | 2 | 0 | 3 | 0 | 9 | +| phase2 | 4 | 0 | 2 | 2 | 0 | 8 | | meta | 4 | 4 | 0 | 1 | 0 | 9 | ## 2. Binary understanding - RTTI type descriptors: **1,924** (`Game::` 1,404, `Mars::` 194; serializable types 179) - Classes with recovered member layouts: **21** / 179 serializable types `[█░░░░░░░░░] 12%` — heuristic: distinct `Game::X`/`Mars::X` in `##`–`####` headings of `struct-recovery.md` + `schema-gaps-resolved.md` -- Functions: **41,411** (parsed from `01-fingerprint.md`); named/annotated in the **address contract** (`ghidra/addresses.json`, not Ghidra's full rename count): **176**, verified **166** `[█████████░] 94%` +- Functions: **41,411** (parsed from `01-fingerprint.md`); named/annotated in the **address contract** (`ghidra/addresses.json`, not Ghidra's full rename count): **211**, verified **202** `[██████████] 96%` ## 3. Data layer @@ -67,7 +67,7 @@ Board `engine:` rows: verified **10**, mapped 0, in flight 0 (of 10) — verifie |---|---|---:|---| | P2-M0 shim bootstrap | ✅ verified | 100% | sots-engine 5f5bc41: proxy binkw32.dll (66 exports identical), MinHook, asm-stub trace hoo | | P2-M1 flat-KV config loader | ✅ verified | 100% | LIVE: GlobalConsts::LoadFile hooked; trace 19 calls/1088 regions (tracecmp 0); compare 19/ | -| P2-M2 manifest/id registry | 🔄 in-progress | 70% | CODE-COMPLETE (engine 81218c7): hooks on WeaponDictionary::Init + SectionDictionary ctor ( | +| P2-M2 manifest/id registry | ✅ verified | 80% | LIVE: trace 22 calls (tracecmp 0); weapons compare 1/1 0 divergences; REPLACE+oracle byte- | | P2-M3 Mars brace-block parser | ⬜ backlog | 0% | Mars::Script pull tokenizer (Open 0x008cd7d0, ReadToken 0x008cd2f0, Next 0x008cd3e0, SkipB | | P2-M4 gobio VFS read | ⬜ backlog | 0% | choke point: bool __cdecl gobio::ReadFile(const char*, IBuffer**) 0x008d5140; FileSystemSe | @@ -94,10 +94,10 @@ Most recent open: ## 8. Delta since previous dashboard -- verified targets: 27 → 28 (+1) · mapped-or-better: 43 → 44 (+1) -- engine LOC: 19,328 → 20,812 (+1,484) · test files: 88 → 88 (+0) · checks: 2,641 → 2,647 (+6) -- addresses verified: 166 → 166 (+0) · recovered layouts: 21 → 21 (+0) · open questions: 27 → 27 (+0) +- verified targets: 28 → 29 (+1) · mapped-or-better: 44 → 45 (+1) +- engine LOC: 20,812 → 20,812 (+0) · test files: 88 → 88 (+0) · checks: 2,647 → 2,647 (+0) +- addresses verified: 166 → 202 (+36) · recovered layouts: 21 → 21 (+0) · open questions: 27 → 27 (+0) --- warnings: mars-rng.md: no oracle total row parsed; mars-stream.md: no oracle total row parsed; mars-vfs.md: no oracle total row parsed - + diff --git a/campaign/board.md b/campaign/board.md index fe6dfc8..f32057f 100644 --- a/campaign/board.md +++ b/campaign/board.md @@ -35,7 +35,7 @@ Status flow: `backlog → in-progress → mapped → verified` (or `blocked`). | strategic turn internals (economy/research/colony/movement/diplomacy) | subsystem | mapped | high | 90% | 2026-09-07 | findings/subsystems/strategic-turn-internals.md: budget/RP/trade/bankruptcy formulas, research rolls (unlisted race=1.0, Zuul x2), colony growth, movement, RNG=MT19937; ~600 g_KEY labels in Ghidra | | P2-M0 shim bootstrap | phase2 | verified | high | 100% | 2026-09-07 | sots-engine 5f5bc41: proxy binkw32.dll (66 exports identical), MinHook, asm-stub trace hook on Application::Initialize; menu reached; evidence verify/results/shim/. Initialize signature unverified -> asm stubs only | | P2-M1 flat-KV config loader | phase2 | verified | high | 100% | 2026-09-08 | LIVE: GlobalConsts::LoadFile hooked; trace 19 calls/1088 regions (tracecmp 0); compare 19/19, 0 divergences; REPLACE loaded all 19 files and End-Turn autosaves hashed exactly to the oracle; offline replay 0. 3 extra parsers found (string/vec3/rect), pi/180 is a double. sots-engine 8b231c0, docs/M1.md; traces verify/traces/m1-* | -| P2-M2 manifest/id registry | phase2 | in-progress | med | 70% | 2026-09-08 | CODE-COMPLETE (engine 81218c7): hooks on WeaponDictionary::Init + SectionDictionary ctor (verified thiscall; added CallConv::Thiscall to the Hook template), manifest_loader + MSVC sort replica; ctest 26/26, cross-build staged /srv/re-lab/shim/dist-m2. Scout trace on the live game proved 123 weapon ids exact, dict sorted by _stricmp on name, 885 sections, 10 dangling ids absent. NEEDS ~20min VM window for golden/compare/replace | +| P2-M2 manifest/id registry | phase2 | verified | high | 80% | 2026-09-08 | LIVE: trace 22 calls (tracecmp 0); weapons compare 1/1 0 divergences; REPLACE+oracle byte-identical with our weapon loader feeding the game. Proves 123 weapon ids == manifest, DELETED lines are comments, dict sorted by _stricmp on name, +0x14 layout fix correct. GAP: section dictionary is TRACE-ONLY - ours crashes the engine in compare mode (leads in docs/M2.md; hooking LoadSection is the next boundary) | | P2-M3 Mars brace-block parser | phase2 | backlog | — | 0% | 2026-09-07 | Mars::Script pull tokenizer (Open 0x008cd7d0, ReadToken 0x008cd2f0, Next 0x008cd3e0, SkipBlock 0x008cd4b0); whitespace-only delimiting, quotes " ' ` no escapes, EOF ends, stray } ignored, LAST PAIR W/O TRAILING NEWLINE DROPPED; consumers = _stricmp if/else chains (WeaponDef::ParseScript 0x00599070, SectionDef::ParseScript 0x005744e0, MasterTechTree::ParseTech 0x0058b050). .effect = Mars::TextFileStream (Open 0x008cfb90) | | P2-M4 gobio VFS read | phase2 | backlog | — | 0% | 2026-09-07 | choke point: bool __cdecl gobio::ReadFile(const char*, IBuffer**) 0x008d5140; FileSystemSet ctor 0x008d6d60 pushes NativeFileSystem(".") FIRST then sots.ini [Modules] Mount (fallback sots.gob, sots_local_en.gob); zip lookup case+slash-insensitive 0x008d4a50 -> matches mars/vfs NativeFirst | | loader prototypes (Ghidra) | meta | verified | high | 100% | 2026-09-07 | findings/subsystems/loader-prototypes.md: 80 entries (79 verified) in ghidra/addresses.json; Initialize = bool(this, AppStartup*) RET 4 (M0 crash explained); 93 fns renamed + 9 structs in Ghidra | @@ -58,7 +58,8 @@ Status flow: `backlog → in-progress → mapped → verified` (or `blocked`). | P2-B3 ProcessResearch (behavioral, RNG) | phase2 | in-progress | med | 70% | 2026-09-08 | CODE-COMPLETE (engine 3ebc8bf), dist-b3 staged. Static analysis found 5 REAL BUGS in our code: draw = y/(2^32-1) not y*2^-32 (constant 1/4294967295; compare could NOT have caught this - 0 decision flips in 1e6); NextInt is [0,n] INCLUSIVE by pointer; spend has no floor at 0; odds/roll/ratio are float32 not double; decay constants are widened float literals. ProcessResearch arg2 = the RNG object. ctest 26/26. NEEDS VM window (queued behind M2) | | RNG signatures (Ghidra) | meta | verified | high | 100% | 2026-09-08 | Seed/Twist/NextFloat verified (own pass) + NextInt pinned by B3: [0,n] inclusive, bound by pointer. Draw mapping = y/(2^32-1). Lazy twist, left@+0x9c4. Open: x87 precision-control mode at runtime (instrumented - hook logs fpu_cw) | | engine: game/effects | engine | verified | high | 100% | 2026-09-08 | merged: TechId enum (196 slots @10000+i), 44 ids with typed strategic effects, species flag bits, ApplyTechEffect; 254 checks | -| VM140 exclusivity (lab rule) | meta | verified | high | 100% | 2026-09-08 | one agent at a time deploys/relaunches; interleaved deploys silently corrupt compares. Holder: M2 (running its window). QUEUE: B3, then B2. Non-holders build in /srv/re-lab/build/sots-engine-, stage dist-, deploy to C:\SOTS\shimdist- | +| VM140 exclusivity (lab rule) | meta | verified | high | 100% | 2026-09-08 | one agent at a time deploys/relaunches. Holder: B3 (window open). QUEUE: B2. Non-holders build in /srv/re-lab/build/sots-engine-, stage dist-, deploy to C:\SOTS\shimdist-. NOTE: a Windows Update dialog can hide a crash dialog and mimic a hang - screenshot before believing one | | Zuul double-roll (behavioural) | verify | backlog | — | 0% | 2026-09-08 | the reference save may have no species-5 player; if so the Zuul double roll is verified only by disassembly. Needs one extra compare from a Zuul save | | budget tail coverage (expenses/aid/debt) | verify | backlog | — | 0% | 2026-09-08 | 8 ComputeBudget slots were always 0 in ref-turn2 (no sliders, no aid, no debt, no handicap). Need a save with expense sliders, a debtor and a research-aid treaty to exercise ExpenseTotal + the aid/bonus tail | | hook GetDifficultyMods | meta | backlog | — | 0% | 2026-09-08 | B1 derived the two difficulty rows from trace values (AI maintenance divisor 3, research x1.5) instead of snapshotting them; hook it properly so they stop being constants | +| section-loader compare crash | verify | backlog | — | 0% | 2026-09-08 | SectionDictionary compare crashes the engine while the identical weapon path succeeds -> fault is in re-running LoadSection, not the manifest reader. Next boundary: hook LoadSection itself. docs/M2.md has 3 ranked leads |