diff --git a/CLAUDE.md b/CLAUDE.md index 1d7a3da..5c7ff25 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,9 +12,10 @@ `engine/ game/ content/ docs/ reference/ tools/ context/`. **Current front (2026-08-06):** core gameplay reconstruction is COMPLETE — SP+MP loop, combat/ damage/scoring, locomotion (gait/gimp/CROUCH), night kit (searchlight), death/respawn, replication -all authentic + benched (builds 4.11.774→801). Active work: the POLISH list + the #60 export -gap census. Details + what's-next: `context/project-overview.md`, `context/open-questions.md`, -recent git log. +all authentic + benched (builds 4.11.774→801). The decomp export was REBUILT 2026-08-06 (#60 +closed: coverage 93.5%, dark code 41 KB — cite `@ADDR`, NOT `part_0NN.c:LINE`; the old export is +archived). Active work: the POLISH list. Details + what's-next: `context/project-overview.md`, +`context/open-questions.md`, recent git log. --- diff --git a/context/decomp-reference.md b/context/decomp-reference.md index b8e5e7d..e1226aa 100644 --- a/context/decomp-reference.md +++ b/context/decomp-reference.md @@ -685,7 +685,22 @@ Respawn SIM path: `DropZoneReply` `FUN_004bffd0` → `Mech::Reset` @0x4009fb74; --- ## 7. Tools -- `tools/gapcensus.py` — the #60 dark-region census: index/export coverage, function-start discovery, TU attribution, repo-citation flags → `reference/decomp/GAP_CENSUS.md` + `gap_census.tsv`. Consult BEFORE any "absent from the export" claim (gotcha §20). +- ⚠ **CITATION POLICY (since the 2026-08-06 re-export): cite `@ADDR`, never `part_0NN.c:LINE`.** + Addresses are stable across exports; shard membership and line numbers are NOT. Pre-08-06 + part/line citations resolve only against `reference/decomp/archive_2025export/`. +- ⚠ **Ghidra renders member access as int-ARRAY indices** (`param_1[0xfe]` == byte offset 0x3f8, + `[0x1e7]` == 0x79c): grepping the export for an offset STRING misses every such site. Divide + by 4 (or grep both forms) — this is a live instance of gotcha §20. +- `tools/gapcensus.py [dir]` — the #60 dark-region census: index/export coverage, function-start + discovery, TU attribution, repo-citation flags → `/GAP_CENSUS.md` + `gap_census.tsv`. + Consult BEFORE any "absent from the export" claim (gotcha §20). +- `tools/ghidra_reexport.sh [reprocess]` — headless re-export: Ghidra 12.1.2 + JDK 21 (installed + in `%LOCALAPPDATA%\bt411-tools` beside DXSDK/cmake) run `reference/ghidra_scripts/ExportGaps.java` + (ExportAll's output contract + the dark-region gap fill). ⚠ the runner MUST use 8.3 SHORT paths + (`JOELAP~1`, `BT411-~1`): Ghidra's launcher .bat expands `%JAVA_HOME%` UNQUOTED and the user + profile has a space. `reprocess` re-runs the script on the saved project (skips re-analysis). +- `tools/gapdiff.py [old] [new]` — score two censused exports (coverage/dark deltas, which + previously-dark addresses the KB already cites, celebrity check). - `tools/disas2.py [len]` — capstone disassembly of BTL4OPT.EXE at a VA (recovers x87 math Ghidra drops; folds known call targets + float constants). THE tool for any `FUN_` the diff --git a/context/locomotion.md b/context/locomotion.md index ad1427b..98ca253 100644 --- a/context/locomotion.md +++ b/context/locomotion.md @@ -335,6 +335,24 @@ receipt duckcp_030 = grass-level view). A false "eye does not drop" residual wa the interior looks unchanged and only the through-window ground shifts). Bench traps for reruns: MP button delivery can miss if pressed during round-start jitter (press >= poll 900 after GO); diags all BT_DUCK_LOG-gated. +### CROUCH addendum -- the #60 re-export pass (2026-08-06) [T1] +The rebuilt export (93.5% coverage) produced pseudocode for the master-perf region this block +was hand-disassembled from, and it **confirms the transcription field for field**: +`param_1[0xfe]`=mapPosture(0x3f8), `[0xe6]`=duckState(0x398), `[0x161]`=squatCapable, +`[0x1e7]`=myomerEffectiveness(0x79c), `[0x10]`=movementMode, `player+0x25c` novice gate, +`FUN_004a7fc4(2|3)`=SetLegAnimation sqd/squ, `FUN_004a4c54(8)+(1)`=ForceUpdate, `+0x131` +stability alarm, duckState cleared after. (Ghidra renders these as int-ARRAY indices -- +`[0xfe]` == byte 0x3f8 -- which is why an offset-string grep of the export misses them; see +[[reconstruction-gotchas]] §20.) + +**It also caught a branch the raw pass missed** (the hand disassembly stopped at `0x4aa0af`): +an **AIRBORNE AUTO-RISE** immediately after the duck consumer -- +`if ((movementMode == 3 || movementMode == 4) && legState == 1) -> SetLegAnimation(3) + +ForceUpdate(8)+(1) + stability 1`. A mech that leaves the ground (jump/knockback) while PARKED +in the squat is forced upright; unconditional on duckState/squatCapable, i.e. a safety +un-crouch rather than a request. Implemented in mech4.cpp the same day; crouch re-benched +un-regressed (squat still holds on flat ground, no spurious rises). + ## Key Relationships - Detail: `docs/P3_LOCOMOTION.md`. Uses: [[asset-formats]] (SKL/ANI), [[decomp-reference]] (offsets). - Feeds: [[combat-damage]] (collision→damage), [[rendering]] (shadow/visual-conform). diff --git a/context/open-questions.md b/context/open-questions.md index 433cfd1..5c17f81 100644 --- a/context/open-questions.md +++ b/context/open-questions.md @@ -1020,6 +1020,25 @@ stability problems or massive lag spikes"*. Relevant to the carried cross-fire-s silent-node-crash opens: neither reproduced at 5 players this session. Not evidence of a fix (neither was addressed), but it bounds how often they occur. +## Post-re-export leads (2026-08-06, #60 closed — [[source-completeness]], `phases/phase-04-gap-census.md`) +- **`@0x4c0904` is the MASTER BTPlayer Performance — our `@0x4c083c` attribution needs a + re-check.** Newly lit by the re-export: it resolves the player's Team by name out of the + `Teams` registry (error string "Team ... does not exist"), calls `@0x4c083c` and the engine + `Player::PlayerSimulation` (`@0x42e100`), then at mission-end (state 4, past a threshold, + once) posts "Sending EndMission" to the console host, and on a timer posts the periodic + console SCORE update (`Round(currentScore)` — corroborating our hand-built scoreboard + heartbeat). btplayer.cpp currently documents `@0x4c083c` as PlayerSimulation; read both and + fix the attribution + fold in the team resolution (we have no Team-by-name resolve today). +- **`0x480a2a-0x487ca0` (~9 KB, l4splr|btmssn boundary) stayed dark THROUGH the re-export** — + the gap fill reached it with neither a call nor a data reference, which is itself a finding: + dead code, data misparsed as code, or reachable only through a jump table. The earlier + spot-check showed a real `enter 0x3c` function driven by a global-index dispatch table + (`[0x4fef88]` → table `0x501588`), so "dead code" is unlikely. Byte-scan for the table's + writers to find the entry path. +- **~41 KB is still dark overall**, mostly munga/munga_l4 (we compile the real engine source, so + low value). Current map: `reference/decomp/GAP_CENSUS.md`; re-run the pipeline after any + future re-export. + ## Key Relationships - Feeds from: every subsystem/render topic (their deferral notes collect here). - Gating master: [[source-completeness]] (the missing BT source). diff --git a/context/project-overview.md b/context/project-overview.md index 72beebb..2004609 100644 --- a/context/project-overview.md +++ b/context/project-overview.md @@ -49,11 +49,14 @@ power/myomers (incl. the seek-4 freeze); replication (masters/replicants, kill/d ghost+skate field detectors); the Steam wire seam + build gate; the operator console/relay lifecycle; gauges/HUD; audio (real OpenAL backend + the AUDIO_FIDELITY trigger waves — footsteps/ gait/alarms/impacts live in the field). [T2] -**Remaining (polish + infra):** the #60 export gap census (NEXT — export-gap blindness has caused -4 wrong conclusions, [[reconstruction-gotchas]] §20); VehicleDead killed-by consumption (operator -"X killed by Y"); burning-wreck handler (mech-0x17 label mismatch); the id-0x16 type-0 curiosity; -MechRIOMapper Keypress @004d2514; marker beacon (LoadObject wrapper stub); DIV firmware -intersection routine (deep-cut); deferred ledger items in [[open-questions]]. [T2] +**Infra ✅ 2026-08-06:** the #60 export gap census AND re-export shipped — coverage 87.3% → +93.5%, dark code 90 → 41 KB, +205 functions, and the re-export independently confirmed the +week's raw-disasm reconstructions ([[source-completeness]], `phases/phase-04-gap-census.md`). +**Remaining (polish):** VehicleDead killed-by consumption (operator "X killed by Y" — the sender +already ships the fields); burning-wreck handler (mech-0x17 label mismatch); `@0x4c0904` master +BTPlayer Performance vs our `@0x4c083c` attribution; the id-0x16 type-0 curiosity; MechRIOMapper +Keypress @004d2514; marker beacon (LoadObject wrapper stub); DIV firmware intersection routine +(deep-cut); deferred ledger items in [[open-questions]]. [T2] ## Key Relationships - Full detail: `docs/PROGRESS_LOG.md`. diff --git a/reference/glossary.yaml b/reference/glossary.yaml index 94b9be9..10e79ab 100644 --- a/reference/glossary.yaml +++ b/reference/glossary.yaml @@ -437,3 +437,9 @@ export-gap-blindness: definition: Concluding "the binary/content lacks X" from the Ghidra EXPORT or the port alone. The export has coverage gaps (#60) and RES-archive content never appears in it, so absence there proves nothing. Four incidents (two falsely [T1]); rule + checklist in reconstruction-gotchas §20 — byte-scan the exe, grep NAMED members, walk the BTL4.RES TOC, consult the manifest. related_terms: [decomp, RES] related_topics: [reconstruction-gotchas, source-completeness] + +dark-region: + kind: concept + definition: A stretch of BTL4OPT.EXE's code section belonging to no function in the Ghidra export -- invisible to any grep of reference/decomp. Inventoried by tools/gapcensus.py into reference/decomp/GAP_CENSUS.md (after the 2026-08-06 re-export: ~41 KB across 321 regions, down from 90 KB). Absence of an address from the export proves nothing until you check whether it is dark; see reconstruction-gotchas 20 (export-gap-blindness). + related_terms: [decomp, export-gap-blindness] + related_topics: [source-completeness, reconstruction-gotchas]