Gitea #47 COMPLETE: the ENG-button attention FLASH is live (jam / bay fire) -- MechTech status scan + BTL4GaugeAlarmManager + lamp chain, all from the binary
The pod behaviour Cyd described -- "on a jam or bay fire the display eng button
for the system flashes" -- is authored data + a five-stage chain, now running:
MechTech::TechnicalAssistance (@004ad33c, per frame)
edge-scans every monitored subsystem's GetStatusFlags() 7-bit condition
mask (TechStatusType: Destroyed 0, Damaged 1, CoolantLeaking 2,
Overheating 3, AmmoBurning 4, Jammed 5, BadPower 6)
-> Start/StopEntityAlarmMessage (@00436688 id 7 size 0x20 / @004366b8 id 8
size 0x1C; broadcast @004364e4; port shape: direct
Start/StopEntityAlarmImplementation calls on the gauge renderer)
-> GaugeAlarmManager::Activate(alarmModel) -- alarmModel = MechTech+0x100 =
the 'mechalrm' ModelList (id 83) -> SearchList(83, type 31) -> the baked
GaugeAlarmStream (id 331, 11 items {condition, lampCode}), decoded:
Destroyed -> gotoEngineering + engCooling + engBusMode
CoolantLeaking -> gotoEngineering + engCooling
AmmoBurning -> gotoEngineering + engEject
Jammed -> gotoEngineering + engEject
BadPower -> gotoEngineering + engBusMode
-> BTL4GaugeAlarmManager::ReadGaugeAlarmStreamItem -- THE REAL BODY, from
@004cc2fc + helpers @004cc108/148/1a0/264/27c + tables @0051cf1c..0x51d084
(gotoEngineering 0x80 = the subsystem's QUAD-SELECT bezel button via
lamp[aux]/mode[aux] tables; 0x81+ descend the eng-page bank; Condenser /
Generator specials on CoolantLeaking; <0x80 = the heat-bank fixed map).
btl4galm.cpp's old bodies were admitted fabrications and its provenance
note ("no override body exists in the image") was wrong -- corrected.
-> LampManager::FindLamp (@00444c80) -> Lamp::SetAlertState (@00444e64, a
COUNTER so stacked alarms hold the flash) -> L4Lamp::NotifyOfStateChange
emits RIO flashFast states 0x37/0x13 (== T0 L4LAMP.cpp:234-239) -> the
pod's physical lamps AND the glass panels (PadRIO IS rioPointer there).
FOUR load-bearing defects found and fixed en route -- each independently fatal
to the feature:
1. HeatableSubsystem's Derivation chained Subsystem directly, SKIPPING
MechSubsystem (written before the WAVE-1 re-basing) -- so EVERY subsystem
on both family branches failed IsDerivedFrom(MechSubsystem), which is
exactly MechTech's monitor filter: the status scan watched NOTHING.
2. MechSubsystem::GetStatusFlags was non-virtual (binary: vtable slot 12) --
the scan's MechSubsystem* call bound statically to the base tier and the
weapon bits could never surface.
3. ProjectileWeapon::GetStatusFlags sat in a Ghidra export gap -- raw-disasm
@004bbf88: base | 0x20 (weaponAlarm==5 Jammed) | 0x10 (linked bin
cookOffArmed@0x18C AmmoBurning). The port had "defer to base".
4. Mech::Reset's respawn sweep blanket-cast every roster entry to
MechSubsystem and called RespawnRepair -- wrong for the Subsystem-level
entries (MechTech 0xBDC, SubsystemMessageManager 0xBD3). On MechTech the
recon damageZone slot lands on its subsystemMonitors chain head: NULL
while the scan was broken (fix #1's bug MASKED this one), but the moment
the monitors populated, RespawnRepair virtual-called through a
SubsystemMonitor as if it were a DamageZone -> load-time crash in
StateIndicator::SetState (caught with cdb; call [edx+14h] on code bytes).
The sweep now filters IsDerivedFrom(MechSubsystem) before the cast.
Also: GUID identities pinned -- 0x50f4bc = PoweredSubsystem::ClassDerivations
(via @004b1208 = its TestInstance; btl4gau2's two "Generator" comments were
wrong, swept), 0x50fb60 = Generator's. A shadow-field instance documented for
the deferred de-shadow: MechSubsystem::damageZone re-declares the PUBLIC engine
Subsystem::damageZone (SUBSYSTM.h:159) -- mechtech's naive `sub->damageZone`
read the never-written engine member (0 monitors again); now reads the recon
member via GetDamageZoneProxy(). Logged in open-questions.
Wiring: BTL4GaugeRenderer now constructs + assigns the BTL4GaugeAlarmManager
(the base ctor NULLs it and Activate Check()s it); MechTech's Report*/
StatusMessageSink stubs are real; alarmModel confirmed baked (= 83) at runtime.
VERIFIED LIVE (scratchpad/lampflash.py, BT_LAMP_LOG chain trace):
[techstat] MechTech id 32 monitors 29 subsystems, alarmModel 83
[techstat] LRM15_1 condition 4 SET (alarmModel 83) <- bay fire armed
[galarm] condition 4 code 0x80 -> lamp 0xd mode 0x1 FLASH
[lamp] 0xd <- 0x37 (FLASHING) <- the select button
[galarm] condition 4 code 0x85 -> lamp 0xb mode 0x4 FLASH <- engEject
[techstat] LRM15_1 condition 4 CLEARED <- detonation clears
[techstat] AmmoBinLRM15_1 condition 0 SET <- bin Destroyed
Regressions: baytest PASS (bay fire kills), baypurge PASS (purge extinguishes),
sim3 3-pod brawl PASS with ZERO crashes (6 kills, organic heat-route bay fires,
respawns clean through the new sweep filter).
Env: BT_LAMP_LOG ([techstat]/[galarm]/[lamp]). KB: gauges-hud (the flash
section), decomp-reference (the GaugeAlarm closure + tables + GUIDs),
open-questions (built-note + the de-shadow deferred item), btl4gau2 comment
sweep. checkctx CLEAN.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
5ae4410914
commit
6f5a264835
@@ -451,17 +451,36 @@ void
|
||||
}
|
||||
|
||||
//
|
||||
// @004bbf88 -- slot 12 (GetStatusFlags). Body NOT recovered by the decompiler
|
||||
// (function prologue present at 0x4bbf88). Overrides MechWeapon's
|
||||
// PoweredSubsystem::GetStatusFlags (@004b0f48); best-effort: ORs the weapon's
|
||||
// ammo/jam status bits onto the base flags.
|
||||
// @004bbf88 -- slot 12 (GetStatusFlags). RAW-DISASSEMBLED 2026-07-25 (#47; the
|
||||
// body sat in a Ghidra export gap):
|
||||
//
|
||||
// call 0x4b0f48 ; flags = PoweredSubsystem::GetStatusFlags
|
||||
// mov eax,[ebx+0x364] ; weaponAlarm level
|
||||
// cmp eax,5 / jne / or esi,0x20 ; Jammed -> bit 5 (TechStatus Jammed)
|
||||
// lea ebx,[ebx+0x43c] / call Resolve ; the linked AmmoBin
|
||||
// mov eax,[eax+0x18c] / or esi,0x10 ; cookOffArmed -> bit 4 (AmmoBurning)
|
||||
//
|
||||
// These are the two bits MechTech's TechnicalAssistance edge-scan turns into
|
||||
// the Start/StopEntityAlarm reports that flash the ENG-page buttons (the
|
||||
// shipped 'mechalrm' table: Jammed/AmmoBurning -> gotoEngineering + engEject).
|
||||
//
|
||||
LWord
|
||||
ProjectileWeapon::GetStatusFlags()
|
||||
{
|
||||
// BEST-EFFORT -- body unrecovered. Defer to base until a human disassembles
|
||||
// 0x4bbf88.
|
||||
return MechWeapon::GetStatusFlags();
|
||||
LWord flags = PoweredSubsystem::GetStatusFlags(); // call 0x4b0f48 (direct in the raw)
|
||||
|
||||
if (weaponAlarm.GetLevel() == JammedState) // +0x364 == 5
|
||||
{
|
||||
flags |= 0x20; // Jammed
|
||||
}
|
||||
|
||||
extern int BTAmmoBinCookOffArmed(void *bin); // ammobin.cpp bridge (+0x18C)
|
||||
void *bin = ammoBinLink.Resolve(); // +0x43C, FUN_00417ab4
|
||||
if (bin != 0 && BTAmmoBinCookOffArmed(bin) != 0)
|
||||
{
|
||||
flags |= 0x10; // AmmoBurning
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user