From d213c980a98bd4eb122a6503db593310eb15472a Mon Sep 17 00:00:00 2001 From: Joe DiPrima Date: Thu, 6 Aug 2026 19:05:04 -0500 Subject: [PATCH] fix: MFD panels never appeared with the HARDWARE RIO (PadRIO coupling) Nick ran the cab with the real board and the mission came up on the main view with every MFD dark -- and not one [glasswin] line in the log. BTGlassPanels_Create() was called only from the END OF THE PadRIO CONSTRUCTOR. The panels began as the frames around the on-screen RIO button banks, so "the buttons ride the device" was reasonable then; it is backwards on a real cab. L4CONTROLS=RIO:COM1 means PadRIO is never constructed, so the MFD windows were never created -- silently, since nothing is wrong from the display layer's point of view. The panels are a DISPLAY concern. Creation moves to LBE4ControlsManager, after the L4CONTROLS parse where every device branch converges, and a symmetric BTGlassPanels_Destroy() goes in its destructor: ~PadRIO tore them down, ~RIO knows nothing about them, and windows outliving the surfaces they blit would crash on the next mission cycle. Both calls are idempotent (Create returns on gWinCount != 0), so the proven PadRIO path is unchanged and simply arrives first. Both guarded by BT_GLASS -- L4GLASSWIN is only in the build when the gate is on. Verified on the cart: hardware RIO up AND all three surfaces on their intended displays in the same run. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Rw7No5wLTpkaUgA3ANbtZZ --- context/pod-hardware.md | 11 +++++++++++ engine/MUNGA_L4/L4CTRL.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/context/pod-hardware.md b/context/pod-hardware.md index c525d5e..7e41158 100644 --- a/context/pod-hardware.md +++ b/context/pod-hardware.md @@ -371,6 +371,17 @@ input device changes, which is what the glass/PadRIO seam was built for. Do NOT pedals `0..470`). A mismatch shows up as drift or short travel, not as an error. - The boot banner names the resolved device — `GLASS (hardware RIO; plasma off [L4PLASMA])`. It used to hardcode "PadRIO", which is a lie on a wired cab and exactly the line you read to check. +- ⚠ **THE COUPLING BUG this exposed (fixed 2026-08-06) [T2].** `BTGlassPanels_Create()` was called + ONLY from the end of the **PadRIO constructor** — the panels began life as the frames around the + on-screen RIO button banks, so "the buttons ride the device". Selecting the hardware RIO means + PadRIO is never constructed, so **every MFD window silently failed to appear**: the mission came + up on the main view with all the pod glass dark, and not one `[glasswin]` line in the log. The + MFD panels are a DISPLAY concern, so creation moved to `LBE4ControlsManager` after the + `L4CONTROLS` parse, where every device branch converges — plus a symmetric `BTGlassPanels_Destroy()` + in its destructor, because `~PadRIO` tore them down and `~RIO` knows nothing about them (windows + outliving the surfaces they blit would crash on the next mission cycle). Both calls are + idempotent (`Create` returns on `gWinCount != 0`), so the PadRIO path is unchanged and simply + arrives first. **Working on the cart, remotely.** SSH over Tailscale lands in **session 0**, which has a dummy "WinDisc" display and CANNOT see or enumerate session 1's windows — GUI work must go through diff --git a/engine/MUNGA_L4/L4CTRL.cpp b/engine/MUNGA_L4/L4CTRL.cpp index 28924c9..49a31b4 100644 --- a/engine/MUNGA_L4/L4CTRL.cpp +++ b/engine/MUNGA_L4/L4CTRL.cpp @@ -9,6 +9,10 @@ #include "dxutils.h" #ifdef BT_GLASS #include "l4padrio.h" +#ifdef BT_GLASS +#include "l4glasswin.h" // the per-display MFD windows -- created below for + // EITHER RIO (they used to ride the PadRIO ctor) +#endif #endif // @@ -865,6 +869,29 @@ LBE4ControlsManager::LBE4ControlsManager(): while (temp[0] != '\0'); } + //-------------------------------------------------- + // The per-display MFD windows (2026-08-06) + //-------------------------------------------------- + // These used to be created ONLY at the end of the PadRIO constructor, + // because they began life as the frames around the on-screen RIO button + // banks -- "the buttons ride the device". On a real cab that coupling is + // backwards: selecting the HARDWARE RIO means PadRIO is never built, so + // the MFD panels never appeared at all. Found on the crash cart, where + // the mission came up on the main view with every MFD dark. + // + // The windows are a DISPLAY concern, so create them here -- after the + // L4CONTROLS parse, where every device branch converges -- and let them + // exist whichever RIO won. In pod surface mode there are no on-screen + // buttons on them at all. Create() is idempotent (`gWinCount != 0` + // returns), so the PadRIO call site stays valid and simply arrives first. + // +#ifdef BT_GLASS + if (rioPointer != NULL && BTGlassPanelsActive()) + { + BTGlassPanels_Create(); + } +#endif + //-------------------------------------------------- // Clear all lamps (and reset analog I/O) //-------------------------------------------------- @@ -1089,6 +1116,17 @@ LBE4ControlsManager::~LBE4ControlsManager() rioPointer = NULL; } +#ifdef BT_GLASS + // + // Symmetric with the Create above (2026-08-06). ~PadRIO tears the panels + // down itself, so this is a no-op there -- but the HARDWARE RIO's dtor + // knows nothing about them, and windows that outlive the surfaces they + // blit are a crash waiting for the next mission cycle. Destroy is safe + // if they were never created. + // + BTGlassPanels_Destroy(); +#endif + Check_Fpu(); }