From caa50ef0f6755baf6f7f09badc7ff31c2caa2715 Mon Sep 17 00:00:00 2001 From: Joe DiPrima Date: Fri, 14 Aug 2026 14:55:30 -0500 Subject: [PATCH] #155 FIXED + LIVE-VERIFIED: the dead eng/weapon MFD banks under a lit PANIC lamp were the gauge renderer's change-detection XOR reading the mode MANAGER's previousModeMask -- a shared scratch overwritten by EVERY Add/RemoveModeMask call. The authentic panic-arm chatter (the no-hysteresis eject evaluator, kept for strict fidelity 2026-08-03) writes that scratch per frame, stomping the SetPresetMode page bits out of the XOR before ExecuteForeground samples it: page EXITS died (reactivation requires the change bit; first entries still worked via !alreadyActivatedFlag), always-active gauges (radar/score/coolant) stayed live -- Oracle's exact bank split. Fix: one line -- sample the renderer's OWN previousModeMask member (already ctor-init'd and maintained at the activate/deactivate guard; the manager read looks like lineage drift), making the change mask accumulate everything since the last RENDER frame, correct under any number of mode writers; single-transition frames identical. Diagnosis chain: authenticity cleared in three legs (121 streamed rows zero eject-gated, MechRIOMapper 0x200000 = PANIC+lamp only, engine dispatch = AND); headless injection exonerated the mapping layer under steady arm AND 2063-edge chatter; the OPERATOR's live mouse session produced the receipts that convicted presentation ([mode] preset fired for the stuck exits while the screen held); fix verified live same session -- 8 transitions incl. 4 exits across all 3 MFDs under 2833 flap edges, all rendered. The PANIC flicker itself stays: authentic (incandescent filament was the pod's low-pass; a glass persistence filter remains a design call). Rig hooks kept: BT_FORCE_EJECT_ARM=1/2. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_016bw71WVsccjwW7uKRg4aWD --- engine/MUNGA/GAUGREND.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/engine/MUNGA/GAUGREND.cpp b/engine/MUNGA/GAUGREND.cpp index 56eaf30..bc507bc 100644 --- a/engine/MUNGA/GAUGREND.cpp +++ b/engine/MUNGA/GAUGREND.cpp @@ -3702,8 +3702,19 @@ void // like the pod -- and the working SetPresetMode page switching NEEDS the // authentic gating (the force made every eng screen paint over the shared // Eng plane, pinning it on the highest screen and ignoring page flips). + // (BT411 #155, 2026-08-14) READ OUR OWN LAST-FRAME MASK, not the mode + // manager's previousModeMask: that cell is a shared scratch overwritten by + // EVERY Add/RemoveModeMask call, and the authentic panic-arm chatter (the + // no-hysteresis eject evaluator) writes it per frame -- stomping the page + // bits out of this XOR before we sample it. Result in the field: MFD page + // EXITS went dead while PANIC flickered (first entries still worked via + // !alreadyActivatedFlag), radar/score/coolant stayed live (always-active). + // The renderer already maintains its own previousModeMask member (updated + // below at the activate/deactivate guard); sampling it here makes the + // change mask accumulate everything since the LAST RENDER FRAME, correct + // under any number of mode writers. Single-transition frames: identical. ModeMask - previous_mode_mask = application->GetModeManager()->GetPreviousModeMask(); + previous_mode_mask = previousModeMask; ModeMask change_mode_mask = current_mode_mask ^ previous_mode_mask; // xor tells me what has changed //-------------------------------------------------------------------