gauges: secondary/radar MFD composites live on a dev box (Milestone B)

The pod's secondary/radar cockpit surface now renders as an inset in the
800x600 dev window under BT_DEV_GAUGES: radar/tactical grid, SPEED/HEADING/
MAGNETIC/PROP dials, and the color-coded ARMOR DAMAGE mech schematic -- real
gauge content (nzSec=27247), composited from the shared CPU pixelBuffer.

Composite pass (engine): SVGA16::DrawDevInset palette-expands the secondary
plane into a MANAGED texture on the MAIN device and draws an XYZRHW inset quad;
BTDrawGaugeInset() reaches the gauge renderer's 'sec' port and is called from
DPLRenderer::ExecuteImplementation as the last draw before EndScene.

Three reconstruction bugs fixed to get real content:
1. BTL4Application::MakeGaugeRenderer signature mismatch (REAL fix): the
   reconstructed no-arg override only HID the 2007-engine's widened 3-arg
   virtual MakeGaugeRenderer(int*,int*,int*), so the engine built a base
   L4GaugeRenderer whose ctor never parsed gauge/l4gauge.cfg -> empty symbol
   table -> "undefined label 'bhk1Init'" -> no ports/gauges. Matched the 3-arg
   signature so it truly overrides (args ignored; BT is fullscreen). Same bug
   class as the BTL4GaugeRenderer(false,NULL,NULL,NULL) ctor fix.
2. Parse hung on undefined primitives (gated dev accommodation): the BT gauge
   primitive table (BTL4MethodDescription) is still a stub, so an unknown
   primitive -> ReportParsingError -> Fail() -> a MODAL dialog freezing the
   parse. Under BT_DEV_GAUGES, skip the unknown primitive's params so labels
   register and the base "configure" primitive builds the ports.
3. Gauge widgets AV on NULL data bindings (gated): NumericDisplayScalar's NULL
   value_pointer -> GaugeConnectionDirectOf ctor deref (bind NULL->static zero);
   RankAndScore::Execute derefs unreconstructed game state (Gauge::GuardedExecute
   SEH wrapper -> Disable(True) on first fault).

All guards gated on BT_DEV_GAUGES: default DEV un-regressed (TARGET DESTROYED,
0 crashes) and the pod path is byte-unchanged (strict Fail, no guards).

Remaining (docs/GAUGE_COMPOSITE.md): the real gauge WIDGET reconstruction
(BTL4MethodDescription method table + gauge->game-state data bindings), then
Step 2 (RP<->BT MFD port-name reconcile) + Step 3 (2-window layout).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-06 10:59:45 -05:00
co-authored by Claude Opus 4.8
parent c13e72d0ba
commit a256813395
10 changed files with 308 additions and 10 deletions
+17 -3
View File
@@ -343,13 +343,27 @@ BTL4Application::SharedData
//#############################################################################
//
GaugeRenderer*
BTL4Application::MakeGaugeRenderer()
BTL4Application::MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index)
{
//
// Only build the gauge renderer when the L4GAUGE environment variable
// is set -- matches RPL4Application's getenv("L4GAUGE") gate. Note
// the BT override takes no arguments (unlike RP's secondary/aux idx).
// is set -- matches RPL4Application's getenv("L4GAUGE") gate.
//
// SIGNATURE NOTE: the shipped BT override (@004d368c) took no arguments,
// but the 2007 WinTesla engine WIDENED the base virtual to
// Application::MakeGaugeRenderer(int* secondaryIndex, int* aux1, int* aux2)
// (the secondary/aux surface indices for windowed mode) and calls THAT
// 3-arg virtual from Application::Initialize (APP.cpp:382). A no-arg
// method here only HIDES the virtual -- it never overrides it -- so the
// engine's L4Application::MakeGaugeRenderer ran instead and built a BASE
// L4GaugeRenderer (which never parses gauge\l4gauge.cfg -> empty symbol
// table -> "undefined label 'bhk1Init'" -> no ports). Matching the 3-arg
// signature makes this the real override. BT is fullscreen with no
// secondary/aux gauge indices, so the args are ignored (the
// BTL4GaugeRenderer ctor hardcodes windowed=false / NULL indices).
//
(void)secondaryIndex; (void)aux1Index; (void)aux2Index;
if (getenv("L4GAUGE") == NULL) // FUN_004dee74
{
return NULL;