From 4215b9865534765e3191b4ea3e3dc951d2e9e87c Mon Sep 17 00:00:00 2001 From: arcattack Date: Tue, 21 Jul 2026 09:31:52 -0500 Subject: [PATCH] Trigger config: root-cause the dead cockpit clicks (missing BT_PLATFORM=glass) The user held the MFD PROGRAM button and nothing happened (weapons kept firing). Diagnosis, verified end-to-end: - The cockpit mouse handler DID register the click ([cockpit] CLICK addr=0x8 press) and 0x8 IS a streamed PROGRAM element (EVENT msg 0x9 -> weapon, Mfd1 quad page mask). - But every launch ran the DEV platform profile (no BT_PLATFORM) -> L4CONTROLS=KEYBOARD -> no PadRIO instance -> PadRIO::SetScreenButton no-ops (activeInstance NULL) -> the press never entered the RIO queue -> ConfigureMappables (id 9) never dispatched -> the mode never flipped -> fire keys kept firing. The config machinery itself was never broken. - With BT_PLATFORM=glass (the GLASS profile: L4CONTROLS=PAD -> PadRIO), the full chain now proves out headlessly: [btntest] PRESS 0x8 -> [cfgmap] ENTER session on ERMLaser_1 mode 0x450421 -> 0x448421 (NonMapping 0x10000 -> Mapping 0x8000) [btntest] RELEASE 0x8 -> [cfgmap] EXIT (mode restored) Landed: - mechweap.cpp: [cfgmap] BT_FIRE_LOG diagnostics in the real ConfigureMappables/ChooseButton handlers (they were silent -- the G-key harness had logs but the authentic button path had none). - L4PADRIO.cpp: BT_BTNTEST="addr,pressPoll,releasePoll" scripted screen- button harness through the REAL click seam (EmitButton -> RIO queue -> manager drain -> buttonGroup mapping) for headless verification. - play_solo.bat: prefer the glass build when present AND set BT_PLATFORM=glass so PadRIO exists and cockpit clicks work. Side finding (the user's keymap "flip-flop"): CONTROLS.MAP (btinput, DEV/pod profile) and bindings.txt (PadRIO, GLASS profile) are two parallel binding engines; which one runs depends on the platform profile, so the felt keymap changes with the boot flavor. Unification pending (user decision). Awaiting live verification of the full hold-PROGRAM + tap-fire regroup flow. Co-Authored-By: Claude Opus 4.8 (1M context) --- engine/MUNGA_L4/L4PADRIO.cpp | 36 +++++++++++++++++++++++++++++++++ game/reconstructed/mechweap.cpp | 11 ++++++++++ players/play_solo.bat | 18 +++++++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/engine/MUNGA_L4/L4PADRIO.cpp b/engine/MUNGA_L4/L4PADRIO.cpp index 699e673..42ec24c 100644 --- a/engine/MUNGA_L4/L4PADRIO.cpp +++ b/engine/MUNGA_L4/L4PADRIO.cpp @@ -352,6 +352,42 @@ void void PadRIO::Poll() { + // + // BT_BTNTEST="addr,pressPoll,releasePoll" (dev): scripted screen-button + // press through the REAL click seam (EmitButton -> RIO queue -> manager + // drain -> buttonGroup mapping) -- verifies the cockpit-click chain + // headlessly. Example: BT_BTNTEST=8,600,1200 holds button 0x8 (an MFD1 + // PROGRAM element) from poll 600 to poll 1200. + // + { + static int s_btnAddr = -2, s_btnOn = 0, s_btnOff = 0, s_poll = 0, s_state = 0; + if (s_btnAddr == -2) + { + s_btnAddr = -1; + const char *e = getenv("BT_BTNTEST"); + if (e != NULL) + sscanf(e, "%i,%i,%i", &s_btnAddr, &s_btnOn, &s_btnOff); + } + if (s_btnAddr >= 0) + { + ++s_poll; + if (s_state == 0 && s_poll >= s_btnOn) + { + s_state = 1; + EmitButton(s_btnAddr, 1); + DEBUG_STREAM << "[btntest] PRESS 0x" << std::hex << s_btnAddr + << std::dec << " at poll " << s_poll << "\n" << std::flush; + } + else if (s_state == 1 && s_poll >= s_btnOff) + { + s_state = 2; + EmitButton(s_btnAddr, 0); + DEBUG_STREAM << "[btntest] RELEASE 0x" << std::hex << s_btnAddr + << std::dec << " at poll " << s_poll << "\n" << std::flush; + } + } + } + unsigned long now = timeGetTime(); float dt = (lastPollMilliseconds == 0) ? 0.0f diff --git a/game/reconstructed/mechweap.cpp b/game/reconstructed/mechweap.cpp index 828de2f..9db8505 100644 --- a/game/reconstructed/mechweap.cpp +++ b/game/reconstructed/mechweap.cpp @@ -218,6 +218,13 @@ void ConfigureMappablesMessageID, // 9 0); // active_message_id (direct bind) } + // [cfgmap] diagnostic (BT_FIRE_LOG): the session bracket + resulting mode. + if (getenv("BT_FIRE_LOG")) + DEBUG_STREAM << "[cfgmap] " << ((value < 1) ? "EXIT" : "ENTER") + << " session on " << GetName() << " (elem 0x" << std::hex << element + << ") mode now=0x" + << (unsigned)application->GetModeManager()->GetModeMask() + << std::dec << std::endl; } // @@ -242,6 +249,10 @@ void mapper->AddOrErase( // vtbl+0x44 (direct overload) (unsigned int)message->dataContents, // RAW 1-based (ControlsButton *)&fireImpulse); + if (getenv("BT_FIRE_LOG")) + DEBUG_STREAM << "[cfgmap] ChooseButton toggle btn 0x" << std::hex + << (message->dataContents - 1) << std::dec + << " on " << GetName() << std::endl; } } } diff --git a/players/play_solo.bat b/players/play_solo.bat index be03893..a9fd790 100644 --- a/players/play_solo.bat +++ b/players/play_solo.bat @@ -2,13 +2,27 @@ rem BT411 -- single-player practice (no network, no operator). rem Edit the -egg below for other maps (ARENA2/DBASE/FOGDAY/...). cd /d %~dp0 -if not exist "build\Release\btl4.exe" goto badpath +rem Prefer the GLASS build when present (dev checkout): it carries PadRIO, the +rem click-to-button seam that makes the cockpit surround's MFD red buttons, +rem radar rails and joystick buttons mouse-clickable (trigger config needs +rem this). The pod build renders the same cockpit but its clicks are a no-op +rem (PadRIO is not compiled there); player zips ship only build\. +set GAME=build\Release\btl4.exe +if exist "build-glass\Release\btl4.exe" ( + set GAME=build-glass\Release\btl4.exe + rem The GLASS platform profile is what creates PadRIO (L4CONTROLS=PAD): + rem without it the boot falls to the DEV profile (KEYBOARD only) and every + rem cockpit click is silently discarded -- trigger config dead, keymap on + rem the btinput/CONTROLS.MAP engine instead of PadRIO/bindings.txt. + set BT_PLATFORM=glass +) +if not exist "%GAME%" goto badpath if not exist "content\OPERATOR.EGG" goto badpath set BT_START_INSIDE=1 set BT_DEV_GAUGES=1 set BT_LOG=join.log cd content -..\build\Release\btl4.exe -egg ARENA1.EGG +..\%GAME% -egg ARENA1.EGG echo. echo The game has exited. If it closed unexpectedly, echo send the operator content\join.log.