From 1746c5bb1f431e41191cd785b45b085baf38d390 Mon Sep 17 00:00:00 2001 From: arcattack Date: Mon, 6 Jul 2026 21:17:52 -0500 Subject: [PATCH] docs: record the map (radar) gauge as done + its follow-ups GAUGE_COMPOSITE.md + CLAUDE.md: add the map/MapDisplay radar (increment 6, the view wedge renders) to the done list; note the systemic pattern (a newly-consumed reconstructed gauge is the first reader of stubbed helpers -- the map exposed 3); narrow the remaining gauge widgets to PlayerStatus + vehicleSubSystems, and list the map follow-ups (contact classification / stubbed pip+name infra, SetTargetRange zoom). Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 25 ++++++++++++++++--------- docs/GAUGE_COMPOSITE.md | 28 +++++++++++++++++++++------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 01a7453..c58a89f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -711,15 +711,22 @@ gap slots uninitialized and `Find` strcmps EVERY slot → a published table MUST `NextAttributeID`; fill gaps with a shared read-only pad member.** Done: **HeatSink table** (`CurrentTemperature` → Heat readout shows 77), **Mech table** (dense prefix 0x15..0x21, `LinearSpeed` → SPEED readout shows ~225), **vertBar** (coolant bars; x87 pixel math recovered by disassembly), **segmentArcRatio** (speed arc; thin subclass -of engine `SegmentArc`), and **oneOfSeveralPixInt** (the button-state lamps — reconstructed the whole OneOfSeveral -strip-selector family + PixMap8 blit path). **Base primitives `numeric`/`numericSpeed`/`digitalClock`/`rankAndScore` -are ENGINE (L4GAUGE.cpp) — only need the data; `vertBar`/`segmentArcRatio`/`oneOfSeveralPixInt`/`map`/`PlayerStatus`/ -`vehicleSubSystems` are BT-specific (reconstruct + register).** Technique added: `tools/disas2.py ` -(recover FPU math Ghidra drops — `FUN_004dcd94`=round, `FUN_004dcd00`=fabs) + `tools/vtdump.py ` -(find a vtable override the assert-anchored decomp didn't export). REMAINING: `map` (radar — the marquee, needs the -Mech table extended to 0x31 + a Sensor table + the `MapDisplay` renderer), `PlayerStatus`, `vehicleSubSystems` -(task #13) + the aggregate HeatSink-bank `AmbientTemperature` (`#if 0`'d 0xBBE) + the Reservoir `coolantCapacity` -shadow + making the duck/searchlight buttons dynamic (extend the Mech table to 0x37 + a Searchlight table). +of engine `SegmentArc`), **oneOfSeveralPixInt** (the button-state lamps — reconstructed the whole OneOfSeveral +strip-selector family + PixMap8 blit path), and **map** (the RADAR / tactical display — the marquee; the MapDisplay +renderer was already reconstructed, so this was the registration glue + data: the Mech table extended to the full +0x15..0x38 with the radar Point3D*/Quaternion* attributes + a Sensor "Avionics"/RadarPercent table + a reconstructed +`MapDisplay::Make`/`methodDescription`; renders the FOV view wedge live). **Base primitives `numeric`/`numericSpeed`/ +`digitalClock`/`rankAndScore` are ENGINE (L4GAUGE.cpp) — only need the data; `vertBar`/`segmentArcRatio`/ +`oneOfSeveralPixInt`/`map`/`PlayerStatus`/`vehicleSubSystems` are BT-specific (reconstruct + register).** Technique +added: `tools/disas2.py ` (recover FPU math Ghidra drops — `FUN_004dcd94`=round, `FUN_004dcd00`=fabs) + +`tools/vtdump.py ` (find a vtable override the assert-anchored decomp didn't export). **⚠ SYSTEMIC PATTERN +(map): a newly-consumed reconstructed subsystem/gauge is often the FIRST reader of a stubbed helper — the map +exposed 3 (Sensor radarPercent negative from un-normalized heatEnergy; `ResolveOperatorEntity`→NULL; unguarded NULL +entity), each fixed with the established viewpoint-fallback/guard patterns.** REMAINING: `PlayerStatus`, +`vehicleSubSystems` (task #13) + the map's contact classification (0 contacts — the spatial-query `Get* +EntitiesWithinBounds` + the stubbed pip/name/video-object infra) + `SetTargetRange` (radar zoom, 500m default) + the +aggregate HeatSink-bank `AmbientTemperature` (`#if 0`'d 0xBBE) + the Reservoir `coolantCapacity` shadow + the +Searchlight `LightOn` table (duck button already resolves via the 0x37 Mech entry). **Alternate route considered:** run original `btrel410.exe` under DOSBox — **blocked**: it needs the VPX/IG board DOSBox can't emulate; bypassing it = the shim work anyway. diff --git a/docs/GAUGE_COMPOSITE.md b/docs/GAUGE_COMPOSITE.md index 070ed93..6ba7fea 100644 --- a/docs/GAUGE_COMPOSITE.md +++ b/docs/GAUGE_COMPOSITE.md @@ -406,6 +406,21 @@ fill the gaps (bind not-yet-needed ids to a shared read-only pad member). frame index; added the missing `OneOfSeveral::foregroundColor`@0x9C. Config binds duck/searchlight/ display-mode/piloting-mode buttons; `ControlsMapper/DisplayMode` resolves live, the rest degrade to frame 0 until their tables land. +6. **map** (MapDisplay, btl4rdr) — the RADAR / tactical display (the marquee). The renderer was already + reconstructed (Execute phases: bounds → gather static/moving entities → DrawViewWedge/DrawStatic/ + DrawMoving/DrawNames); only the registration glue + data were missing. Extended the Mech table to the + full 0x15..0x38 (RadarRange/RadarLinearPosition[Point3D*]/RadarAngularPosition[Quaternion*]/DuckState; + `AttributePointer`=`int Simulation::*` so the ATTRIBUTE_ENTRY reinterpret binds pointer members), + published the Sensor("Avionics") RadarPercent table, and reconstructed `MapDisplay::methodDescription`+ + `Make` from the config (the "center"/"bottom" enum keyword typed as a STRING + converted in Make → no + ModeManager named-constant needed). Renders the view wedge (mech FOV cone) live. THREE pre-existing + stubs the map was the first consumer of, each fixed: Sensor `radarPercent` went negative (un-normalized + `heatEnergy` in the not-byte-exact heat-leaf → guarded to no-penalty); `ResolveOperatorEntity` returned + NULL (→ viewpoint fallback); `MapName::ExtractFromEntity` didn't NULL-guard the entity. ⚠ Debug via + `BT_MAP_LOG` (phase/draw trace). FOLLOW-UPS: contacts show 0 (the `GetStaticEntitiesWithinBounds`/ + `GetMovingEntitiesWithinBounds` classification finds nothing — the enemy dummy isn't in the spatial + lists); the pip/name/video-object infrastructure (`GetVideoObject`/`LookUpPip`/`GetNameID`) is stubbed + so contacts/labels need it; radarRange is a 500m default until `SetTargetRange` is un-stubbed. ### Reconstruction-technique additions (durable) - **x87 float math Ghidra drops** (`FUN_004dcd94()`/`FUN_004dcd00()` show no args = FPU-stack operands): @@ -425,10 +440,9 @@ fill the gaps (bind not-yet-needed ids to a shared read-only pad member). - Reservoir shadow: `Reservoir::coolantCapacity`@0x128 shadows the inherited `thermalCapacity` the gauge reads → `Reservoir/CoolantCapacity` reads the base default; fix = delete the shadow + write thermalCapacity in the Reservoir ctor (bundle with the Reservoir coolant-bar verification). -- ✅ **oneOfSeveralPixInt** DONE (increment 5 above). To make its `DuckState`/`Searchlight/LightOn` - buttons DYNAMIC (they read frame 0 today): extend the Mech dense table to 0x37 (DuckState@0x3f8) + add a - Searchlight `LightOn` table. -- Remaining widgets (task #13): `map` (radar — the marquee; needs the Mech dense table extended to 0x31 for - RadarRange/RadarLinearPosition/RadarAngularPosition + a Sensor `RadarPercent` table + the map/radar - renderer reconstruction, base `MapDisplay` in btl4rdr.cpp), `PlayerStatus` (comm/score, 8 uses), - `vehicleSubSystems` (26 uses). +- ✅ **oneOfSeveralPixInt** DONE (increment 5). The Mech table now reaches 0x37 so `DuckState` resolves; + `Searchlight/LightOn` still needs a Searchlight `LightOn` table to make that button dynamic. +- ✅ **map** DONE (increment 6) — renders the view wedge. FOLLOW-UPS: the spatial-query contact + classification (0 contacts today) + the stubbed pip/name/video-object infrastructure (contacts + labels) + + `SetTargetRange` (radar zoom, currently a 500m default). +- Remaining widgets (task #13): `PlayerStatus` (comm/score, 8 uses), `vehicleSubSystems` (26 uses).