diff --git a/engine/MUNGA_L4/L4CTRL.cpp b/engine/MUNGA_L4/L4CTRL.cpp index 2fe8c78..59917b7 100644 --- a/engine/MUNGA_L4/L4CTRL.cpp +++ b/engine/MUNGA_L4/L4CTRL.cpp @@ -2670,6 +2670,16 @@ void ); Check(&keyboardGroup[rio_event.Data.Keyboard.Unit]); + { + static int s_klog = -1; + if (s_klog < 0) s_klog = (getenv("BT_PAD_LOG") != 0) ? 1 : 0; + if (s_klog) + DEBUG_STREAM << "[lbe4key] unit " + << (int)rio_event.Data.Keyboard.Unit + << " key " << (int)new_key + << " mode 0x" << std::hex << (unsigned)mode_mask + << std::dec << "\n" << std::flush; + } keyboardGroup[rio_event.Data.Keyboard.Unit]. ForceUpdate(&new_key, mode_mask); diff --git a/engine/MUNGA_L4/L4PADRIO.cpp b/engine/MUNGA_L4/L4PADRIO.cpp index 345deb9..d0df651 100644 --- a/engine/MUNGA_L4/L4PADRIO.cpp +++ b/engine/MUNGA_L4/L4PADRIO.cpp @@ -466,6 +466,18 @@ void << (pressed ? "HELD" : "released") << "\n" << std::flush; } + // PANIC (0x3d): the pod's guarded PANIC key reports through the PILOT + // KEYPAD bank -- the binary's ONLY panic press binding is + // keyboardGroup[KeyboardPilot].Add(mode 0x200000, mech, msg 0x19 = + // EjectPilot) in the RIO mapper ctor (FUN_004d266c @004d266c); there is + // NO buttonGroup[0x3d] consumer anywhere (0x3d is the LAMP address, mode- + // linked via MakeLinkedLamp). Mirror that wiring for the desktop click: + // a Panic press ALSO lands as a pilot-keypad key, so the ARMED mode + // binding fires the eject; a healthy press is a mode-masked no-op -- + // exactly the pod behaviour. + if (address == 0x3D && pressed) + EmitKeypad(LBE4ControlsManager::KeyboardPilot, 0); + RIOEvent event; event.Type = pressed ? ButtonPressedEvent : ButtonReleasedEvent; event.Data.Unit = address; @@ -479,6 +491,9 @@ void event.Type = KeyEvent; event.Data.Keyboard.Unit = unit; event.Data.Keyboard.Key = key; + if (getenv("BT_PAD_LOG")) + DEBUG_STREAM << "[padkey] unit " << unit << " key " << key + << " queued\n" << std::flush; PushEvent(event); } diff --git a/game/reconstructed/btl4mppr.hpp b/game/reconstructed/btl4mppr.hpp index 5c120c9..dbff654 100644 --- a/game/reconstructed/btl4mppr.hpp +++ b/game/reconstructed/btl4mppr.hpp @@ -74,8 +74,17 @@ // public: enum { - KeypressMessageID = MechControlsMapper::NextMessageID, - StringMatchMessageID, + // PINNED to the binary literals (FUN_004d266c passes 0x19/0x1a + // straight into the group Adds; corrected 2026-08-03). The chain + // arithmetic (MechControlsMapper::NextMessageID) lands on 0x17 -- + // TWO mapper ids between 0x16 ToggleVoiceAssist and 0x19 are + // unreconstructed -- and the mis-numbered Keypress send was + // SILENTLY swallowed by the Mech (no 0x17 handler), which is why + // the armed pilot-keypad press never ejected. Mech::EjectPilot is + // id 0x19 on the MECH's receiver: the panic-mode keypad binding + // sends THIS id to the OWNER, and the collision is the design. + KeypressMessageID = 0x19, + StringMatchMessageID, // 0x1a (unregistered; stringManager route) NextMessageID }; @@ -307,8 +316,12 @@ // was previously self-consistent at the wrong value (0x2a), so it // worked by accident -- now it matches the binary. // (Faithful-fidelity note: the binary RIO table also carries its OWN - // Keypress id 0x19 -> @004d2514; our ctor still registers the shared - // L4 Keypress (0x17, @004d1bf0) -- see the Gitea backlog issue.) + // Keypress id: FIXED 2026-08-03 -- KeypressMessageID is now pinned to + // the binary's 0x19 (the old chain arithmetic landed on 0x17, and the + // panic-mode pilot-keypad send was silently swallowed by the Mech -- + // no 0x17 handler -- so the armed eject press never fired). Remaining + // refinement: the ctor registers the shared L4 Keypress BODY + // (@004d1bf0); the RIO-specific body is @004d2514.) // enum { Aux1QuadMessageID = MechControlsMapper::Aux1QuadMessageID, // 3 diff --git a/game/reconstructed/mech.cpp b/game/reconstructed/mech.cpp index a149d87..32814c7 100644 --- a/game/reconstructed/mech.cpp +++ b/game/reconstructed/mech.cpp @@ -599,6 +599,9 @@ void } if (IsDisabled()) // @0049fb54 -- no ejecting from a wreck { + DEBUG_STREAM << "[eject] " << GetEntityID() + << " REFUSED (disabled: movementMode " + << MovementMode() << ")" << std::endl << std::flush; return; }