docs: root-cause the heat-leaf byte-exactness gap (P7)

Record the measured/decompiled diagnosis of the systemic heat-leaf layout gap
(auxScreenNumber compiles to 0x194 vs binary 0x1DC, -72): duplicate temps +
spurious heatState/heatModelFlag (really alarm-internal) + SubsystemConnection
4->0xC + HeatAlarm 8->0x54 (AlarmIndicator confirmed 0x54; HeatFilter already
byte-exact).  Includes the offsetof-probe measurement technique.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-07 08:33:09 -05:00
co-authored by Claude Opus 4.8
parent dc6af8cef6
commit 16ad741282
+40
View File
@@ -197,3 +197,43 @@ would trip it). (2) The im2 scenario re-run fast: **3601 shots + 10.6 km walked*
**Durable lesson (systemic checklist entry):** an owner offset `+0x128` in subsystem raw decomp is the
subsystem ROSTER (`subsystemArray`), NOT the segment table — audit every `GetSegment(int)` call in
reconstructed subsystem ctors (only these two existed; both fixed).
## P7 — Heat-leaf subsystem byte-exactness (the systemic layout gap) ⭐ NEW (root-caused this session)
The reconstruction's **heat-leaf branch** (`HeatableSubsystem:MechSubsystem` -> `HeatSink` -> `PoweredSubsystem`
-> the weapon/sensor leaves) is **NOT byte-exact to the binary** -- measured: `PoweredSubsystem::auxScreenNumber`
compiles to **0x194** but the binary has it at **0x1DC** (72 bytes short). Consequence: any code reading a
heat-leaf subsystem field at a RAW binary offset above the gap gets garbage (this is what forced the aux-screen
BRIDGE in vehicleSubSystems, and the Sensor RadarPercent gauge stub, and blocks authentic data on the
engineering-screen cluster panels' secondary lamps). Fixing it byte-exact makes ALL raw reads correct
everywhere -> a high-leverage foundational fix.
**Root cause (measured + decompiled this session, authoritative):**
- `MechSubsystem` base + `HeatableSubsystem` (currentTemperature@0x114 / degradationTemperature@0x118 /
failureTemperature@0x11C / heatLoad@0x120) are byte-exact.
- `HeatSink` accumulates a **+16 over-allocation** from two RECONSTRUCTION LAYOUT ERRORS:
1. HeatSink RE-DECLARES `degradationTemperature`/`failureTemperature` that already exist in HeatableSubsystem
(a shadow/duplicate, +8).
2. `heatState`/`heatModelFlag` are modeled as SEPARATE HeatSink fields (+8) but in the binary they are
**INSIDE the heatAlarm** -- `heatState` is read at `this[0x61]==0x184 == heatAlarm@0x170 + 0x14` (the
alarm's level field). So they are modeling errors: heatState reads should be `heatAlarm.GetLevel()`.
- Then two **type-size under-allocations**: `SubsystemConnection` is 4B but the binary's is **0xC** (built by
`FUN_004af9cf`); `HeatAlarm` (heat.hpp) is 8B but the binary's alarm at 0x170 is a **0x54 `AlarmIndicator`**
(ctor `FUN_0041b9ec` @part_002.c:4767 = base `FUN_004178cc` + three 0x14-byte `FUN_0041c42c` sub-objects at
+0x18/+0x2C/+0x40, ending 0x54). `HeatFilter` is ALREADY 0xC (byte-exact -- NO reimplement needed; earlier
fear of a behavior-risk filter change was WRONG).
- Net at `PoweredSubsystem::auxScreenNumber`: +8 (dup temps) +8 (spurious heatState/heatModelFlag) -8
(SubsystemConnection) -76 (HeatAlarm) -4 (a PoweredSubsystem delta) = **-72**.
**The fix = a byte-exact re-base of the heat-leaf chain:** remove the duplicate temps; remove the spurious
heatState/heatModelFlag and re-point their reads to `heatAlarm.GetLevel()`; grow `SubsystemConnection` 4->0xC
and `HeatAlarm` 8->0x54 (as shared 0x54/0xC types used everywhere the binary has them, WITHOUT breaking the
already-byte-exact Watcher branch which uses separate `WatcherGaugeAlarm`/`WatchedConnection`); fix the
PoweredSubsystem -4. It touches the core classes every heat/power/weapon subsystem derives from (large blast
radius) + includes CODE changes (heatState), so it needs a full at-risk-read audit (raw `this+0xNN` reads
calibrated to the CURRENT compiled layout would break) + exhaustive combat/heat verification. Safety revert
point tagged `pre-heatleaf-rebase`. The `heat-leaf-layout-audit` workflow derives the full plan.
MEASUREMENT TECHNIQUE (reusable): a `template<int N> struct HSOff;` + `friend struct XProbe;` +
`struct XProbe { HSOff<offsetof(Class, field)> a; ... };` -- the "uses undefined struct 'HSOff<NNN>'" build
error reports each field's COMPILED offset in decimal. Compare to the binary offset from the ctor decomp.