P7: byte-exact re-base of the CORE heat leaf (HeatSink/Condenser/Reservoir/Generator/Myomers)
The reconstruction modeled the binary's shared alarm/connection types with undersized
stand-ins, sliding every field above them low (the 72-byte auxScreenNumber gap). Fix the
foundational heat-leaf classes byte-exact + static_assert-lock them, from the ctor decomp:
Shared types corrected:
* SubsystemConnection 4 -> 0xC (binary link node FUN_004af9cf; FUN_00417ab4 derefs +8)
* GaugeAlarm54 = 0x54 (real AlarmIndicator FUN_0041b9ec; STATUS level at +0x14,
so subsystem+0x184 == heatAlarm+0x14 == GetLevel())
WatcherGaugeAlarm now typedefs GaugeAlarm54 (Watcher branch locks stay valid).
Byte-exact + locked (ctor-verified):
* HeatSink heatEnergy@0x158 linkedSinks@0x164 heatAlarm@0x170 resource@0x1C4
pendingHeat@0x1C8, sizeof 0x1D0 (@004adda0)
* Condenser valveState@0x1D0 condenserAlarm@0x1DC (@004ae568)
* Reservoir reservoirAlarm@0x1D0 ... squirtEfficiency@0x22C, sizeof 0x230 (@4aef78)
* Generator stateAlarm@0x1FC, sizeof 0x250 (@004b225c)
* Myomers phantom moverConnection tail removed (fits 0x358)
Three systemic bug classes fixed (added to the checklist in CLAUDE.md / HARD_PROBLEMS.md):
* alias field - a subclass member re-declaring an inherited slot the ctor reuses
(Condenser refrigerationOutput==massScale@0x160; Reservoir
coolantCapacity==thermalCapacity@0x128) -> use the inherited name
* alarm-interior - a value read at alarm+0x14 modeled as a separate member
(HeatSink heatState@0x184, Reservoir injectActive@0x1e4)
-> route to alarm.GetLevel()
* phantom field - a member past the object end (Generator shortFlag@0x25C is really
*(owner+0x190)+0x25c the msg-manager, @004b0efc; Myomers
moverConnection@0x110 a write-only base slot) -> remove it
Heat conduction now reads the REAL heatEnergy=1.34e7 (not garbage); combat DESTROYED-in-8,
0 crashes, heapcheck-clean through construction.
REMAINING (measured; a distinct larger task): making PoweredSubsystem byte-exact grows it
+0x98 and cascades into MechWeapon/Emitter/PPC/Sensor/Myomers -- all model the 0x54
AlarmIndicator with 4-byte ReconAlarm / 8-byte HeatAlarm stand-ins and are short +
phantom-tailed; retyping without byte-exacting them overflows the Emitter alloc (heap
corruption). PoweredSubsystem kept on HeatAlarm(8) stand-ins (marked) pending a
subsystem-tree ALARM UNIFICATION. See docs/HARD_PROBLEMS.md P7.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
16ad741282
commit
1356870e56
@@ -237,3 +237,38 @@ point tagged `pre-heatleaf-rebase`. The `heat-leaf-layout-audit` workflow derive
|
||||
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.
|
||||
|
||||
### P7 — STATUS: the CORE heat leaf is DONE + byte-exact; PoweredSubsystem + the weapon subtree are a larger follow-up
|
||||
|
||||
**✅ DONE this session (byte-exact, static_assert-LOCKED, combat+heat verified):** `HeatSink`,
|
||||
`HeatableSubsystem`, `Condenser`, `Reservoir`, `Generator` (a HeatSink subclass, alloc 0x250) + `Myomers`
|
||||
(phantom tail removed). The shared types are now correct: **`SubsystemConnection` = 0xC** (was 4; the binary
|
||||
`FUN_004af9cf` link node, `FUN_00417ab4` two-level derefs +8) and **`GaugeAlarm54` = 0x54** (the real
|
||||
`AlarmIndicator` from `FUN_0041b9ec`; its STATUS level is at **+0x14**, so `subsystem+0x184 == heatAlarm+0x14
|
||||
== GetLevel()`; `WatcherGaugeAlarm` is now a typedef of it). Confirmed from the ctors: `HeatSink` heatEnergy@0x158,
|
||||
linkedSinks@0x164, heatAlarm@0x170, resource@0x1C4, pendingHeat@0x1C8, sizeof **0x1D0** (ctor @004adda0);
|
||||
`Condenser` valveState@0x1D0, condenserAlarm@0x1DC (ctor @004ae568); `Reservoir` reservoirAlarm@0x1D0,
|
||||
sizeof **0x230** (raw @4aef78); `Generator` stateAlarm@0x1FC, sizeof **0x250** (ctor @004b225c). Heat conduction
|
||||
now reads the REAL `heatEnergy=1.34e7` (not garbage); combat DESTROYED-in-8, 0 crashes, heapcheck-clean through
|
||||
construction. `heatState`/`heatModelFlag`/`field_1d0` deleted (reads -> `heatAlarm.GetLevel()` / `coolantActive`);
|
||||
several **alias-field bugs** fixed the same way (Condenser `refrigerationOutput`==inherited `massScale@0x160`;
|
||||
Reservoir `coolantCapacity`==inherited `thermalCapacity@0x128`, `injectActive`==`reservoirAlarm.GetLevel()`) and
|
||||
**phantom fields** removed (Generator `shortFlag@0x25C` -- really `*(owner+0x190)+0x25c`, the msg-manager, raw
|
||||
@004b0efc; Myomers `moverConnection@0x110` -- a write-only base slot).
|
||||
|
||||
**◐ REMAINING (the newly-measured true scope -- a SYSTEMIC alarm-stand-in unification, NOT a heat-only fix):**
|
||||
making **`PoweredSubsystem`** byte-exact (its two 0x54 alarms `electricalStateAlarm@0x264`/`modeAlarm@0x2B8`)
|
||||
grows it **+0x98**, which cascades into EVERY subclass -- `MechWeapon`, `Emitter`, `PPC`, `Myomers`, `Sensor` --
|
||||
and they ALL model the binary's 0x54 `AlarmIndicator` with 4-byte `ReconAlarm` (`weaponAlarm`) or 8-byte
|
||||
`HeatAlarm` stand-ins, so they are themselves short AND carry phantom/duplicate/misplaced tail fields
|
||||
(measured: `MechWeapon` 0x3C4 vs binary 0x3F0 with ~0x24 of phantom tail; `Emitter` 0x4B0 vs binary 0x478 with
|
||||
a duplicate `outputVoltage`==`rechargeLevel@0x320` + ~0x64 of oversized own fields). Retyping PoweredSubsystem's
|
||||
alarms WITHOUT also byte-exacting MechWeapon/Emitter/PPC overflowed the Emitter factory alloc (0x478) -> a heap
|
||||
corruption during Emitter construction. So PoweredSubsystem was kept on `HeatAlarm(8)` stand-ins (marked in
|
||||
powersub.hpp) and the whole tree still fits its allocs. **The real fix is a subsystem-tree ALARM UNIFICATION:
|
||||
retype every binary-`AlarmIndicator` stand-in (ReconAlarm/HeatAlarm) to `GaugeAlarm54(0x54)` and de-phantom
|
||||
each weapon/power class against its ctor** (MechWeapon @004b99a8, Emitter @004ba478, PPC, Sensor). Each class
|
||||
needs: alarm retype + phantom/alias-field removal + a `static_assert` sizeof/offset lock vs its factory alloc.
|
||||
This is a multi-class effort (a separate task, bigger than the heat leaf) -- the core heat leaf above is the
|
||||
foundational prerequisite and is complete. Same techniques apply (ctor decomp -> offsets, alias/phantom checks,
|
||||
`friend struct XLayoutCheck` locks). The aux-screen gauge reads + Sensor RadarPercent stay approximate until then.
|
||||
|
||||
Reference in New Issue
Block a user