//===========================================================================// // File: btl4gaug.hpp // // Project: BattleTech Brick: Gauge Renderer Manager // // Contents: The cockpit instrument gauge library -- the family of small // // "widget" gauges that the BattleTech HUD is assembled from: // // * ColorMapper* -- palette-animating tint gauges driven by // // subsystem state (heat / armour / crit) // // * Horiz/VertTwoPartBar, VertNormalSlider // // -- two-colour fill bars (throttle / damage) // // * OneOfSeveral* -- multi-frame bitmap selectors (state lamp) // // * HeadingPointer -- rotating numeric heading readout // // * SegmentArc270/Ratio-- arc / dial style gauges // // * BitMap wipe gauges -- bitmap "fuel / leak" wipe indicators // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 02/22/96 CPB Initial coding. // //---------------------------------------------------------------------------// // Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// // // RECONSTRUCTED. No BTL4GAUG.HPP survived (the BT_L4 source tree retains only // BTL4RDR.HPP and BTL4GALM.HPP). This declaration is recovered from the // shipped binary (BTL4OPT.EXE); the Ghidra pseudo-C is in // recovered/all/part_013.c (@004c2f94..@004c5e84) // recovered/all/part_014.c (@004c5e84..@004c6394) // The module is the .obj that links immediately after btl4rdr.obj and before // btl4gau2.obj (see BTL4.MAK), so it owns the contiguous code run // [ @004c2f94 .. @004c6771 ] (btl4gau2.cpp begins at @004c6798). // // The sole address with a surviving embedded assert path -- the anchor -- // is ColorMapperHeat's constructor: // @004c3f6c "d:\tesla\bt\bt_l4\BTL4GAUG.CPP", line 0x68a // // Class names are recovered verbatim from the CODE name-string pool // (section_dump.txt @0x518480..0x51859e): // ColorMapper ColorMapperArmor ColorMapperMultiArmor ColorMapperCritical // ColorMapperHeat HorizTwoPartBar VertTwoPartBar VertNormalSlider // OneOfSeveral OneOfSeveralInt OneOfSeveralPixInt OneOfSeveralStates // HeadingPointer BitMapInverseWipe BitMapInverseWipeScalar // SegmentArc270 SegmentArcRatio // // Field offsets in comments are the byte offsets observed in the decompiled // object (e.g. "@0x90" == this[0x24]). The two base gauges are the MUNGA L4 // gauge primitives: // Gauge ctor FUN_00444308 dtor FUN_00444360 -- non-graphic; // used by the ColorMapper family (they tint a palette, they // do not own a GraphicsView). // GraphicGauge ctor FUN_00444818 dtor FUN_00444870 -- owns a GraphicsView // embedded at +0x48 (this[0x12]); used by every drawing gauge. // (Same base as MapDisplay in btl4rdr.cpp.) // // Names flagged "(name unconfirmed)" are best-effort: the class exists in the // binary but its identification string could not be tied to it unambiguously. // #if !defined(BTL4GAUG_HPP) # define BTL4GAUG_HPP # if !defined(SLOT_HPP) # include # endif # if !defined(L4GREND_HPP) # include # endif # if !defined(L4GAUGE_HPP) # include # endif # if !defined(HEAT_HPP) # include # endif // NOTE (reconstruction): the original BTL4GAUG.HPP also pulled in // , but nothing in this gauge-widget family actually depends // on a power-subsystem type (the gauges connect to subsystems by name / // attribute index, not by class). The include is dropped to keep this TU // independent of the (separately-reconstructed) powersub header. //####################################################################### //####################################################################### // ColorMapper family // // A ColorMapper is NOT a drawing gauge: every frame it reads a single // subsystem-derived value (0..255), looks the corresponding R/G/B // triple out of a named palette resource, and -- if it has changed -- // writes it straight into one hardware palette slot (colorIndex). The // cockpit art that uses that slot therefore changes colour live. With // two palette names it alternates between them every frame to flash. // // The driving value arrives through a small file-private GaugeConnection // (see btl4gaug.cpp) wired to currentColorIndex. ColorMapperHeat's // connection reads HeatableSubsystem::currentTemperature (@0x114). //####################################################################### //####################################################################### class ColorMapper : public Gauge { public: ColorMapper( GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer, int graphics_port_number, int color_index, const char *palette_name_a, const char *palette_name_b, const char *identification_string ); ~ColorMapper(); Logical TestInstance() const; // inherits Gauge void BecameActive(); void Execute(); // @004c3980 -- palette push protected: char *paletteName[2]; // @0x48,@0x4C this[0x12],[0x13] Logical twoColorMode; // @0x50 this[0x14] (names differ) int currentColorIndex; // @0x54 this[0x15] (connection dst) int previousColorIndex; // @0x58 this[0x16] int colorSlot; // @0x5C this[0x17] hw palette slot int paletteToggle; // @0x60 this[0x18] 0/1 flash phase unsigned char previousRed, // @0x64 this[0x19].b0 previousGreen, // @0x65 previousBlue; // @0x66 GraphicsPort *graphicsPort; // @0x68 this[0x1A] (renderer port) }; // // ColorMapperArmor -- tints by the damage ratio of one named damage zone. // Connection: @004c33a4 (reads Subsystem damage-zone array @0x120[index]). // class ColorMapperArmor : public ColorMapper { public: // Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "cmArmor". static MethodDescription methodDescription; static Logical Make( // @004c3aa4 int display_port_index, Vector2DOf position, Entity *entity, GaugeRenderer *gauge_renderer); ColorMapperArmor( // @004c3b98 GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer, int graphics_port_number, int color_index, Entity *entity, const char *palette_a, const char *palette_b, int damage_zone_index, const char *identification_string); ~ColorMapperArmor(); // @004c3c38 -- store the group state into @0x6C (used by PlayerStatusMappingGroup // to push the mech's disabled/enabled state onto all 28 zone tints). void SetColor(int state) { unused = state; } protected: int unused; // @0x6C this[0x1B] (state slot; SetColor writes it) }; // // ColorMapperMultiArmor -- worst-of-N damage zones. // Connection: @004c346c (copies 8 zone indices, takes the max ratio). // class ColorMapperMultiArmor : public ColorMapper { public: // Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "colorMapperMultiArmor". static MethodDescription methodDescription; static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c3c48 ColorMapperMultiArmor( // @004c3d60 GaugeRate, ModeMask, L4GaugeRenderer *, int, int, Entity *, const char *, const char *, const int *zone_indices /*[8]*/, const char *); ~ColorMapperMultiArmor(); }; // // ColorMapperCritical -- tints by a subsystem's operational state. // Connection: @004c3598 (subsystem operational flag @0x40 -> 100, else value). // class ColorMapperCritical : public ColorMapper { public: // Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "cmCrit". static MethodDescription methodDescription; static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c3ddc ColorMapperCritical( // @004c3e40 GaugeRate, ModeMask, L4GaugeRenderer *, int, int, Entity *, const char *, const char *, const char *subsystem_name, const char *); ~ColorMapperCritical(); }; // // ColorMapperHeat -- the cockpit heat tint. ANCHOR @004c3f6c. // Connection: @004c3664 (reads HeatableSubsystem::currentTemperature@0x114 // as a 0..100 percentage). The named subsystem must derive from a heat // class (IsDerivedFrom 0x50e3ec HeatableSubsystem or 0x50e604 HEATWATCHER // -- task #57 relabel) or the ctor asserts (line 0x68a). // class ColorMapperHeat : public ColorMapper { public: static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c3f08 ColorMapperHeat( // @004c3f6c GaugeRate, ModeMask, L4GaugeRenderer *, int, int, Entity *, const char *, const char *, const char *heat_subsystem_name, const char *); ~ColorMapperHeat(); // Registered in BTL4MethodDescription[] (btl4grnd.cpp) so the config // interpreter builds this gauge from the CFG "cmHeat" primitive. static MethodDescription methodDescription; }; //####################################################################### //####################################################################### // Two-part fill bars (: GraphicGauge) // // A bar is split into a "filled" colour and a "background" colour at a // pixel computed from a Scalar input. HorizTwoPartBar grows left->right, // VertTwoPartBar grows bottom->top. Both blit a tile bitmap behind the // fill (FUN_004c2ff8 = tiled blit helper). //####################################################################### //####################################################################### class HorizTwoPartBar : public GraphicGauge { public: static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c407c HorizTwoPartBar( // @004c4170 GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number, int left, int bottom, int right, int top, const char *tile_image, int fill_color, int background_color, Scalar *value_pointer, Scalar *low_pointer, Scalar *high_pointer, const char *identification_string); ~HorizTwoPartBar(); Logical TestInstance() const; void BecameActive(); // @004c4324 void Execute(); // @004c4340 protected: Scalar value; // @0x90 this[0x24] (connection) Scalar low; // @0x94 this[0x25] Scalar high; // @0x98 this[0x26] char *tileImage; // @0x9C this[0x27] int fillColor; // @0xA0 this[0x28] int backgroundColor; // @0xA4 this[0x29] int width; // @0xA8 this[0x2A] right-left int height; // @0xAC this[0x2B] (top-bottom)-1 int previousFill; // @0xB0 this[0x2C] int previousFull; // @0xB4 this[0x2D] }; class VertTwoPartBar : public GraphicGauge { public: // Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "vertBar". static MethodDescription methodDescription; static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c462c VertTwoPartBar( // @004c4724 (ctor arg order = binary param_12..17) GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number, int left, int bottom, int right, int top, const char *tile_image, int background_color, int fill_color, int extra_color, Scalar *value_pointer, Scalar *low_pointer, Scalar *high_pointer, const char *identification_string); ~VertTwoPartBar(); Logical TestInstance() const; void BecameActive(); // @004c48e0 void Execute(); // @004c48fc protected: char *tileImage; // @0x90 this[0x24] int backgroundColor; // @0x94 this[0x25] int fillColor; // @0x98 this[0x26] int extraColor; // @0x9C this[0x27] int width; // @0xA0 this[0x28] (right-left)-1 int height; // @0xA4 this[0x29] top-bottom Scalar value; // @0xB0 this[0x2C] (connection) Scalar low; // @0xB4 this[0x2D] Scalar high; // @0xB8 this[0x2E] int previousFill; // @0xA8 this[0x2A] int previousFull; // @0xAC this[0x2B] }; // // VertNormalSlider -- a single-colour rectangle whose height tracks a // normalised [0,1] value (clamped at @004c4cc0). (name unconfirmed but // matches the "VertNormalSlider" pool entry and the vtable ordering.) // class VertNormalSlider : public GraphicGauge { public: // gauge wave P2: the "vertNormalSlider" config factory (the condenser VALVE // slider @2 in GenericHeatGauges1/2). Registered in BTL4MethodDescription[] // (btl4grnd.cpp); the ctor/Execute existed only as prose, so the keyword was // parse-skipped and the SET column never built. static MethodDescription methodDescription; static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c4b08 VertNormalSlider( // @004c4b84 GaugeRate, ModeMask, L4GaugeRenderer *, int, int left, int bottom, int right, int top, int fill_color, int background_color, int baseline, Scalar *value_pointer, const char *identification_string); ~VertNormalSlider(); // @004c4c68 Logical TestInstance() const; // @004c4c94 -> GraphicGauge::TestInstance void BecameActive(); // @004c4cac void Execute(); // @004c4cc0 -> Draw @004c4d48 private: void Draw(); // @004c4d48 (XOR indicator blit; non-virtual) protected: // Corrected byte-exact layout (from the ctor's this[N] stores @004c4b84; // the earlier order was jumbled). 8 words, 0x90..0xAF, sizeof == 0xB0. int previousFill; // @0x90 this[0x24] XOR indicator row; -1 = none int width; // @0x94 this[0x25] (right-left)-1 int height; // @0x98 this[0x26] top-bottom (track height) int baseline; // @0x9C this[0x27] indicator thickness int span; // @0xA0 this[0x28] height-baseline (travel) int fillColor; // @0xA4 this[0x29] indicator colour int backgroundColor; // @0xA8 this[0x2A] stored, unused by Draw Scalar value; // @0xAC this[0x2B] connection dst [0,1] }; //####################################################################### //####################################################################### // OneOfSeveral family -- multi-frame bitmap selectors // // A strip bitmap holds N frames; the gauge blits whichever frame the // driving value selects. The base (OneOfSeveral) stores the strip and // the per-frame size; subclasses add the value source. //####################################################################### //####################################################################### class OneOfSeveral : public GraphicGauge { public: OneOfSeveral( // @004c4d88 GaugeRate, ModeMask, L4GaugeRenderer *, int, int x, int y, Logical from_image_strip, const char *image_name, int /*reserved*/, int /*reserved*/, int columns, int rows, const char *identification_string); ~OneOfSeveral(); Logical TestInstance() const; void BecameActive(); // @004c4f14 void Execute(); // @004c4f28 protected: Logical fromImageStrip; // @0x90 this[0x24] char *imageName; // @0x94 this[0x25] int backgroundColor; // @0x98 this[0x26] int foregroundColor; // @0x9C this[0x27] (DrawBitMapOpaque bg arg) int columns; // @0xA0 this[0x28] int selected; // @0xAC this[0x2B] (connection) int previousSelected; // @0xB0 this[0x2C] int frameWidth; // @0xA4 this[0x29] int frameHeight; // @0xA8 this[0x2A] }; // // OneOfSeveralInt -- frame = a direct int input. @004c5148 Make @004c5068 // class OneOfSeveralInt : public OneOfSeveral { public: static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); OneOfSeveralInt(GaugeRate, ModeMask, L4GaugeRenderer *, int, int x, int y, const char *image, int columns, int rows, int *value_pointer, const char *); ~OneOfSeveralInt(); // @004c51d8 }; // // OneOfSeveralPixInt -- frame from a packed-pixel int strip. // @004c52d8 Make @004c5204 // class OneOfSeveralPixInt : public OneOfSeveral { public: // Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "oneOfSeveralPixInt". static MethodDescription methodDescription; static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c5204 OneOfSeveralPixInt( // @004c52d8 GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number, int x, int y, const char *image, int columns, int rows, int *value_pointer, const char *identification_string); ~OneOfSeveralPixInt(); // @004c5364 }; // // OneOfSeveralStates -- frame from a subsystem state value (clamped >=0). // @004c5470 Make @004c5390 Execute clamp @004c552c // Connection: @004c3324 (reads Subsystem state @0x14). // class OneOfSeveralStates : public OneOfSeveral { public: static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); OneOfSeveralStates(GaugeRate, ModeMask, L4GaugeRenderer *, int, int x, int y, const char *image, int columns, int rows, Entity *subsystem_source, const char *); ~OneOfSeveralStates(); // @004c5500 void BecameActive(); // @004c552c }; //####################################################################### // HeadingPointer -- a rotating numeric compass-heading readout. // @004c562c Make @004c554c Execute @004c5914 (rotate by torso yaw, // degrees = radian * 57.2958). Owns a NumericDisplay (@0x44 object, // FUN_004700bc) and a GraphicsViewRecord (@0xA4) for erase tracking. //####################################################################### class HeadingPointer : public GraphicGauge { public: // Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "headingPointer". static MethodDescription methodDescription; static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c554c // // The binary ctor (@004c562c) takes 14 args -- the earlier header collapsed // owner_ID/graphics_port_number and merged the colours. Also: fields // @0x98/@0x9C are the needle's inner/outer RADIUS (Execute multiplies them // by sin/cos of the heading), NOT a colour+spacing as the old names implied. // HeadingPointer( // @004c562c GaugeRate, ModeMask, L4GaugeRenderer *, unsigned int owner_ID, int graphics_port_number, int x, int y, int needle_color, // -> @0x90 the drawn needle colour int numeric_color, // -> NumericDisplay foreground (readout) int erase_color, // -> @0x94 erase + NumericDisplay background int inner_radius, // -> @0x98 needle near-end radius int outer_radius, // -> @0x9C needle tip radius (the change key) const char *font_name, const char *identification_string = "HeadingPointer"); ~HeadingPointer(); // @004c573c Logical TestInstance() const; void ShowInstance(char *indent); // @004c57d0 void BecameActive(); // @004c58e8 void Execute(); // @004c5914 protected: int needleColor; // @0x90 needle (fg) colour int eraseColor; // @0x94 erase (bg) colour int innerRadius; // @0x98 needle near-end radius int outerRadius; // @0x9C needle tip radius (change key) char *imageName; // @0xA0 interned font name GraphicsViewRecord previousDrawing; // @0xA4 erase-tracking record int previousX; // @0xB4 int previousY; // @0xB8 NumericDisplay *numericDisplay; // @0xBC }; //####################################################################### // BitMap "wipe" gauges -- a fuel/leak style bar that reveals a bitmap up // to a level. (names "BitMapInverseWipe" / "BitMapInverseWipeScalar" are // best-effort from the pool; the Scalar variant adds a GaugeConnection.) // BitMapInverseWipe @004c5b7c (used as a base by btl4gau2 LeakGauge) // @004c5e84 // Scalar @004c61c8 (adds GaugeConnectionDirectOf) //####################################################################### class BitMapInverseWipe : // (name unconfirmed) public GraphicGauge { public: // gauge wave P2: registered in BTL4MethodDescription[] (btl4grnd.cpp) as // "LeakGauge" -- the config factory the class was missing (the ctor/Execute // already existed but the keyword was parse-skipped so it never built). static MethodDescription methodDescription; static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c... (config factory) BitMapInverseWipe( // @004c5b7c GaugeRate, ModeMask, L4GaugeRenderer *, int, int x, int y, const char *image, int color_a, int color_b, int third, int frames, Scalar *value_pointer, const char *); ~BitMapInverseWipe(); // @004c5c80 Logical TestInstance() const; void BecameActive(); // @004c5cf4 void Execute(); // @004c5d08 protected: char *imageName; // @0x90 this[0x24] int colorA; // @0x94 this[0x25] int colorB; // @0x98 this[0x26] int fullWidth; // @0x9C this[0x27] frames*2 int frameWidth; // @0xA8 this[0x2A] width/3 int frameHeight; // @0xA4 this[0x29] int frames; // @0xA0 this[0x28] int previousLevel; // @0xAC this[0x2B] int third; // @0xB0 this[0x2C] Scalar value; // @0xB4 this[0x2D] (connection) }; //####################################################################### // SegmentArc gauges -- needle / dial over a 270-degree arc. Derived from // the MUNGA L4 arc primitives (FUN_004745e0 / FUN_00473f44). // SegmentArc270 @004c6244 // SegmentArcRatio @004c6394 Make @004c62fc (adds two connections) //####################################################################### class SegmentArc270 : public SegmentArc // MUNGA L4 base (engine class SegmentArc) { public: SegmentArc270( // @004c6244 GaugeRate, ModeMask, L4GaugeRenderer *, int owner_ID, int graphics_port_number, int center_x, int center_y, Scalar inner0, Scalar outer0, Scalar inner1, Scalar outer1, Scalar deg0, Scalar deg1, int number_of_segs, int background_color, int foreground_color, Scalar *value_pointer, Logical use_thick_lines, const char *identification_string); ~SegmentArc270(); // dtor thunk @004c66b3 void Execute(); // PORT diag wrapper (chains SegmentArc::Execute) const char *diagName; // PORT diagnostic (frozen-dial hunt) protected: Scalar segmentSpan; // @0xC0 this[0x30] }; class SegmentArcRatio : public SegmentArc // MUNGA L4 base (engine SegmentArc, L4GAUGE.cpp:4827) { public: // Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "segmentArcRatio". static MethodDescription methodDescription; static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c62fc SegmentArcRatio( // @004c6394 GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number, int center_x, int center_y, Scalar inner, Scalar outer, Scalar deg0, Scalar deg1, int number_of_segs, int background_color, int foreground_color, Scalar *numerator_pointer, Scalar *denominator_pointer, const char *identification_string); ~SegmentArcRatio(); // dtor thunk @004c668d void Execute(); // @004c6488 (ratio -> currentValue -> SegmentArc::Execute) protected: Scalar numerator; // @0xC0 this[0x30] (connection) Scalar denominator; // @0xC4 this[0x31] (connection) Scalar segmentSpan; // @0xC8 this[0x32] (float, read by Execute) }; #endif