Files
BT411/context/subsystems.md
T
arcattackandClaude Opus 4.8 82e6bb306a KB: sweep STALE "unfinished" claims -> match landed commits (context-system audit)
4-agent audit cross-checked every open/pending/stub/deferred claim in the context
system against git + code. Fixed ~13 stale spots (currency only, no code change),
each contradicted by its own file body + a landed commit:

- 0xBD3 SubsystemMessageManager (task #7, afefaee): subsystems.md frontmatter+body
  line 57; decomp-reference.md 0xBD3 row + +0x434 row -- all still said
  "MISLABELS controlsMapper / WAVE 8 untangle" (done; mech.hpp names it messageManager).
- Cylinder hit-location STEP 6 (d07ac7d): combat-damage.md frontmatter;
  decomp-reference.md "not reconstructed" line.
- Per-mech turn-rate wiring (task #64b, a83995a): multiplayer.md + locomotion.md
  frontmatter (still "bring-up constant / not yet wired").
- Mech-level update records (task #1, c9f0c2a): open-questions.md "dead Wword
  branches mech.cpp:1511/1613" (those branches are gone; named fields now).
- Collision damage + DeathShutdown (2026-07-08/12): combat-damage.md frontmatter.
- Myomers un-stub (8b36440): decomp-reference.md "INERT un-stub" row.
- Day/night BT_MATPRI (shipped, default-on): rendering.md frontmatter (LOD half kept).
- Fire-trigger path (task #5, 8ed6184): open-questions.md "still gBTWeaponTrigger
  bring-up" (globals retired/never-read).
- HEAT entry FACTUAL fix: "heatLoad -> effectiveRange 0 = overheat cutout" was false
  per aab7a8a -- effectiveRange reads host-zone damage; the real cutout is the
  FailureHeat charge-hold.

Frontmatter open_questions re-pointed at genuinely-open items. VERIFIED NOT stale
(left as-is): multiplayer body-channel-projection notes (a real open [T3] residual
per the coupled-motion section's ~2.9u leg-vs-body snap). Genuinely-open items
(factory roster loops 2-4, subsystem-panel gate, missile cluster, console-death
freeze, gyro tails, etc.) untouched. checkctx CLEAN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 14:35:41 -05:00

109 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: subsystems
title: "Subsystems — the factory + the reconstruction waves"
status: established
source_sections: "PROGRESS_LOG.md §10d; docs/SUBSYS_PLAN.md; docs/VEHICLE_SUBSYSTEMS.md; docs/RESOURCE_AUDIT.md"
related_topics: [decomp-reference, reconstruction-gotchas, combat-damage, gauges-hud]
key_terms: [subsystem, factory, ClassID, subsystem-roster, PoweredSubsystem, bridge]
open_questions:
- "Myomers coupling (gates on owning-player @mech+0x190); factory capability-roster loops 2-4 still dead (SubProxy stub)"
---
# Subsystems
The mech's components (heat/power/weapons/sensor/gyro/torso/myomers/…), built by the Mech-ctor
factory. Full per-family plan: `docs/SUBSYS_PLAN.md`; the engineering-cluster panels:
`docs/VEHICLE_SUBSYSTEMS.md`; the layout audit: `docs/RESOURCE_AUDIT.md`. ClassID map:
[[decomp-reference]] §2.
## The factory
The Mech ctor switches on the resource ClassID to build each subsystem into the [[subsystem-roster]]
(`subsystemArray@0x128`). **The `case <Name>ClassID` LABELS are systematically MISLABELED** — the
real class is the `// FUN_004xxxxx` ctor-address comment reconciled via `CLASSMAP.md`, not the case
name (e.g. 0xBBE case="Sensor" is actually AggregateHeatSink). Each real class is wired via a
`Create<Class>Subsystem(Mech*,int,void*)` **bridge** in the class's own `.cpp` (do NOT `#include` the
real subsystem headers into mech.cpp — the local stubs collide). Keep the alloc SIZE + special-cache.
[T2]
## Class hierarchy (two branches, shared only at MechSubsystem)
- **Heat leaf:** `PoweredSubsystem : HeatSink : HeatableSubsystem : MechSubsystem`. Emitter/PPC/
Sensor/Myomers/ProjectileWeapon/MissileLauncher/GaussRifle chain here. Uses 0xC `SubsystemConnection`
+ 0x54 `GaugeAlarm54` (alarm level at +0x14). [T1]
- **Watcher branch:** `Torso/Gyroscope/Searchlight/ThermalSight/HUD : PowerWatcher : HeatWatcher :
MechSubsystem`; `AmmoBin : HeatWatcher`. Uses a 0xC `WatchedConnection` + 0x54 `WatcherGaugeAlarm`. [T1]
Making a base byte-exact GROWS every subclass — they must be re-based TOGETHER in one build, each
`static_assert`-locked (the P7 alarm-unification: HeatSink 0x1D0 → PoweredSubsystem 0x31C → MechWeapon
0x3F0 → Emitter 0x478). [T2]
## Reconstruction waves (state: ALL 20 factory cases wired to real classes — 0xBD3 = the real SubsystemMessageManager since task #7, 2026-07-11; the mapper lives in roster slot 0)
- **WAVE 1** — HeatableSubsystem re-based onto MechSubsystem (de-shadow cascade).
- **WAVE 2** — heat family (Condenser/AggregateHeatSink/Reservoir) + HUD + MechTech (un-swap).
- **WAVE 3** — power bus (Generator/PoweredSubsystem) + Emitter/PPC fire-path (end-to-end fire; heat
conducts to the central sink via the linked-sink roster).
- **WAVE 4** — standalone readouts: Sensor/Searchlight/ThermalSight/AmmoBin (de-shim, gate fixes).
- ⚠ **Searchlight has an ORIGINAL latent bug [T1, task #63]:** `SearchlightSimulation` (@004b841c)
reads `requestedOn`@0x1E0 (never written) while `ToggleLamp` (@004b860c) toggles `commandedOn`@0x1DC
— no bridge, so `lightState`@0x1D8 is perpetually 0 (lamp never lights). Present in the 1995 binary
(sibling ThermalSight reads the field it toggles, 0x1DC); the port reproduces it faithfully. Left
as-is by decision; it makes the searchlight→fog swap inert. See [[open-questions]] + [[rendering]] fog.
- **WAVE 5** — Torso (aim twist/elevation; joint-I/O reconstructed; the BLH record disables torso →
faithfully no visible twist).
- **WAVE 6** — Myomers (mover-coupled; structural un-stub is INERT — no live mover/heat coupling).
- **WAVE 7** — projectile/missile weapons (byte-exact; flying projectiles are a PORT reconstruction —
the 2007 Entity is 0x1BC vs the binary's 0x300, so raw base-offset reads fail).
- **TASK #56 (2026-07-11)** — Gyroscope LIVE byte-exact (ctor @004b3778, sizeof 0x3D0 locked;
integrators + `FUN_004b2980` damage fan-out; joint dispatch from the Mech performance tail
@0x4aaf74/83; `BT_GYRO_LOG`/`BT_GYRO_TRACE`) — see [[cockpit-view]].
- **✅ DONE (task #7, `afefaee`)** — SubsystemMessageManager 0xBD3 (a
**damage/explosion consolidation hub** cached to `Mech[0x10d]`=0x434; the factory builds the REAL
class and `mech.hpp` names the slot `messageManager` — the old `controlsMapper` mislabel is swept,
the real mapper is roster slot 0. NOT the valve/advanced-damage gate — that's the owning **BTPlayer**
@mech+0x190, see [[combat-damage]]/[[open-questions]]). [T2]
## The watcher electrical chain (task #57, 2026-07-13 — the torso power gate)
The Watcher branch is POWERED indirectly: a watcher WATCHES another roster subsystem and mirrors
its electrical state. The full chain, byte-verified [T1]:
- **Data:** the model entry `WatchedSubsystem=<name>` → segment index **+2** at resource+0xE4
(`HeatWatcher::CreateStreamedSubsystem` @004aec54); the ctor @004aeb40 stores it at
watcher+0x128 (`watchedSubsystem`).
- **Bind (factory post-roster loop 1):** vtable slot 14 (+0x38) — `@004aee2c` (HeatWatcher) /
`@004b1a40` (PowerWatcher/Torso override, byte-identical); **Ghidra missed both function
starts** (recovered from raw bytes; the vtables.tsv rows have GAPS where the exporter skipped
slots — dump the exe bytes at vtable+slot*4 when a slot looks missing). Master-gated
(`(owner->simulationFlags & 0xC)==0 && (flags & 0x100)`); binds `watchedLink(+0x114).Add(
owner->roster[+0x128][watchedSubsystem])`. Port: `BTWatcherWatchedIndex`/`BTWatcherBindTarget`
bridges (heatfamily_reslice.cpp) called from the mech.cpp factory loop.
- **Tick:** `@004b181c` = the REAL `PowerWatcher` Performance (PTR @0050f5fc → 004b181c) =
`UpdateWatch()`: heat mirror (FUN_004aeac4) + `watchdogAlarm.SetLevel(watched->electrical
level @+0x278)` + brownout downgrade to 1 when `gen->outputVoltage(+0x1DC) <= minVoltage(+0x180)
× gen->ratedVoltage(+0x1D8)`. The Torso sims (@004b5cf0/@004b65f8) call it first-line.
(`@004b1804` is slot-10 **ResetToInitialState**, NOT the Simulation — old recon mislabel, fixed.)
- **MinVoltageScale = 0.01** — a 10-byte x87 literal at 0x4b1924 (`0a d7 a3 70 3d 0a d7 a3 f8 3f`);
the port had 1.0f, making minVoltage 100× too big → the brownout latched every watchdog at 1.
- **PowerWatcher::GetClassDerivations chains HeatWatcher** (real base) — the old HeatableSubsystem
stand-in broke `IsDerivedFrom(HeatWatcher)` for Torso/Searchlight/ThermalSight and silently
skipped them in the connect pass.
- **Effect:** `Torso::ElectricalStateLevel()==Ready(4)` un-gates `effectiveTwistRate` — the MadCat
torso twists at its authored 50°/s (±140° limits, roster 17 watching 15 → generator @10000V);
the BLH is authentically fixed (`horizontalEnabled=0`, limits ±0.01°). [T2 live-verified]
- **STILL DEAD:** factory loops 2-4 (heatable/weapon/damageable capability rosters) go through the
`SubProxy` stub whose `IsDerivedFrom` returns 0 — they add NOTHING. See [[open-questions]].
## The four systemic checks (every subsystem)
See [[reconstruction-gotchas]]: (1) shadowing (re-declared engine-base fields), (2) the `Wword` trap,
(3) message-handler chaining, (4) entity validity. Plus resource-struct layout (must mirror the class
hierarchy, byte-exact — the RESOURCE_AUDIT found 8 bugs) and object-layout (alias/phantom/interior
fields). A `+0x128`-style owner offset is the ROSTER, not the segment table (the heat-link type
confusion that caused a heap-corruption via OOB `ConductHeat` writes). [T2]
## Engineering cluster panels (`vehicleSubSystems`)
Not a widget — a per-subsystem FACTORY (`FUN_004cbaf0`) building a status CLUSTER onto one of 12 aux
MFD positions, dispatching on classID → HeatSinkCluster/MyomerCluster/EnergyWeaponCluster/
BallisticWeaponCluster. Reads `PoweredSubsystem::auxScreenNumber/Placement/Label` (res +0x104/8/C) via
the `BTGetSubsystemAuxScreen` bridge. See `docs/VEHICLE_SUBSYSTEMS.md` + [[gauges-hud]]. [T2]
## Key Relationships
- Data: [[decomp-reference]] (ClassIDs/hierarchy). Bugs: [[reconstruction-gotchas]].
- Feeds: [[combat-damage]] (weapons/damage), [[gauges-hud]] (attribute state).
- Plan: `docs/SUBSYS_PLAN.md`.