From cf695d9d673fce680d637357d6559b71df1aaf86 Mon Sep 17 00:00:00 2001 From: arcattack Date: Sun, 5 Jul 2026 21:10:08 -0500 Subject: [PATCH] CLAUDE.md: adapt operational sections to the bt411 tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite the build/run/debug recipe (§10a) and the "where inputs live" section (§10a-bis) for the consolidated bt411 layout; remap the reconstruction-ledger citations (btbuild/*.md -> docs/*.md); flag §6's port/ viewer as archive-only. The deep decomp-history sections still cite the original nick-games paths as provenance -- the orientation banner at the top maps them onto the new tree. Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 102 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 39 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 2d40c5a..5a6e6c5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,7 +25,7 @@ arcade pod hardware. Primary target: **BattleTech (BT)**; Red Planet (RP) shares > Update existing statements when reality changes them rather than letting the doc drift. Goal: a later > session (or a fresh agent) can read this file and have the full working context with nothing lost to > chat history. Durable project facts → here; per-session/cross-cutting reminders → the `memory/` files -> (indexed in `MEMORY.md`); detailed running findings → `btbuild/RECONCILE.md`. +> (indexed in `MEMORY.md`); detailed running findings → `docs/RECONCILE.md`. --- @@ -194,7 +194,13 @@ HUD/app), which is confirmed gone (§5a) → must be **reconstructed**, now with implementations as a live reference** (`VTV`≈mech, `VTVMPPR`≈mechmppr, `WEAPSYS`≈mech weapons, `RP_L4` app≈`BT_L4` app) — plus `btrel410.exe` as a behavioral oracle. -## 6. Port codebase (`port/`) +## 6. Port codebase (`port/`) — the standalone viewer sandbox (NOT in bt411) + +> ⚠️ **This section documents the standalone D3D9 viewer, which lives in the ORIGINAL workspace +> (`nick-games/port/`), NOT in bt411.** It is a dev sandbox that proved the renderer bypass + asset +> pipeline; the game itself does not use it. Its `image.{cpp,h}` codec IS in bt411 (as +> `engine/MUNGA_L4/image.{cpp,h}` — the engine loader shares it). If the viewer is ever wanted here, +> it's a small self-contained add. The rest of this section is retained as reference. Standalone **D3D9 model/animation viewer** — proves the renderer bypass + asset pipeline. **Not the game.** @@ -222,7 +228,7 @@ Standalone **D3D9 model/animation viewer** — proves the renderer bypass + asse governed thrust *vehicles* (RP hovercraft `VTVPWR`, camera ship) + collisions, NOT walk gait. NOTE: the BT walking-mech mover/mapper code is NOT in the source dump (BT here is weapons-only; the mech consumer of Animate() is absent) — but the per-clip speed is fully recoverable from the `.ANI` data above. - **✅ P3 LOCOMOTION CUTOVER — STEP 1 DONE (`btbuild/P3_LOCOMOTION.md`).** btl4's live drive (mech4.cpp + **✅ P3 LOCOMOTION CUTOVER — STEP 1 DONE (`docs/P3_LOCOMOTION.md`).** btl4's live drive (mech4.cpp `PerformAndWatch`) is now ANIMATION-DRIVEN: the engine `AnimationInstance::Animate(dt,True)` return `adv` (the clip's per-frame `[RootTranslation]` distance) drives the forward step (`localOrigin.linearPosition += facing * adv`), replacing the hand-tuned `kDriveMaxSpeed` slide. Verified: mech walks at the clip's @@ -230,7 +236,7 @@ Standalone **D3D9 model/animation viewer** — proves the renderer bypass + asse un-regressed. NOTE: the reconstructed two-channel gait (mech2.cpp `AdvanceLeg/BodyAnimation`, `IntegrateMotion`) is bracketed by no-op stubs (`ReconSeq` controllers → Advance()=0; `Matrix34`=`ReconMatrix` no-op), so the full gait (STEP 7) needs those backed by real engine `AnimationInstance`/affine-matrix first. Plan + - 7 steps in `btbuild/P3_LOCOMOTION.md`; the smallest milestone (STEPs 1-2, real per-clip speeds on the + 7 steps in `docs/P3_LOCOMOTION.md`; the smallest milestone (STEPs 1-2, real per-clip speeds on the proven engine path) is the near-zero-risk win. **✅ P3 STEP 7 CUTOVER — the real gait controller drives locomotion LIVE (gated `BT_GAIT_CUTOVER=1`; verified).** The BT-specific `SequenceController` (`decomp/reconstructed/seqctl.cpp`, reconstructed from binary @@ -556,7 +562,7 @@ Old roadmap below is superseded for Phases 1–3 (engine/renderer/HAL/audio = do sim core (InterestManager/Entity/HostManager) is complete. So multiplayer = **integrate + smoke-test that existing TCP stack**, gated on P3 (locomotion update writer) + P5 (entity create/destroy lifecycle) + subsystem WAVEs. Unknown: whether that TCP path has ever run successfully even in RP (a send-size bug at `L4NET.CPP:1853`). - This is problem **P6** in `btbuild/HARD_PROBLEMS.md`. + This is problem **P6** in `docs/HARD_PROBLEMS.md`. **⭐ P6 SMOKE TEST PASSED — TWO INSTANCES SHARE A WORLD (cross-pod entity replication live).** The full chain works on one box: console egg delivery → TCP mesh → synchronized mission start → bidirectional entity replication (each instance renders its own mech + the peer's REPLICANT; `[BTrender] mech tree @@ -634,21 +640,26 @@ VPX/IG board DOSBox can't emulate; bypassing it = the shim work anyway. The reconstructed BT (`C:\git\nick-games\btbuild` → `run\btl4.exe`) now boots, renders the cavern world + a skinned Blackhawk, and runs a **drive → animate → target → fire → damage → destroy** loop. The remaining work is making each link *authentic* (reconstructed from the binary), not bringing the link up. -Companion ledgers: `btbuild/RECONCILE.md` (running findings), `docs/BT_SOURCE_STATUS.md` (missing-file +Companion ledgers: `docs/RECONCILE.md` (running findings), `docs/BT_SOURCE_STATUS.md` (missing-file map), memory files `bt-combat-bringup`, `reconstruction-no-standins`. -### 10a. Build / run / debug recipe -- **Build:** `cmake --build C:\git\nick-games\btbuild\build --config Debug` (CMake/MSVC Win32, VS2019 - **BuildTools** instance). Links `bt410_l4` (reconstructed BT) + `munga_engine.lib` (enginebuild) + - DXSDK d3d9/d3dx9/dinput8 + OpenAL/libsndfile. Linker uses `/FORCE` (tolerates header-defined globals - + dead offline-factory unresolved externals — see CMakeLists comment; a cleanup TODO). -- **Single-file check** before a full build: `cmd /c C:\git\nick-games\btbuild\compile1.cmd .cpp` - (green = compiles). NOTE: compile-green ≠ link-green — a fn that pulls `mech3.obj` exposes the dead - factory unresolveds (why `/FORCE`). -- **Run:** copy `build\Debug\btl4.exe`+`.pdb` to `btbuild\run\`, run from the **pod BT dir** - `tesla4pod_extracted\Tesla4PodPCNovell\CopyofNovellDisk\REL410\BT` with `-egg TEST.EGG`. Logs to - `btl4.log` in that dir (grep `[anim]/[drive]/[target]/[fire]/[damage]/[boot]` markers). cwd MUST be the - pod BT dir (see `loadTables` gotcha below). +### 10a. Build / run / debug recipe (bt411 layout — see README.md) +- **Configure once** (32-bit / Win32 — the DXSDK link libs are `Lib/x86`): + `cmake -S C:\git\bt411 -B C:\git\bt411\build -G "Visual Studio 16 2019" -A Win32 + -DCMAKE_GENERATOR_INSTANCE="C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools"`. +- **Build:** `cmake --build C:\git\bt411\build --config Debug`. The one top-level `CMakeLists.txt` + builds `munga_engine` (engine lib, `engine/MUNGA{,_L4}/`) + `bt410_l4` (reconstructed BT game lib, + `game/reconstructed/` + `game/original/`) + `btl4.exe`, linking DXSDK d3d9/d3dx9/dinput8 + + OpenAL/libsndfile (`engine/lib/`). Linker uses `/FORCE` (tolerates header-defined globals + the dead + offline-factory unresolved externals in `mech3.cpp` — see the CMakeLists comment; a cleanup TODO). + ⚠ Editing an `engine/` file rebuilds the engine lib automatically now (one project) — no separate + engine build step; but a NEW member on a `DPLRenderer`/`d3d_OBJECT` class still needs the game objs + that embed its layout recompiled (delete stale objs if layout-mismatch corruption appears). +- **Run:** `run\run.cmd [EGG]` (default `DEV.EGG`) — it `cd`s to `content\` and launches + `build\Debug\btl4.exe -egg `. **cwd MUST be `content\`** (the engine resolves `BTL4.RES`, + `VIDEO\`, `BTDPL.INI`, eggs relative to cwd — see the `loadTables` gotcha below). Logs to `btl4.log` + in `content\` (grep `[anim]/[drive]/[target]/[fire]/[damage]/[boot]` markers). The DLLs + (OpenAL32/libsndfile) are copied next to the exe automatically at build time. - **⭐ THE AUTHENTIC STACK IS NOW DEFAULT-ON** (`BTEnvOn`, mechrecon.hpp): `BT_GAIT_CUTOVER`, `BT_GAIT_SM`, `BT_COLLISION`, `BT_REAL_CONTROLS` all default ON — set `=0` to fall back to the historic bring-up path (e.g. `BT_GAIT_SM=0`). Verified: an env-free run gets the full authentic chain @@ -700,26 +711,39 @@ map), memory files `bt-combat-bringup`, `reconstruction-no-standins`. per weapon FAMILY not per mech); (3) beam colour still the BLH red (per-weapon `VideoObjectName` pending weapon enumeration). Everything else is foundational. - **cdb (x86):** `"C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe"`. Pattern for a faulting - stack (set cwd to the pod BT dir first): `-g -c ".lines;sxe av;g;kp 24;q"` with `BT_ASSERT_TO_DEBUGGER=1`. + stack (set cwd to `content\` first): `-g -c ".lines;sxe av;g;kp 24;q"` with `BT_ASSERT_TO_DEBUGGER=1`. The debug CRT marks fresh heap **0xCDCDCDCD** (uninitialized) and freed **0xFEEEFEEE** — invaluable for "was this ever constructed?" questions. gflags PageHeap (needs elevation) caught the earlier subsystem heap overruns. -### 10a-bis. Where the BT build's inputs live (NOT consolidated — a "virtual assembly") -The build is pinned (no ad-hoc archive searching), but spans 6 locations + runtime content; all paths are -**absolute** (not relocatable). Compiled into `btl4.exe`: (1) **`decomp/reconstructed/`** — reconstructed -BT source (the bulk); (2) **`410srczipped_extracted/410SRC/.../CODE/BT/{BT,BT_L4}`** — ~9 *surviving -original* BT `.cpp` (`BTMSSN/BTREG/BTTEAM/BTSCNRL/BTCNSL/GAUSS/PPC/BTL4MODE/BTL4ARND`) + BT header include -dirs; (3) **`btbuild/`** — launcher `btl4main.cpp` + CMake + `run/` + `compile1.cmd`; (4) **`enginebuild/`** -— prebuilt `munga_engine.lib` + `shim/` headers. The **engine is referenced twice**, both rooted in the -archive: (5) **`elsewhen_extracted/.../MUNGA/`** is compiled into `munga_engine.lib` (via `enginebuild`) -AND its **headers** are reached at compile time through **~188 `btbuild/fwd/*.hpp` forwarding shims** (each -just `#include "C:/git/.../elsewhen_extracted/.../MUNGA/.h"`) — this is the glue letting reconstructed -code do `#include ` without copying engine headers. External: DXSDK June 2010 + OpenAL/ -libsndfile. At **runtime** the exe needs cwd = **`tesla4pod_extracted/.../REL410/BT/`** (content: `BTL4.RES`, -models, `TEST.EGG`, `VIDEO\\REPLACEMATS.tbl`). Reference-only (not built): `decomp/recovered/all/part_*.c` -(raw pseudocode = source of truth). Consolidating into one relocatable tree (copy engine headers + content, -relativize paths) is a possible future cleanup, not done. +### 10a-bis. Repo layout — where everything lives (CONSOLIDATED into bt411) +The build was formerly a "virtual assembly" scattered across 6 absolute-path locations in the RE +workspace; it is now **one relocatable tree** (`C:\git\bt411`, all repo-relative). Map of the tree +(full detail in `README.md`): +- **`engine/MUNGA/` + `engine/MUNGA_L4/`** — the shared 2007 MUNGA engine + Win32/D3D9 HAL, carrying + our BT render/loader work (`bgfload`/`L4D3D`/`L4VIDEO` + the `image.{cpp,h}` codec). Plus + `engine/shim/` (ATL shim), `engine/lib/` (OpenAL/libsndfile libs + runtime DLLs), `engine/rp/` (the + ~21 RP *headers* the audio HAL includes via `..\rp\vtv.h` — headers only, no RP game source), and + `engine/DPLSTUB.h`/`LOGGER.h` (the trunk-root headers reached via `..\`). +- **`game/reconstructed/`** — the reconstructed BT source (the bulk; was `decomp/reconstructed/`). +- **`game/original/BT/` + `game/original/BT_L4/`** — the surviving *original* BT `.cpp` + (`BTMSSN/BTREG/BTTEAM/BTSCNRL/BTCNSL/GAUSS/PPC/BTL4MODE/BTL4ARND`) **+ all the BT headers** (these two + dirs are the game's header include path). +- **`game/fwd/`** — the ~186 forwarding shims letting reconstructed code do `#include `; + each now `#include "../../engine/MUNGA/.h"` (relativized). `fwd/app.thp` is a self-contained + `TestApplication` reconstruction shim; `fwd/bgfload.h` forwards to the engine loader header. +- **`game/btl4main.cpp`** — the WinMain launcher. +- **`content/`** — the runtime tree (was `tesla4pod_extracted/.../REL410/BT/`): `BTL4.RES`, `VIDEO/`, + `GAUGE/`, `AUDIO/`, eggs, `BTDPL.INI`, `VIDEO/REPLACEMATS.tbl`. **Run cwd = `content/`.** +- **`reference/decomp/`** — the raw Ghidra pseudocode `all/part_*.c` (was `decomp/recovered/`), the + source-of-truth every reconstruction is verified against. `reference/ghidra_scripts/` = the exporter. +- **`docs/`** — format specs (`BGF_FORMAT`, `ASSET_PIPELINE`, `BT_SOURCE_STATUS`) + the reconstruction + ledgers (`RECONCILE`, `HARD_PROBLEMS`, `RESOURCE_AUDIT`, `SUBSYS_PLAN`, `WAVE_PLAN`, `P3_LOCOMOTION`). +- **`tools/`** — `btconsole.py` (MP console emulator) + `mapscan.py`/`resscan.py` scanners. +- External (not vendored): **DXSDK June 2010** (overridable `-DDXSDK`). ⚠ Historical sections below + still cite the old `nick-games/…` absolute paths as provenance — see the orientation banner at the + top; they map onto the dirs above. **NOT copied into bt411:** the standalone D3D9 viewer (§6 `port/`, + a dev sandbox) and the RE toolchain blobs (Ghidra/JDK) — those stay in the original workspace. ### 10b. Reconstruction workflow (the method) — **RULE: no stand-ins** The loop for each feature: (1) read the RAW decomp `decomp/recovered/all/part_*.c` for the relevant @@ -848,7 +872,7 @@ read-only **Workflow** (understanding phase), then implement hands-on so each ch (reads `movementMode==2||9`), but `movementMode` is set by the bypassed gait/death-transition → bring-up death reads the real zone state directly (a `vitalDamageZone` with `damageLevel>=1.0`). Removing the wreck (`DestroyEntityMessage`) crashes on teardown — death = explosion + stop-targeting for now. - ⚠ **ROOT-CAUSE PIVOT (P5 — full writeup `btbuild/HARD_PROBLEMS.md`; repro `BT_ENABLE_TEARDOWN=1`):** it is + ⚠ **ROOT-CAUSE PIVOT (P5 — full writeup `docs/HARD_PROBLEMS.md`; repro `BT_ENABLE_TEARDOWN=1`):** it is a **TEARDOWN-SEQUENCE double-free, NOT a base-region stomp** (two earlier theories DISPROVEN). (a) "solids never built" — WRONG (`Mover::Mover`:1756 allocs `collisionLists` unconditionally). (b) "reconstructed Mech raw offsets stomp the engine collision cluster" — ALSO WRONG: those stomps (`Mech::Simulate` collision/ @@ -872,7 +896,7 @@ read-only **Workflow** (understanding phase), then implement hands-on so each ch artifact of forcing a removal the original never does (only reachable via `BT_ENABLE_TEARDOWN`). NOTHING to fix. Real future death work = reconstruct DeathShutdown + collapse anim + destroyed skin (does NOT touch the teardown path). Later trace also showed it's heap corruption in a SINGLE teardown, not the double-free the - line above hypothesized. Full trail: `btbuild/HARD_PROBLEMS.md`. + line above hypothesized. Full trail: `docs/HARD_PROBLEMS.md`. ⭐ **P5 TRULY CLOSED — ROOT CAUSE FOUND & FIXED (the whole trail above was chasing run-2 of a DOUBLED dtor chain).** `Mech::~Mech` (mech.cpp:1106) contained an EXPLICIT `JointedMover::~JointedMover();` — the Ghidra decomp shows the binary's `FUN_00425550(this,0)` tail call, which IS the compiler-emitted @@ -910,7 +934,7 @@ read-only **Workflow** (understanding phase), then implement hands-on so each ch heat (`heat`), weapons (`emitter`/`mechweap`/`mislanch`/`missile`/`projweap`/`projtile`/`gauss`/`ppc`), subsystems (`gyro`/`sensor`/`gnrator`/`powersub`/`myomers`/`torso`/...), app/HUD (`btl4app`/`btl4vid`/ `btl4mppr`/`btl4mssn`/`btplayer`/`hud`/`dpl2d`). **Subsystem instances are `RECON_SUBSYS` STUBS — the -un-stub wave is IN PROGRESS** (full per-family plan: `btbuild/SUBSYS_PLAN.md`, from the `bt-subsystem-recon` +un-stub wave is IN PROGRESS** (full per-family plan: `docs/SUBSYS_PLAN.md`, from the `bt-subsystem-recon` workflow). KEY FINDING: the **real subsystem classes mostly already exist** (heat→`heatfamily_reslice`, weapons→`emitter`/`projweap`/`mislanch`, gyro/sensor/power/torso/myomers/searchlight/thermalsight/ammobin all reconstructed); the work is *wiring* them in + the 4 systemic checks (shadowing, `Wword` trap, handler @@ -939,7 +963,7 @@ chain ran through MechSubsystem. Worked around by qualifying `this->Subsystem::d the proper fix = remove the `MechSubsystem::damageZone` shim shadow (cascades to mechsub.cpp) — a follow-up. Two include fixes also needed: `heat.hpp` now `#include `; `mechrecon.hpp` now `#include ` (self-sufficient Quaternion, for myomers's include order). Next = WAVE 2 (heat factory -wiring + MechTech/HUD un-swap) per `btbuild/SUBSYS_PLAN.md`.** +wiring + MechTech/HUD un-swap) per `docs/SUBSYS_PLAN.md`.** **✅ WAVE 2 DONE** — real heat family + HUD + MechTech wired into the factory. Swap mechanism: a per-class `CreateSubsystem(Mech*,int,void*)` BRIDGE fn appended to each real class's own `.cpp` (heat.cpp: Condenser 0x230 + HeatSink-bank 0x1e4; heatfamily_reslice.cpp: Reservoir 0x230; hud.cpp: HUD 0x2a4; @@ -1037,7 +1061,7 @@ each faithful to the decomp (no stand-ins): offline-tool code; Torso 640==0x280 alloc is an EXACT fit (zero headroom — any Torso/Watcher growth must bump the factory alloc); StatusMessagePool->New() at btplayer.cpp:460 derefs a NULL stub pool (latent); mechdmg.cpp:289 leaks IntegerPlugs into a no-op DZIndexTable::Add. -**✅ RESOURCE-LAYOUT AUDIT — DONE (full report: `btbuild/RESOURCE_AUDIT.md`; commits 802a7a6/7de66ad/975a397).** +**✅ RESOURCE-LAYOUT AUDIT — DONE (full report: `docs/RESOURCE_AUDIT.md`; commits 802a7a6/7de66ad/975a397).** A 33-agent adversarial audit of all 24 `*__SubsystemResource` structs found **8 confirmed layout bugs** (same silent-garbage class as the heat fix), all rooting to 2 broken base resources (`HeatWatcher`, `PowerWatcher`) + 2 field defects (`Gyroscope`, `Searchlight`). Raw-decomp-verified + FIXED: **HeatWatcher re-based onto