From 88cd68aaa176d0c889c91272ab7b02bd03c96f15 Mon Sep 17 00:00:00 2001 From: arcattack Date: Tue, 7 Jul 2026 17:57:20 -0500 Subject: [PATCH] gauge wave P2d: GeneratorCluster un-gated -- the 4 generator panels render Root-caused the P2c abort with a cdb attach to the frozen abort dialog: the stack was Gauge::Execute (GAUGE.cpp:598) -> abort, via GuardedExecute <- Update <- ProcessOneActiveGauge. The engine base Gauge::Execute is Fail("not overridden") -> abort, so an ACTIVE container that doesn't override Execute aborts by design; GuardedExecute's SEH can't catch an abort(). The decode's "GeneratorCluster overrides ONLY the dtor / renders via its children" was wrong -- the 1995 base Gauge::Execute was a no-op, the 2007 WinTesla engine's aborts, so the container MUST override Execute (the sibling SubsystemCluster does). FIX: give GeneratorCluster the two container overrides (mirroring SubsystemCluster): - BecameActive() -- blit the panel's static background pixmap (DrawPixelMap8) and, by overriding the default, DON'T self-inactivate so the panel stays active. - Execute() -- no-op (the 5 self-registered child gauges draw the dynamic content; the override exists only to avoid the base Fail->abort). Re-registered in BTL4MethodDescription[]. Verified DBASE+dev gauges: all 4 generator panels (A/B/C/D) render -- blue OutputVoltage bars (the @004c72ac ScalarBarGauge Scalar* variant), labels, status lamps -- 0 "BecameActive not defined" warnings, NO abort, combat un-regressed (TARGET DESTROYED). Phase 2 is now COMPLETE (4/4 widgets: LeakGauge, VertNormalSlider, PilotList, GeneratorCluster). Co-Authored-By: Claude Opus 4.8 (1M context) --- game/reconstructed/btl4gau2.cpp | 30 ++++++++++++++++++++++++++++++ game/reconstructed/btl4gau2.hpp | 8 ++++++++ game/reconstructed/btl4grnd.cpp | 13 +------------ 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/game/reconstructed/btl4gau2.cpp b/game/reconstructed/btl4gau2.cpp index d3f0c24..4c41b25 100644 --- a/game/reconstructed/btl4gau2.cpp +++ b/game/reconstructed/btl4gau2.cpp @@ -785,6 +785,36 @@ GeneratorCluster::~GeneratorCluster() backgroundImage = NULL; } +// +// BecameActive -- paint the panel's static background pixmap. MUST override the +// default (which self-inactivates the panel + warns); a no-op keeps the panel +// active so its 5 child gauges (self-registered) keep drawing. The bg is drawn +// here (on activation) beneath the children. +// +void + GeneratorCluster::BecameActive() +{ + L4Warehouse *warehouse = (L4Warehouse *)renderer->warehousePointer; + PixelMap8 *bg = warehouse->pixelMap8Bin.Get(backgroundImage); // already AddRef'd by the ctor + if (bg != NULL) + { + localView.MoveToAbsolute(0, 0); // vtbl+0x24 + localView.DrawPixelMap8(True, 0, bg, 0, 0, // vtbl+0x5C (opaque, full image) + bg->Data.Size.x - 1, bg->Data.Size.y - 1); + } + warehouse->pixelMap8Bin.Release(backgroundImage); // balance this Get +} + +// +// Execute -- the panel itself has no per-frame content (the temp/voltage/leak/lamp +// children each Execute independently), but Execute MUST be overridden: the engine +// base Gauge::Execute is Fail(...)->abort (GAUGE.cpp:598). No-op. +// +void + GeneratorCluster::Execute() +{ +} + //########################################################################### //########################################################################### diff --git a/game/reconstructed/btl4gau2.hpp b/game/reconstructed/btl4gau2.hpp index b813e4a..9235dfd 100644 --- a/game/reconstructed/btl4gau2.hpp +++ b/game/reconstructed/btl4gau2.hpp @@ -267,6 +267,14 @@ int lamp_on_color, int lamp_off_color, const char *identification_string); ~GeneratorCluster(); // @004c7778 + // A container panel MUST override BecameActive + Execute: the engine base + // Gauge::Execute is Fail("not overridden")->abort (GAUGE.cpp:598), and the + // default BecameActive self-inactivates. The panel draws its static + // background pixmap; the 5 self-registered child gauges draw the dynamic + // content. (The decode's "only the dtor is overridden" was wrong: the + // 1995 base Gauge::Execute was a no-op, the 2007 engine's aborts.) + void BecameActive(); + void Execute(); protected: char *backgroundImage; // @0x90 this[0x24] interned .pcc (pixelMap8Bin AddRef'd) int secondaryColor; // @0x94 this[0x25] = leak colorB (stored, unread here) diff --git a/game/reconstructed/btl4grnd.cpp b/game/reconstructed/btl4grnd.cpp index 1a28183..7a17118 100644 --- a/game/reconstructed/btl4grnd.cpp +++ b/game/reconstructed/btl4grnd.cpp @@ -146,18 +146,7 @@ MethodDescription &BitMapInverseWipe::methodDescription, // "LeakGauge" -- coolant-leak inverse-wipe (Condenser/CoolantMassLeakRate) &VertNormalSlider::methodDescription, // "vertNormalSlider" -- condenser valve-setting slider (heat MFD) &PilotList::methodDescription, // "pilotList" -- Comm KILLS/DEATHS pilot roster - // GeneratorCluster is reconstructed (btl4gau2.cpp) + its infra is in place - // (Generator OutputVoltage table + the @004c72ac ScalarBarGauge variant), but - // registering it aborts at runtime: the 4 panels build (the 4 "BecameActive not - // defined" warnings fire) then abort() -- isolated to the PARENT lifecycle (the - // abort persists with all 5 children nulled; no pure virtuals; the ctor path is - // unguarded by the SEH GuardedExecute). The sibling SubsystemCluster overrides - // BecameActive/Execute/TestInstance whereas the decode has GeneratorCluster - // overriding ONLY the dtor -- that "inherits only dtor" claim is the prime - // suspect. DEFERRED: unregistered so it parse-skips (never built) -> no abort; - // the other 3 P2 widgets ship clean. Re-enable this line once the parent - // lifecycle is resolved. - // &GeneratorCluster::methodDescription, // "GeneratorCluster" -- 4 generator panels (buttons 9-12) + &GeneratorCluster::methodDescription, // "GeneratorCluster" -- the 4 generator engineering panels (buttons 9-12) &BTL4ChainToPrevious };