Cockpit: GENERATOR POWER ROUTING -- assign weapons to generators (task #12)
The pilot's second heat-management tool: the PoweredSubsystem message table
@0x50F4EC (ids 4-8) registered and implemented -- SelectGeneratorA-D
(@004b099c..@004b0a74: FindGeneratorByNumber roster walk on generatorNumber
@0x1E0 -> AttachToVoltageSource re-tap with tap accounting -> modeAlarm
Connected) and ToggleGeneratorMode (@004b0abc: Manual -> Auto -> detach+Manual
cycle). Weapons inherit via the MechWeapon handler chain. Desktop: F5-F8
assign the selected weapon (BT_CONFIG_SLOT) to Generator A-D, F9 toggles
reconnect mode; BT_GENSEL_TEST scripts a headless verify.
Verified live end-to-end: dispatch -> handler -> re-tap ("PPC_1 ->
GeneratorD (tapped)") -> the charging I^2R physically moved (GenD cold ~90K
baseline -> ~1570K carrying the PPC; GenA relieved), stable over a sustained
autofire soak with thermal-breaker trips.
FOUR defects found and fixed on the way [all T1/T2]:
- THE e17 HEAT EXPLOSION: Generator::SourceLevel misread *(this[0x38]+0x158)
as linkedSinks->heatEnergy; it is the engine-base DamageZone @0xE0 ->
damageLevel [0..1] (the same named-member pattern as the bank radiator's
zone read). A breaker-restarting generator emitted (1 - 4e8) x 10000
volts; squared through the customers' I^2R feed, one restart blew the
whole thermal network to e17. Authentic: a damaged generator yields
proportionally less voltage.
- FUN_004ac9c8 is NOT "IsDamaged": raw body = owner -> mech+0x190 player ->
roleClassIndex(+0x274) == 0 -- the ROOKIE-role lockout for advanced
cockpit systems. New bridge BTPlayerRoleLocksAdvanced (NULL player =
unlocked [T3]; bring-up role 2 = unlocked). The old stand-in gated the
handlers off permanently (healthy subsystems have simulationState==1).
- MESSAGE_ENTRY tables must be FUNCTION-LOCAL statics inside the accessor:
as namespace-scope arrays they are read by other TUs' static-init chains
before their own initializers run -- Build copies zeros and every id in
the table is silently dropped (ids 9/10 only worked by TU-order luck;
both tables relocated; gotcha recorded, reconstruction-gotchas #9).
- The AutoConnect hunt scanned GetSegment() -- the raw @004b0bd0 walks the
subsystem ROSTER (+0x124/+0x128); EntitySegments were being cast to
Subsystems (the classic +0x128 gotcha).
Also: the dense handler table's GAP slots (skipped ids) are uninitialized
heap -- the name-based Find strcmp-walks them and AVs; diagnostic probes use
the id-based Find only (the 1995 binary's own tables carry the same holes).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
092408041c
commit
d7b900d108
@@ -175,8 +175,29 @@ authentic path scoped.
|
||||
the only MechWeapon attribute" claim was wrong (fixed in mechweap.hpp).
|
||||
* Tails: weapon+0x110 (write 0/-1 on session open/close; port name vitalSubsystemIndex)
|
||||
has NO confirmed reader yet; @004d1acc (+0x48 L4 Notify override) is unexported —
|
||||
re-export from Ghidra; the PoweredSubsystem generator-select handlers (ids 4-8,
|
||||
@004b099c..@004b0abc) are decoded but not yet registered in the port.
|
||||
re-export from Ghidra.
|
||||
* **Task #12 (2026-07-11) [T2]: the PoweredSubsystem POWER-ROUTING handlers landed** --
|
||||
ids 4-8 registered (table @0x50F4EC): SelectGeneratorA-D = FindGeneratorByNumber
|
||||
(@004b0b18 ROSTER walk matching generatorNumber@0x1E0) -> AttachToVoltageSource ->
|
||||
modeAlarm=Connected; ToggleGeneratorMode (@004b0abc) = <2 -> AutoConnect, ==2 ->
|
||||
Detach + ManualConnect. Weapons inherit via the MechWeapon handler chain (the old
|
||||
qualified GetMessageHandlers() calls silently resolved to the engine Receiver ROOT
|
||||
set -- same trap as the task #6 weapon handlers). The AutoConnect hunt's
|
||||
GetSegment() scan corrected to the subsystem ROSTER (the +0x128 gotcha). Desktop:
|
||||
F5-F8 assign the selected weapon (BT_CONFIG_SLOT) to Generator A-D, F9 toggles
|
||||
Manual/Auto; BT_GENSEL_TEST scripts a headless re-tap. Note: Myomers/Sensor still
|
||||
chain the root set (their binary tables unverified) -- extend if aux maps prove
|
||||
they receive these ids. TWO MORE TRAPS found landing this: (a) MESSAGE_ENTRY
|
||||
tables must be function-local statics INSIDE the accessor (cross-TU static-init
|
||||
order emptied the table -- see [[reconstruction-gotchas]] #9 last bullet); (b)
|
||||
**FUN_004ac9c8 is NOT IsDamaged** -- raw body: `owner(+0xD0) -> mech+0x190 player
|
||||
-> roleClassIndex(+0x274) == 0` = the ROOKIE-role lockout for advanced cockpit
|
||||
systems (port bridge BTPlayerRoleLocksAdvanced, btplayer.cpp; NULL player =
|
||||
unlocked [T3]; bring-up role defaults to 2 = unlocked). AUDIT TAIL: the other
|
||||
powersub.cpp sites annotated FUN_004ac9c8 (the coolant-draw gate ~:427,
|
||||
ForceShortRecovery ~:444, the Generator/PowerWatcher site ~:1085) still call the
|
||||
heat-family IsDamaged (simulationState != 0) stand-in -- each needs its raw fn
|
||||
re-checked and swapped to the role bridge where the binary calls 4ac9c8.
|
||||
- **Myomers authentic coupling** — the structural un-stub is INERT (mover feed + heat-gen no-op).
|
||||
Real coupling needs the advanced-damage gate (`OwnerAdvancedDamage`/`FUN_004ad7d4` → the owning
|
||||
**BTPlayer** `mech+0x190`+0x260, NOT 0xBD3 — see the mech+0x190 item above) + `MoverAttach` routing
|
||||
|
||||
@@ -160,6 +160,18 @@ real PoweredSubsystem). Keep the alloc SIZE + special-cache when swapping a fact
|
||||
Receiver::NextMessageID` early branch does NOT save you — it lacks a `return`, and the console IDs
|
||||
aren't in that range anyway.) [T2]
|
||||
|
||||
- **MESSAGE_ENTRY tables must be FUNCTION-LOCAL statics inside the GetMessageHandlers()
|
||||
accessor** (task #12). A namespace-scope `HandlerEntry MessageHandlerEntries[]` can be read
|
||||
by ANOTHER TU's static-init chain (DefaultData -> accessor -> Build) before its own TU's
|
||||
dynamic initializers run -- Build copies ZEROS, and every id in that table is silently
|
||||
dropped at dispatch (the set LOOKS built; ids added later in the chain still work, which
|
||||
hides it). Symptom: message transmitted, handler never runs, no error. The engine's own
|
||||
APP.cpp idiom (table + set both function-local in the accessor) is init-order-proof --
|
||||
always use it. Related trap: the dense handler table (Build indexes slots by id-1) leaves
|
||||
GAP slots (skipped ids) as uninitialized heap -- the NAME-based `Find(const char*)`
|
||||
strcmp-walks every slot and AVs on a gap's garbage entryName (the id-based Find is safe).
|
||||
The 1995 binary's own tables carry the same holes. [T2]
|
||||
|
||||
## 10. Container-Execute must override (gauges)
|
||||
|
||||
The 2007 engine `Gauge::Execute` base is `Fail("not overridden")` → `abort()` (GAUGE.cpp:598);
|
||||
|
||||
Reference in New Issue
Block a user