//===========================================================================// // File: btl4gau2.cpp // // Project: BattleTech Brick: Gauge Renderer Manager // // Contents: Cockpit instrument library, part 2 -- composite panel gauges // // (see btl4gau2.hpp). // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 02/22/96 CPB Initial coding. // //---------------------------------------------------------------------------// // Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// // // RECONSTRUCTED from the shipped binary (BTL4OPT.EXE). Behaviour follows the // Ghidra pseudo-C in recovered/all/part_014.c (@004c6798..@004c9b50). Class / // member names taken from the CODE name-string pool; per-method @ADDR evidence // is cited inline. This TU links between btl4gaug.obj and btl4gau3.obj. // // Engine-internal helper map (consistent with btl4gaug.cpp / btl4rdr.cpp): // FUN_00444818 GraphicGauge ctor FUN_00444870 GraphicGauge dtor // FUN_004448ac GraphicGauge::TestInstance // FUN_004440d4 Gauge-group ctor FUN_00443f7c Gauge-group dtor // FUN_0044ae0c ChainOf dtor (PrepEngrScreen child list) // FUN_004442b8 default GaugeRate FUN_004442dc default ModeMask // FUN_00444290 alt default rate/mask // FUN_004700ac GaugeRenderer::InternName FUN_004022e8 FreeName // FUN_00442aec/00442c12 BitMapCache AddRef/Release (renderer+0x4C, +4) // FUN_00442d2b/00442e51 PixMapCache AddRef/Release (renderer+0x4C, +0x20) // FUN_0041bfc0 Entity::FindAttributeIndex(name) // FUN_0041f98c Entity::FindSubObject(name) // FUN_00447f1c GaugeRenderer::InstallPort / FUN_00447f84 GetGraphicsPort // FUN_00417ab4 SharedData::Resolve / operator Entity* // FUN_0041a1a4 IsDerivedFrom(classDerivations) (0x50f4bc = Generator) // FUN_0042076c Subsystem::FindDamageZone(record) -> index // FUN_004dcd94 Round(Scalar) -> int // FUN_004700bc NumericDisplay ctor FUN_0047018c ::dtor // FUN_004703f4 NumericDisplay::Reset FUN_00470430 ::DrawAt FUN_00470758 ::Erase // FUN_00470ec8 NumericDisplay::SetColors FUN_00470cfc NumericDisplayInteger ctor // FUN_00470888 NumericDisplayScalar ctor FUN_00473c94 NumericDisplayScalarTwoState // FUN_004739d8 TwoState ctor FUN_00471d00 BackgroundBitmap ctor // FUN_00472ef0 BarGraph ctor FUN_00472fb4 BarGraph dtor // FUN_00474855 GaugeConnectionDirectOf::ctor FUN_004749de // FUN_004c2ec4 DrawClippedBitmap (file-private, btl4gaug) FUN_004c2f88 -> 7 // FUN_004c3134/004c31ec/004c3288 shared GaugeConnection ctors (btl4gaug TU) // FUN_004c4170 HorizTwoPartBar FUN_004c4724 VertTwoPartBar // FUN_004c4d88 OneOfSeveral FUN_004c5148 OneOfSeveralInt // FUN_004c5470 OneOfSeveralStates FUN_004c5b7c LeakGauge(BitMapInverseWipe) // FUN_004c61c8 BitMapInverseWipeScalar FUN_004c6244 SegmentArc270 // FUN_004c3b98 ColorMapperArmor ctor (btl4gaug) // FUN_0040385c Verify FUN_004dbb24 DebugStream< #pragma hdrstop #if !defined(BTL4GAU2_HPP) # include #endif #if !defined(APP_HPP) # include #endif static const Scalar SeekVoltageXScale = 230.0f; // 0x43660000 static const Scalar SeekVoltageYScale = 187.0f; // 0x433b0000 static const Scalar RedrawSentinel = 9999.0f; // 0x461c3c00 static const Scalar GeneratorMaxVoltage = 12000.0f; // 0x463b8000 static const Scalar HeatNumericBase = 100.0f; // 0x42c80000 // (DebugStream warning channel, DAT_00524e20, is provided by the shared // reconstruction headers -- heat.hpp / mechrecon.hpp.) // // Unrecovered .data resource pool used by GeneratorCluster::Make. Concrete // bytes were not recovered from the optimised image; typed placeholders so the // resolve-and-construct path compiles. (BEST-EFFORT.) // static char DAT_00518f24[] = "GeneratorCluster"; // subsystem name to resolve static int DAT_00518ee0 = 0; // GaugeRate static char DAT_00518f68[] = ""; // background image name // // Original FUN_0041bfc0 = Entity::FindAttributeIndex(name) -> ordinal. The // WinTesla engine exposes attribute lookup via Simulation::AttributeIndexSet // (Find/FindEntry by name) rather than a name->ordinal call, so this best-effort // shim stands in for it; the stored indices are consumed by the (summarised) // SeekVoltageGraph::Execute plot. // static int FindAttributeIndex(Entity *, const char *) { return -1; } //########################################################################### //########################################################################### // SeekVoltageGraph @004c6798 //########################################################################### //########################################################################### // // @004c6798 -- ctor (vtable PTR_FUN_0051a1fc). GraphicGauge base, interns and // ref-counts the "destroyed" bitmap, resolves the four SeekVoltage attribute // indices off the weapon subsystem, sets the port extent (0x97,0x80,0x17d,0x13b) // and stashes the 230x187 plot scale. // SeekVoltageGraph::SeekVoltageGraph( GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer, int graphics_port_number, Entity *subsystem, AttributeAccessor *seek_voltage_pointer, const char *destroyed_image, Logical draw_cursor, const char *identification_string ): GraphicGauge(rate, mode_mask, renderer, /*owner*/0xFFFF, graphics_port_number, identification_string) // FUN_00444818 { // Original interned a copy of the name (FUN_004700ac) + AddRef'd it in the // bitmap cache; retain the persistent resource string and AddRef the bitmap. destroyedImage = (char *)destroyed_image; renderer->warehousePointer->bitMapBin.Get(destroyedImage); // FUN_00442aec (AddRef) currentSeekIndex = FindAttributeIndex(subsystem, "CurrentSeekVoltageIndex"); // FUN_0041bfc0 minSeekIndex = FindAttributeIndex(subsystem, "MinSeekVoltageIndex"); maxSeekIndex = FindAttributeIndex(subsystem, "MaxSeekVoltageIndex"); seekVoltageTable = FindAttributeIndex(subsystem, "SeekVoltage"); voltageSubsystem = (Entity *)seek_voltage_pointer; // this[0x29] this->subsystem = (Subsystem *)subsystem; // this[0x2A] // graphicsView -> GraphicGauge::localView. SetExtent == SetPositionWithinPort; // the original SetClip() (vtbl+0x0C) constrained drawing to that extent. localView.SetPositionWithinPort(0x97, 0x80, 0x17d, 0x13b); // vtbl+0x08 xScale = SeekVoltageXScale; // this[0x2C] yScale = SeekVoltageYScale; // this[0x2D] drawCursor = draw_cursor; // this[0x2F] destroyedShown = 0; // this[0x2E] } // // @004c68ac -- dtor. Release the destroyed bitmap, GraphicGauge::~GraphicGauge. // // @004c6920 -- BecameActive: previousVoltage = 9999.0f (force first redraw). // // @004c6934 -- Execute. If the subsystem is destroyed (subsys+0x40 == 1) draw // the centred "destroyed" bitmap once. Otherwise, when the live seek voltage // (subsys vtbl+0x3c sampler) changes: clear (SetupClip @004c6be4), re-plot the // 0..1 voltage curve as a polyline (step _DAT_004c6bdc up to _DAT_004c6be0, // Round each point), then draw the min/max tick marks (DrawTicks @004c6c6c) // and, if drawCursor, the live cursor at the current seek index // (DrawCursor @004c6c30). // //########################################################################### // ConfigMapGauge @004c6d80 //########################################################################### // // @004c6d80 -- ctor (vtable PTR_FUN_0051a1b8). GraphicGauge base; interns the // joystick base bitmap "btjoy.pcc" (BitMapCache) and the four config-state // pixmaps cm_off/cm_other/cm_only/cm_both.pcc (PixMapCache); sets the port // origin (x,y); subsystem = param_9. // @004c6e54 -- dtor: release btjoy bitmap + 4 pixmaps, GraphicGauge::~GraphicGauge. // @004c6ee0 -- SetColor: this[0x25] = color. // @004c6ef4 -- BecameActive: dirty=1; previousState[0..3] = -1. // @004c6f1c -- Execute. When dirty, blit the base joystick bitmap. Then for // each of the 4 config slots, read the control-mapper state via the table // DAT_00518eb8 (renderer+0x3c port + 0x1c0 + slot*0x20, sampler vtbl+0x24) and, // if it changed, MoveTo + stretch-blit the matching cm_* pixmap. // //########################################################################### // OneOfSeveral data-driven lamps @004c70a4 / @004c7160 //########################################################################### // // @004c70a4 -- AnimatedSubsystemLamp ctor (vtable PTR_FUN_0051a174): chains // OneOfSeveral::OneOfSeveral (@004c4d88, fromImageStrip=1), selected=0, then // AddConnection(new (&selected, source)). dtor @004c7134. // // @004c7160 -- AnimatedSourceLamp ctor (vtable PTR_FUN_0051a130): identical but // the connection ctor is @004c31ec. dtor @004c71f0. // // Both add the connection via (*this+0x34) AddConnection and otherwise inherit // OneOfSeveral::Execute @004c4f28 (frame select + blit). // //########################################################################### // ScalarBarGauge @004c721c / @004c72ac //########################################################################### // // @004c721c -- ctor (vtable PTR_FUN_0051a0e4): chains the MUNGA L4 bar primitive // (@00472ef0) then AddConnection(new (&value, source)). // @004c72ac -- same vtable, but AddConnection(new GaugeConnectionDirectOf // (@00474855)(&value, scalar)). Both share dtor @004c733c (chains @00472fb4). // Used as the generator-voltage bar with range 0..12000.0f. // //########################################################################### //########################################################################### // GeneratorCluster @004c7368 Make / @004c746c ctor //########################################################################### //########################################################################### // // @004c7368 -- Make. Resolve the named subsystem ("GeneratorCluster") via // Entity::FindSubObject (DAT_00518f24); on failure warn "Subsystem not // found" and return 0. Else allocate (0xb4) and construct, passing the four // resource strings / colours from DAT_00518e..00519298. // Logical GeneratorCluster::Make( int /*display_port_index*/, Vector2DOf /*position*/, Entity *entity, GaugeRenderer *gauge_renderer ) { Subsystem *subsystem = entity->FindSubsystem((char *)&DAT_00518f24); // FUN_0041f98c if (subsystem == NULL) { DebugStream << "Subsystem " << (char *)&DAT_00518f24 << " not found\n"; // FUN_004dbb24 x3 return False; } GeneratorCluster *gauge = (GeneratorCluster *)operator new(0xb4); if (gauge != NULL) { // // Construct with the recovered subsystem + name; the geometry / colour / // image-name resource arguments (DAT_00518f68..00519298) were not // recovered from the optimised image, so are passed as typed placeholders. // new (gauge) GeneratorCluster( (GaugeRate)DAT_00518ee0, // rate (ModeMask)0, // mode mask (L4GaugeRenderer *)gauge_renderer, 0, // graphics port number 0, 0, // x, y (char *)&DAT_00518f68, // background image 0, // color (char *)0, // temperature tile (Scalar *)0, (Scalar *)0, // temp low / high (char *)0, // voltage tile (Scalar *)0, // voltage low (char *)0, // leak image (char *)0, (char *)0, // lampA / lampB images 0, 0, // on / off colours subsystem, "GeneratorCluster"); } return True; } // // @004c746c -- ctor (vtable PTR_FUN_0051a0a0). GraphicGauge base; resolves // CurrentTemperature/DegradationTemperature/FailureTemperature/ // CoolantMassLeakRate/OutputVoltage attribute indices; interns the background // image; then builds the five child gauges (each parented at this graphics // port, offset from x,y): // this[0x26] = new VertTwoPartBar(...,CurrentTemp,Degrade,Fail) @004c4724 // this[0x27] = new ScalarBarGauge(0..12000, OutputVoltage) @004c72ac // this[0x28] = new LeakGauge(CoolantMassLeakRate) @004c5b7c // this[0x29] = new TwoState(lampA, subsys+0x1d4) @004739d8 // this[0x2A] = new TwoState(lampB, subsys+0x1d4) @004739d8 // this[0x2B] = subsystem // @004c7778 -- dtor: release the background, delete the five children, base dtor. // //########################################################################### //########################################################################### // PrepEngrScreen @004c7b30 Make / @004c7bf0 ctor //########################################################################### //########################################################################### // // @004c7b30 -- Make. DAT_0051936c is the engineer-screen number; must be 1..12 // or "PrepEngr: screen number out of range " is warned. Allocates (0x90) // and constructs with seven status-image names (DAT_005193b0..00519548). // // @004c7bf0 -- ctor (vtable PTR_FUN_0051a06c). Derives from the non-graphic // Gauge group (FUN_004440d4) -- it owns no GraphicsView, only a child-gauge // chain at +0x24. Interns and BitMapCache-AddRefs the seven status pixmaps // (this[0x1D..0x23]); stores mech (this[0x1B]) and screen number (this[0x1C]). // // @004c7d14 -- dtor: release + free the seven images, tear down the child chain // (FUN_0044ae0c), Gauge-group dtor (FUN_00443f7c). // // @004c7e48 -- Execute. Walk the mech's critical-subsystem roster // (mech+0x124 count, mech+0x128 array). For each subsystem that (a) is a // Generator-derived weapon (IsDerivedFrom 0x50f4bc) and (b) belongs to the // selected screen (subsys+0x1dc == screenNumber), draw its label and -- via // NumericDisplay (FUN_004700bc/0047043 0) -- its temperature and a HeatSink // read-out, then dispatch on ClassID to lay out the weapon's status bitmaps // (FUN_004c79c8 = draw three labelled status cells): // 0xBC3 Sensor -> one cell + ammo bitmap (this[0x23]) // 0xBC6 -> two cells (this[0x22],this[0x20]) // 0xBC8/0xBD4 Emitter/PPC -> three cells (this[0x1E..0x20]) // 0xBCD/0xBD0 Proj/Missile -> one cell (this[0x21]) // 0xBCE GaussRifle -> warn "Gauss rifle not yet supported", one cell // //########################################################################### //########################################################################### // SubsystemCluster family @004c8140 base //########################################################################### //########################################################################### // // @004c8140 -- SubsystemCluster ctor (vtable PTR_FUN_0051a020). GraphicGauge // base. Resolves InputVoltage/HeatSink/CurrentTemperature/Degradation/Failure // attribute indices, then builds the panel's child gauges into its port: // this[0x26] HorizTwoPartBar (temperature) @004c4170 // this[0x27] AnimatedSubsystemLamp ("CoolingLoop",btploop) @004c70a4 // this[0x29] AnimatedSourceLamp ("PowerSource",btpbus) @004c7160 (if InputVoltage) // this[0x24] BackgroundBitmap (if background present) @00471d00 // this[0x28] AnimatedSubsystemLamp (bteloop) @004c70a4 // this[0x2D] OneOfSeveralInt (btecmode, subsys+0x134) @004c5148 // this[0x2A] AnimatedSourceLamp (btebus) @004c7160 (if InputVoltage) // this[0x25] ScalarBarGauge (evolt, GeneratorVoltage) @004c721c (if InputVoltage) // this[0x2E] OneOfSeveralStates (btemode, subsys+0x2b8) @004c5470 // (only when subsystem IsDerivedFrom Generator 0x50f4bc) // this[0x2C] VertTwoPartBar x2 (temperatures) @004c4724 // this[0x2F] LeakGauge (eleak, CoolantMassLeakRate) @004c5b7c // this[0x30] subsystem ; this[0x31] operating // @004c87dc -- dtor: GraphicGauge::~GraphicGauge (children freed by subclasses). // @004c88e4 -- Execute: operating = (subsys+0x40==1); when it changes, repaint // the panel frame (operational => coloured rectangle; offline => background // bitmap blit) and forward enable to the temperature/loop children // (SetEnable @004c8a28 / FUN_00444650). // // @004c8a6c -- HeatSinkCluster ctor (vtable PTR_FUN_00519fd4): chains // SubsystemCluster, this[0x36]=100.0f, then builds four failure TwoStates // (this[0x37] heat, this[0x38] btehfail, this[0x39] btepfail subsys+0x324, // this[0x3A] btesfail subsys+0x320) and a NumericDisplayScalar (this[0x3B], // helv18, this[0x36]) plus a Scalar connection (&this[0x35], subsys+0x31c). // Execute @004c8db0: failFlag = (failSubsystem+0x40==1); heatLoadScaled = // heatLoad * _DAT_004c8df0; chain SubsystemCluster::Execute. // // @004c8fc4 -- WeaponCluster ctor (vtable PTR_FUN_00519f38): chains // SubsystemCluster; resolves "PercentDone"; interns the cluster image // (this[0x33]); warns "WeaponCluster missing " if absent; centres a // SegmentArc270 recharge dial (this[0x34], 0..360, @004c6244) and a // ConfigMapGauge (this[0x35], "ConfigMap", @004c6d80); adds a Scalar connection // (&percentDone, PercentDone). Execute @004c9290: chain base Execute; when // percentDone > _DAT_004c92e0 toggle the warning lamp (DrawWarningLamp @004c932c). // // @004c93b0 -- EnergyWeaponCluster ctor (vtable PTR_FUN_00519ee8): chains // WeaponCluster; adds a SeekVoltageGraph (this[0x3A], "EngrGraph", edestryd.pcc, // @004c6798) reading OutputVoltage, and a seek-step OneOfSeveralInt (this[0x3B], // bteseek.pcc, subsys+0x3f0, @004c5148). dtor @004c94dc. // // @004c9558 -- BallisticWeaponCluster ctor (vtable PTR_FUN_00519e98): chains // WeaponCluster; resolves the ammo bin (Resolve subsys+0x43c) and builds: // this[0x45]/[0x46] NumericDisplayInteger (ammo counts) @00470cfc // this[0x42] TwoState (btejam) this[0x43] TwoState (btefire) @004739d8 // this[0x3F] GraphicsViewRecord erase tracker @0044ad78 // this[0x40] NumericDisplayScalarTwoState (helv42) @00473c94 // this[0x41] TwoState (edestryd) @004739d8 // this[0x44] BitMapInverseWipeScalar (bteejtm, subsys+0x3f8) @004c61c8 // Execute @004c9a38: jammed = (subsys+0x364==5 weaponAlarm Jammed); read the // ammo-bin reload state (bin+0x18c) and, while reloading, compute elapsed // seconds (frame clock @00414b60 / DAT_0052140c); chain WeaponCluster::Execute. // TestInstance @004c9adc: True unless the ammo bin is present and the eject // wipe is mid-cycle. dtor @004c9940 frees the GraphicsViewRecord + numeric. // // === btl4gau3.cpp begins at @004c9bd0 (PlayerStatusMappingGroup) -- not this TU.