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:
co-authored by
Claude Fable 5
parent
1d6339b226
commit
6783619069
+10
-16
@@ -3677,22 +3677,16 @@ void
|
||||
Check(application->GetModeManager());
|
||||
ModeMask
|
||||
current_mode_mask = application->GetModeManager()->GetModeMask();
|
||||
// DEV-COMPOSITE (2026-07-12, the frozen-dial fix): page-gated gauges (mode
|
||||
// = their MFD page bit) freeze when their page isn't mode-active -- on the
|
||||
// pod you FLIP pages, but the dev window shows every page surface at once,
|
||||
// so six of seven weapon dials sat frozen on screen (user-hit; the arcs
|
||||
// executed exactly 8 times at startup then never again). Under
|
||||
// BT_DEV_GAUGES force the 15 MFD page-plane bits (BTL4 mode bits 0..14 =
|
||||
// MFD1/2/3 Quad+Eng1-4) active so every visible page runs. The secondary
|
||||
// trio (bits 18-20) stays authentic -- those views SHARE pixels and are
|
||||
// exclusive by design.
|
||||
{
|
||||
static int s_devAllPages = -1;
|
||||
if (s_devAllPages < 0)
|
||||
s_devAllPages = (getenv("BT_DEV_GAUGES") != NULL) ? 1 : 0;
|
||||
if (s_devAllPages)
|
||||
current_mode_mask |= (ModeMask)0x7FFF;
|
||||
}
|
||||
// DEV-COMPOSITE history: a 2026-07-12 scaffold ("the frozen-dial fix")
|
||||
// forced the 15 MFD page-plane bits (BTL4 mode bits 0..14 = MFD1/2/3
|
||||
// Quad+Eng1-4) active under BT_DEV_GAUGES, because the dev panel then drew
|
||||
// every page plane at once and page-gated dials froze. REMOVED for Gitea
|
||||
// #9 (2026-07-19): the dev composite now honors the mode-driven
|
||||
// `reconfigure` (a BlankColor plane is skipped -- L4VB16.cpp
|
||||
// BTDrawGaugeSurfaces), so exactly the ACTIVE page of each MFD is shown,
|
||||
// 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).
|
||||
ModeMask
|
||||
previous_mode_mask = application->GetModeManager()->GetPreviousModeMask();
|
||||
ModeMask
|
||||
|
||||
@@ -167,7 +167,7 @@ void SVGA16::DrawDevSurface(LPDIRECT3DDEVICE9 device, int slot, int mask, int pa
|
||||
{
|
||||
int w = pixelBuffer.Data.Size.x; // 640
|
||||
int h = pixelBuffer.Data.Size.y; // 480
|
||||
if (device == NULL || slot < 0 || slot >= 8 || w <= 0 || h <= 0) return;
|
||||
if (device == NULL || slot < 0 || slot >= 10 || w <= 0 || h <= 0) return;
|
||||
|
||||
// Lazily create this surface's texture on the MAIN device (MANAGED -> lockable +
|
||||
// survives device reset).
|
||||
@@ -289,7 +289,13 @@ struct BTGaugeSurfaceDesc
|
||||
// buffer, so past ~1.5x you magnify, not sharpen.
|
||||
static const float kBTPanelW = 1320.0f;
|
||||
static const float kBTPanelH = 480.0f;
|
||||
static const BTGaugeSurfaceDesc kBTGaugeSurfaces[6] =
|
||||
// Gitea #9: each preset-able MFD is TWO bit-planes sharing one physical
|
||||
// monitor -- the base Quad plane (Mfd1/2/3) and the engineering-page plane
|
||||
// (Eng1/2/3). The mode-driven `reconfigure` swaps which of the pair is
|
||||
// channel-enabled and which is BlankColor; the draw loop below skips the
|
||||
// blanked plane, so the dev cell shows exactly what the pod monitor shows.
|
||||
// The Eng entries share their sibling's cell rect and FOLLOW it in the list.
|
||||
static const BTGaugeSurfaceDesc kBTGaugeSurfaces[9] =
|
||||
{
|
||||
{ "Heat", 0xFFFF, 0.0f / kBTPanelW, 0.0f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
{ "Mfd2", 0xFFFF, 320.0f / kBTPanelW, 0.0f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
@@ -297,6 +303,9 @@ static const BTGaugeSurfaceDesc kBTGaugeSurfaces[6] =
|
||||
{ "Mfd3", 0xFFFF, 320.0f / kBTPanelW, 0.5f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
{ "sec", -1, 640.0f / kBTPanelW, 0.0f, 360.0f / kBTPanelW, 1.0f, 1 },
|
||||
{ "Comm", 0xFFFF, 1000.0f / kBTPanelW, 0.0f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
{ "Eng2", 0xFFFF, 320.0f / kBTPanelW, 0.0f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
{ "Eng1", 0xFFFF, 0.0f / kBTPanelW, 0.5f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
{ "Eng3", 0xFFFF, 320.0f / kBTPanelW, 0.5f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
};
|
||||
|
||||
//
|
||||
@@ -345,11 +354,17 @@ void BTDrawGaugeSurfaces(LPDIRECT3DDEVICE9 device, float px, float py, float pw,
|
||||
}
|
||||
if (svga == NULL) return;
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
const BTGaugeSurfaceDesc &d = kBTGaugeSurfaces[i];
|
||||
L4GraphicsPort *port = static_cast<L4GraphicsPort*>(gr->GetGraphicsPort(d.portName));
|
||||
if (port == NULL) continue; // this surface's port isn't configured -> skip
|
||||
// Gitea #9: honor the live mode-driven `reconfigure` -- a mono plane
|
||||
// whose channel is currently BlankColor contributes nothing on the pod
|
||||
// monitor (its palette bits translate to black), so skip it; its
|
||||
// non-blank sibling (Mfd<n> or Eng<n>, same cell rect) draws instead.
|
||||
if (d.monoTint >= 0 && port->GetEnableID() == L4GraphicsPort::BlankColor)
|
||||
continue;
|
||||
// Secondary-CRT unrotation direction is env-flippable (BT_GAUGE_SEC_ROT=3
|
||||
// for the other way) in case the assumed pod mounting is mirrored.
|
||||
int rot = d.rotateCCW;
|
||||
@@ -4309,7 +4324,7 @@ SVGA16::SVGA16(
|
||||
):Video16BitBuffered(init_width, init_height)
|
||||
{
|
||||
BuildWindows(init_width,init_height,windowed, secondaryIndex, aux1Index, aux2Index);
|
||||
for (int _i = 0; _i < 8; _i++) // DEV-COMPOSITE: lazily created on first surface draw
|
||||
for (int _i = 0; _i < 10; _i++) // DEV-COMPOSITE: lazily created on first surface draw
|
||||
mDevSurfaceTex[_i] = NULL;
|
||||
//STUBBED: VIDEO RB 1/15/07
|
||||
# if defined(DEBUG)
|
||||
|
||||
@@ -292,8 +292,9 @@ private:
|
||||
|
||||
int mDisplayToUpdate;
|
||||
|
||||
LPDIRECT3DTEXTURE9 mDevSurfaceTex[8]; // DEV-COMPOSITE: one texture per gauge surface
|
||||
// (sec/radar + the 5 MFD bit-planes), on the MAIN device.
|
||||
LPDIRECT3DTEXTURE9 mDevSurfaceTex[10]; // DEV-COMPOSITE: one texture per gauge surface
|
||||
// (sec/radar + the 5 MFD bit-planes + the Eng1-3
|
||||
// preset-page planes, Gitea #9), on the MAIN device.
|
||||
public:
|
||||
// DEV-COMPOSITE: extract ONE gauge surface from the shared pixelBuffer into
|
||||
// mDevSurfaceTex[slot] on the given (main) device + draw it as a quad at (dstX,dstY,
|
||||
@@ -462,6 +463,15 @@ public:
|
||||
Check(this);
|
||||
return bitMask;
|
||||
}
|
||||
// DEV-COMPOSITE (Gitea #9): the dock honors the live reconfigure state --
|
||||
// a plane whose channel is currently BlankColor contributes nothing on the
|
||||
// pod's shared-word palette LUT, so the dev panel skips drawing it.
|
||||
L4GraphicsPort::ChannelEnableID
|
||||
GetEnableID()
|
||||
{
|
||||
Check(this);
|
||||
return channelEnable;
|
||||
}
|
||||
SVGA16::PaletteID
|
||||
paletteID;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user