Gitea #9: the upper-MFD PRESET pages (3 MFDs x 5) live -- SetPresetMode

table re-decoded to the ModeMFD bits + desktop J/K/L page cycle

The preset system was unwired by ONE defect in the message layer: the
SetPresetMode @004d1b24 table @0051dbf0 had been transcribed from the
section dump as BIG-endian dwords ({0x1e,0x01000000} instead of
{0x1e,0x01}), so a preset press set a garbage high bit -- and for group 1
items 3-4 / group 2 items 0-2 stomped the LIVE NonMapping / Intercom /
ModeSecondary* bits -- while the real page bits never moved.  Ground
truth (section_dump.txt:72901-72908, little-endian + BTL4MODE.HPP [T0]):
set = ModeMFD{1,2,3}{Quad,Eng1-4} = 1<<(group*5+item), bits 0-14, fully
disjoint from the #6 secondary trio (bits 18-20); group 2 is MFD3, NOT a
duplicate of the secondary views.

What the 15 presets show (l4gauge.cfg): group = the MFD (Mfd1 lower left
/ Mfd2 upper center / Mfd3 lower right), item 0 = the btquad.pcx Quad
overview (up to 4 vehicleSubSystems cluster panels), items 1-4 = the
full-screen engineering-detail pages (bteng.pcx + prepEngr screens
group*4+1..4 + the cluster eng children: GENERATOR SELECT A-D, POWER
graph, COOLING loop, DAMAGE, ammo).  Empty screens are authored per mech
(Blackhawk: 3/11/12 empty).

Authentic dispatch (streamed "L4" .CTL EventMappings, BT_CTRLMAP_LOG
dump): each MFD owns the 8-button RIO bank around it, MODE-MASK-gated --
Mfd1 = 0x08-0x0F, Mfd2 = 0x20-0x27, Mfd3 = 0x00-0x07.  Quad page ->
direct-select buttons for the POPULATED eng pages (mapper msgs
Aux1Eng1-4 0x4-0x7 / Aux2* 0x9-0xC / Aux3* 0xE-0x11); eng page -> one
back-to-Quad button (0x3/0x8/0xD) + per-subsystem controls.  These
records already install and fire on desktop (btinput passes the live
manager mask), so the NUMPAD profile's 0x20-0x27 keys page MFD2
authentically.

Port wiring (the #6 pattern): keys J/K/L -> actions Mfd1/2/3Cycle ->
gBTPresetCycle -> L4MechControlsMapper::CyclePresetModeNow(group) -- a
documented desktop shim (24 mode-dependent pod buttons don't fit a
keyboard) that cycles Quad -> populated Eng pages -> Quad, visiting
exactly the pod-reachable set; the body is the authentic SetPresetMode.

Dev-composite: BTDrawGaugeSurfaces now draws the Eng1-3 planes at their
sibling cells and skips any mono plane whose channel is BlankColor,
honoring the mode-driven reconfigure (RemapGraphicsPort) -- each dev
cell shows the ACTIVE page like the pod monitor.  This supersedes and
removes the 2026-07-12 GAUGREND "frozen-dial" scaffold (forced all 15
page bits active under BT_DEV_GAUGES; it pinned the shared Eng plane on
the highest screen and ate the page flips).

Pixel-verified (BT_PRESET_TEST + BT_DEV_GAUGES_DOCK + BT_SHOT,
Blackhawk): all three MFDs page Quad -> SYSTEM NN eng details -> back to
Quad in lockstep with the [mode] preset mask log; group 0 skips the
authored-empty screen 3, group 2 skips 11/12.  Un-regressed: N display
cycle (0x450421->0x490421->0x510421, page bits intact), M control mode,
CONTROLS.MAP 52 bindings parse clean.

Diags: BT_MODE_LOG ([mode] preset), BT_PRESET_TEST=<frame>.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-19 17:30:35 -05:00
co-authored by Claude Fable 5
parent 1d6339b226
commit 6783619069
14 changed files with 336 additions and 36 deletions
+34
View File
@@ -653,6 +653,7 @@ static int gBTMissileKey = 0;
static int gBTPinkyKey = 0; // key '4' = the pod's 4th fire button (Pinky 0x45)
int gBTModeCycle = 0; // 'M' edge: cycle the control mode (mapper consumes)
int gBTDisplayCycle = 0; // 'N' edge: cycle the secondary schematic (Gitea #6, mapper consumes)
int gBTPresetCycle[3] = {0,0,0}; // J/K/L edges: cycle an upper-MFD preset page (Gitea #9, L4 mapper consumes)
int gBTLookBehind = 0; // 'V' held: the pod's rear-view button (task #68)
float gBTTwistAxis = 0.0f; // Q/E torso-twist deflection (assisted-mode stick X)
float gBTElevAxis = 0.0f; // R/F torso-elevation (pitch aim, stick Y)
@@ -2680,6 +2681,19 @@ void
if (nNow && !sPrevN) gBTDisplayCycle = 1;
sPrevN = nNow;
}
// Gitea #9: J/K/L cycle an upper-MFD preset page
// (Quad -> populated Eng pages -> Quad) -- the desktop
// sender for the pod's per-MFD page-button banks
// (SetPresetMode, consumed by the L4 mapper).
{
static int sPrevMfd[3] = {0,0,0};
for (int mg = 0; mg < 3; ++mg)
{
const int gNow = gBTInput.mfdCycle[mg];
if (gNow && !sPrevMfd[mg]) gBTPresetCycle[mg] = 1;
sPrevMfd[mg] = gNow;
}
}
// (task #68) LookBehind action HELD = the pod's rear-view
// button (releases back to the forward view). Rear-mounted
// weapons (blackhawk/owens back racks) fire only in it.
@@ -5191,6 +5205,26 @@ void
}
}
// Gitea #9 scripted verify (BT_PRESET_TEST=<frame>): from the given
// frame, pulse a preset-page cycle on ALL THREE upper MFDs every 120
// frames (Quad -> populated Eng pages -> Quad, per MFD) -- with
// BT_DEV_GAUGES_DOCK + BT_SHOT the Mfd1/Mfd2/Mfd3 page swaps are
// pixel-verifiable ([mode] preset log lines under BT_MODE_LOG).
if ((Entity *)this == application->GetViewpointEntity()
&& getenv("BT_PRESET_TEST"))
{
static int s_ptFrame = 0;
++s_ptFrame;
int t0 = atoi(getenv("BT_PRESET_TEST"));
if (t0 < 1) t0 = 600;
if (s_ptFrame >= t0 && (s_ptFrame - t0) % 120 == 0)
{
gBTPresetCycle[0] = 1;
gBTPresetCycle[1] = 1;
gBTPresetCycle[2] = 1;
}
}
// Gitea #7 scripted verify (BT_FLUSH_TEST=<frame>): hold the coolant
// flush for ~60 sim frames starting at the given frame -- the
// reservoir drains ([flush] log), the coolant vertBar drops, and the