gauges: reconstruct + register the first BT gauge widget (cmHeat) [widget recon 1]

Begins the BT gauge WIDGET reconstruction -- making the cockpit instruments show
live data instead of just frame art. The BT gauge method table
(BTL4MethodDescription[]) was a chain-only stub with zero registered
methodDescriptions, so every BT-specific gauge keyword was parse-skipped.

Registers the first widget, cmHeat (ColorMapperHeat -- tints the heat/critical
schematic palette by a named subsystem's live temperature):
- Added ColorMapperHeat::methodDescription (keyword "cmHeat", param list
  R,Md,C,St,St,St matching the binary .data) and registered it in
  BTL4MethodDescription[] (chain link stays last).
- Rewired ColorMapperHeat::Make to read methodDescription.parameterList[]
  (the interpreter restores each instance's parsed params there) instead of the
  earlier unrecovered DAT_* placeholders -- so it uses the real CFG rate/mode/
  colour-slot/palette/subsystem-name, and the runtime port arg as the graphics
  port.

Registering it exposed the /FORCE trap: two REAL functions in the chain were
undefined (silently stubbed -> would AV once the gauge builds). Reconstructed
both from the decomp:
- ColorMapper::BecameActive (@004c395c): invalidate the cached colour index +
  last-written RGB so the next Execute re-pushes the hardware palette.
- ColorMapperHeat::~ColorMapperHeat: empty -- the base chain (~ColorMapper ->
  ~Gauge) releases the HeatConnection + palettes.

Verified: register->parse->Make->ctor->FindSubsystem("GeneratorA") (resolves,
no "does not exist")->HeatConnection->Execute->palette-push runs end-to-end
under BT_DEV_GAUGES; no parse desync; combat un-regressed (TARGET DESTROYED,
0 crashes). Establishes the registration recipe + the /FORCE-check discipline
for every remaining widget. Details + priority order: docs/GAUGE_COMPOSITE.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-06 15:05:47 -05:00
co-authored by Claude Opus 4.8
parent b526e92cad
commit 547f25e043
4 changed files with 117 additions and 18 deletions
+59 -18
View File
@@ -304,6 +304,20 @@ ColorMapper::~ColorMapper()
// base ~Gauge -- FUN_00444360
}
//
// @004c395c -- ColorMapper::BecameActive. On (re)activation, force the next
// Execute (@004c3980) to re-push the hardware palette: invalidate the cached
// colour index + the last-written RGB so the "unchanged" fast-out can't skip the
// write (the surface may have been cleared/redrawn while the gauge was inactive).
//
void
ColorMapper::BecameActive()
{
currentColorIndex = -1; // this[0x15] @0x54
previousColorIndex = -1; // this[0x16] @0x58
previousRed = previousGreen = previousBlue = 0xFF; // this[0x19] @0x64-0x66
}
//
// @004c3980 -- the palette push. Clamp the driving value to a [0,255] colour
// index, choose the active palette (flashing alternates the two when
@@ -423,41 +437,57 @@ void
// DAT_00515020 port, DAT_00515064/0a8/0ec palette/slot/subsystem-name) and the
// class name "ColorMapperHeat" (0x5184c4).
//
//
// Unrecovered .data resource pool used by ColorMapperHeat::Make (the gauge's
// configured rate/mode/port/colour/palette names). The concrete bytes were not
// recovered from the optimised image; declared here as typed placeholders so the
// construction path compiles. (BEST-EFFORT -- real values live in l4gauge.cfg.)
// The gauge's configured parameters come LIVE from the config interpreter (the
// CFG "cmHeat" primitive) via methodDescription.parameterList -- the interpreter
// restores each instance's parsed params into this scratch list before calling
// Make (the engine pattern, cf. NumericDisplayScalar::Make L4GAUGE.cpp:569).
// The earlier DAT_* placeholders (unrecovered .data) are gone.
// CFG shape (verified L4GAUGE.CFG:182):
// cmHeat( rate, modeMask, colourSlot, paletteA, paletteB, subsystemName )
// e.g. cmHeat(H, ModeSecondaryHeat, 32, heatpal.pcc, heatpal2.pcc, GeneratorA);
//
static int DAT_00514f98 = 0; // GaugeRate
static int DAT_00514fdc = 0; // ModeMask
static int DAT_00515020 = 0; // graphics port number
static int DAT_00515064 = 0; // colour-slot resource (&-taken)
static char DAT_005150a8[] = ""; // palette name A
static char DAT_005150ec[] = ""; // palette name B
MethodDescription
ColorMapperHeat::methodDescription =
{
"cmHeat",
ColorMapperHeat::Make,
{
{ ParameterDescription::typeRate, NULL }, // refresh-rate ID
{ ParameterDescription::typeModeMask, NULL }, // display mode mask
{ ParameterDescription::typeColor, NULL }, // hardware colour slot
{ ParameterDescription::typeString, NULL }, // palette name A
{ ParameterDescription::typeString, NULL }, // palette name B
{ ParameterDescription::typeString, NULL }, // heat subsystem name
PARAMETER_DESCRIPTION_END
}
};
Logical
ColorMapperHeat::Make(
int /*display_port_index*/,
int display_port_index,
Vector2DOf<int> /*position*/,
Entity *entity,
GaugeRenderer *gauge_renderer
)
{
ParameterDescription *p = methodDescription.parameterList;
ColorMapperHeat *gauge =
(ColorMapperHeat *)operator new(0x6c); // FUN_00402298(0x6c)
if (gauge != NULL)
{
new (gauge) ColorMapperHeat( // FUN_004c3f6c
(GaugeRate)DAT_00514f98,
(ModeMask) DAT_00514fdc,
p[0].data.rate, // rate ID
p[1].data.modeMask, // mode mask
(L4GaugeRenderer *)gauge_renderer,
DAT_00515020, // graphics port number
(int)&DAT_00515064, // colour slot resource
display_port_index, // graphics port number (the runtime port)
p[2].data.color, // colour slot
entity,
(char *)&DAT_005150a8, // palette name A
(char *)&DAT_005150ec, // palette name B
(char *)"ColorMapperHeat", // subsystem name resource / id
p[3].data.string, // palette name A
p[4].data.string, // palette name B
p[5].data.string, // heat subsystem name (e.g. "GeneratorA")
"ColorMapperHeat");
}
return True;
@@ -524,6 +554,17 @@ ColorMapperHeat::ColorMapperHeat(
AddConnection(connection); // (*this+0x34)
}
//
// ColorMapperHeat destructor. No extra work: the HeatConnection added above is
// released by the base Gauge teardown (RemoveAllConnections), and the two
// palettes by ~ColorMapper -- so the base-dtor chain (~ColorMapper -> ~Gauge)
// runs implicitly at the closing brace. (The binary's deleting-dtor thunks
// @004c66ff/6725/674b/6771 forward to that same base chain.)
//
ColorMapperHeat::~ColorMapperHeat()
{
}
//###########################################################################
//###########################################################################