docs: record the gauge attribute-wave (mechanism + 4 increments) + durable RE tools

Document the cockpit-gauge attribute-pointer system in GAUGE_COMPOSITE.md
(§Attribute wave) and CLAUDE.md §10: how a Subsystem/Attribute or bare-Attribute
binding resolves (ParseAttribute -> FindSubsystem/GetName -> GetAttributePointer
-> activeAttributeIndex), what a class must publish (AttributeID enum +
AttributePointers[] + GetAttributeIndex chained + DefaultData wiring), the
DENSE-TABLE HAZARD (Build leaves gap slots uninitialized, Find strcmps every
slot -> tables must be a dense prefix), and the base-primitive vs BT-specific
widget split.  Records the 4 committed increments (HeatSink table, Mech table,
vertBar, segmentArcRatio) and the follow-ups (oneOfSeveralPixInt/map/PlayerStatus/
vehicleSubSystems, the #if0'd HeatSink-bank AmbientTemperature, the Reservoir
coolantCapacity shadow).

Promote the two reverse-engineering helpers from the session scratchpad into
tools/ (durable): disas2.py (capstone + PE parse -- recovers x87 float math
Ghidra drops; FUN_004dcd94=round, FUN_004dcd00=fabs) and vtdump.py (dump a class
vtable to find an override the assert-anchored decomp never exported, e.g.
SegmentArcRatio::Execute).  Doc references updated scratchpad/ -> tools/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-06 18:52:53 -05:00
co-authored by Claude Opus 4.8
parent a2ee1181e6
commit c2c4ab1f67
4 changed files with 190 additions and 0 deletions
+23
View File
@@ -696,6 +696,29 @@ depth SMALLER than the RT is INVALID → all draws silently fail (window shows t
unbind depth (Z is off anyway), restore after. Pod `BuildWindows`/`Update` path byte-unchanged. REMAINING = the
widget recon (above) + the pod MFD port-name fallback.
**✅✅ GAUGE WIDGET RECONSTRUCTION — the cockpit instruments now read LIVE game state (attribute wave DONE;
full mechanism + technique in `docs/GAUGE_COMPOSITE.md` §Attribute wave).** After Milestone C put all 6
surfaces on screen (drawing NULL), two waves made them read real data. (a) The **ColorMapper family + headingPointer**
(prior session): the palette-tint schematics (`cmHeat`/`cmCrit`/`cmArmor`/`colorMapperMultiArmor`) + the rotating
compass, each a reconstructed BT gauge class registered in `BTL4MethodDescription[]` (btl4grnd.cpp). (b) The
**attribute wave** (this session, 4 commits): gauges bind to game state by NAME via the engine attribute-pointer
system — the config's `Subsystem/Attribute` (e.g. `HeatSink/CurrentTemperature`) or bare `Attribute` (e.g.
`LinearSpeed`) resolves through `ParseAttribute``FindSubsystem`(stricmp on `GetName()`)→`GetAttributePointer`
the class's `activeAttributeIndex`. A class publishes attributes by declaring an `<Name>AttributeID` enum + a
`static AttributePointers[]` (`ATTRIBUTE_ENTRY`) + `GetAttributeIndex()` chained to its parent, and passing
`GetAttributeIndex()` to its `DefaultData`. **⚠ DENSE-TABLE HAZARD (systemic): `AttributeIndexSet::Build` leaves
gap slots uninitialized and `Find` strcmps EVERY slot → a published table MUST be a dense prefix from the parent's
`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`). **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 <VA> <len>`
(recover FPU math Ghidra drops — `FUN_004dcd94`=round, `FUN_004dcd00`=fabs) + `tools/vtdump.py <vtVA> <n>`
(find a vtable override the assert-anchored decomp didn't export). REMAINING: `oneOfSeveralPixInt`/`map`/
`PlayerStatus`/`vehicleSubSystems` (task #13) + the aggregate HeatSink-bank `AmbientTemperature` (`#if 0`'d 0xBBE)
+ the Reservoir `coolantCapacity` shadow.
**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.