Issue #19: wire ToggleSeekVoltage (Myomers id 9 + energy weapons id 0xb)
Root cause -- NOT issue #2 (the experience mis-seed pins everyone to VETERAN, which PASSES the novice lockout; the gates were never the blocker). Two unwired handlers, the same silent-swallow pattern ToggleCooling had (Receiver::Receive -> NullHandler for an unregistered id): - Myomers (handler table @0x51158C {9,"ToggleSeekVoltage"@004b8a48}): the reconstruction had an EMPTY stub (the address falls in the untagged decomp gap 0x4b8837..0x4b8a8c) and never registered the id. Body reconstructed faithfully from the raw disassembly (tools/disas2.py 0x4b8a48): novice lockout (@4ac9c8) -> heat-model gate (@4ad7d4) -> press-only (msg+0xc>0) -> currentSeekVoltageIndex@0x320 = (idx+1) % (maxSeekVoltageIndex@0x32C + 1). Modulo from zero, min index not consulted, no ResetFiringState. - Emitter (energy-weapon table @0x511DB8 {0xb,"ToggleSeekVoltage"@004ba478}): the faithful body already existed as the orphaned "AdvanceSeekVoltage" (ZERO callers) -- converted to the registered message handler (same guards; cycle + ResetFiringState when not wrapping, disasm re-verified). PPC and GaussRifle copy-inherit the set; the ammo branch keeps its own id 0xb == EjectAmmo (still unwired, tracked separately). Both registered via MESSAGE_ENTRY on top of the inherited chains. Permanent diagnostics: [seek] gear log (BT_SEEK_LOG) + BT_SEEKTEST scripted dispatch harness (mech4.cpp, the cooltoggle pattern). VERIFIED headless: [seek] Myomers -> 3,0,1,2,3... and [seek] PPC_1 -> 3,0,1,2,3... (modulo-4 wrap, matching the binary's arithmetic). Awaiting the tester's live ADV-mode confirmation for the real MFD button route (the routing layer is the same streamed-EventMapping path ToggleCooling verified). KB: decomp-reference.md message-table rows marked wired. 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
c18d2b0213
commit
4aab10ba89
@@ -155,8 +155,18 @@ Derivation
|
||||
Receiver::MessageHandlerSet&
|
||||
Emitter::GetMessageHandlers()
|
||||
{
|
||||
// issue #19 (2026-07-21): register the energy-weapon handler table
|
||||
// @0x511DB8 {0xb, "ToggleSeekVoltage" -> @004ba478} on top of MechWeapon's
|
||||
// ids 9/10 -- the id was unregistered, so the ADV-mode weapon seek press
|
||||
// was silently swallowed. (PPC/GaussRifle copy-inherit this set; the
|
||||
// ammo-weapon branch binds 0xb to EjectAmmo in ITS OWN table instead.)
|
||||
static const Receiver::HandlerEntry entries[]=
|
||||
{
|
||||
MESSAGE_ENTRY(Emitter, ToggleSeekVoltage) // id 0xb @004ba478
|
||||
};
|
||||
static Receiver::MessageHandlerSet messageHandlers(
|
||||
MechWeapon::GetMessageHandlers()); // copy-inherit
|
||||
ELEMENTS(entries), entries,
|
||||
MechWeapon::GetMessageHandlers()); // copy-inherit (ids 9/10)
|
||||
return messageHandlers;
|
||||
}
|
||||
//
|
||||
@@ -645,21 +655,23 @@ void
|
||||
}
|
||||
|
||||
//
|
||||
// @004ba478 -- advance the seek-voltage index, wrapping modulo (count+1). If
|
||||
// the index wrapped past the recommended one, re-arm via ResetFiringState.
|
||||
// Reached only when the heat-state query is clear and the message has payload.
|
||||
// (best-effort -- exact role of param +0xc unconfirmed.)
|
||||
// @004ba478 -- ToggleSeekVoltage (energy-weapon handler table @0x511DB8, id
|
||||
// 0xb). Advance the seek-voltage index, wrapping modulo (count+1); when not
|
||||
// wrapping, re-arm via ResetFiringState. Guards (disasm-verified): novice
|
||||
// lockout (@4ac9c8) -> heat-model gate (@4ad7d4) -> press only (msg+0xc > 0).
|
||||
// Issue #19 (2026-07-21): converted from the orphaned "AdvanceSeekVoltage"
|
||||
// (no callers) into the registered message handler.
|
||||
//
|
||||
int
|
||||
Emitter::AdvanceSeekVoltage(UpdateRecord *message)
|
||||
void
|
||||
Emitter::ToggleSeekVoltageMessageHandler(ReceiverDataMessageOf<int> *message)
|
||||
{
|
||||
if (MechSubsystem::IsDamaged()) // FUN_004ac9c8 -- NOVICE lockout (seek-voltage cycling is an advanced cockpit control; issue #2)
|
||||
if (MechSubsystem::IsDamaged()) // FUN_004ac9c8 -- NOVICE lockout bridge
|
||||
{
|
||||
return /*non-zero status*/ 1;
|
||||
return;
|
||||
}
|
||||
if (!HeatModelActive() || message->payloadCount <= 0) // FUN_004ad7d4 -- heat-model gate; message+0xc
|
||||
if (!HeatModelActive() || message->dataContents <= 0) // FUN_004ad7d4 -- heat-model gate; msg+0xc
|
||||
{
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int prev = seekVoltageIndex; // 0x3f0
|
||||
@@ -670,7 +682,8 @@ int
|
||||
{
|
||||
ResetFiringState(); // @004ba9a8
|
||||
}
|
||||
return next;
|
||||
if (getenv("BT_SEEK_LOG"))
|
||||
DEBUG_STREAM << "[seek] " << GetName() << " -> gear " << next << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user