//===========================================================================// // File: hud.hpp // // Project: BattleTech // // Contents: Cockpit Heads-Up Display subsystem // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // --/--/95 ?? Initial coding. // //---------------------------------------------------------------------------// // Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// // // RECONSTRUCTED from the shipped binary (Ghidra pseudo-C, recovered shard // part_013.c) cross-referenced with the sibling subsystem sources // (powersub.hpp/.cpp, heat.hpp/.cpp, sensor.hpp/.cpp). NO HUD.HPP survived; // the class body below is inferred from usage, the embedded string pool and // the streamed-resource / attribute tables. Each method cites its @ADDR. // // --------------------------------------------------------------------------- // IDENTIFICATION (resolves a CLASSMAP "gap") // --------------------------------------------------------------------------- // * mech3.cpp factory map: HUD::CreateStreamedSubsystem @004b81d4, // DefaultData &DAT_00511078. // * vtable @0050511510 (slot0 dtor @004b816c), ctor @004b7f94. // * CreateStreamedSubsystem @004b81d4 stamps classID 0x0BD6 and streamed // model size 0x104 (resource +0x20 / +0x24), and parses the HUD-specific // model fields "FlickerRate" / "HorizontalMovementPerSecond" / // "HorizontalLimit" plus a "SegmentPageName" index. // * String pool @005112d0..@00511390 ("HUD", "FlickerRate", // "RotationOfTorsoHorizontal", "HorizontalTorsoLimitRight/Left", // "SpeedOfTorsoHorizontal", "RangeToTarget", "Visible", "Lock", // "HotBoxVector", "ThreatVector", "CompassHeading") names the gauge // read-out attributes. // // CLASSMAP.md "Resolved conflict" already flagged @004b7f94 / vtable // @00511510 as "the HUD torso-horizon gimbal display" mis-labelled // "MechTech" by mech.cpp's factory switch (case 0xBD6). This file confirms // that: classID 0xBD6, base PowerWatcher. // // --------------------------------------------------------------------------- // BASE CLASS // --------------------------------------------------------------------------- // HUD IS-A PowerWatcher (powersub.hpp): the ctor @004b7f94 chains to the // PowerWatcher ctor FUN_004b18a4 and CreateStreamedSubsystem chains to // PowerWatcher::CreateStreamedSubsystem FUN_004b198c. PowerWatcher is a // HeatWatcher/HeatableSubsystem-derived *monitor* subsystem (NOT a // PoweredSubsystem); the HUD therefore inherits the heat/voltage watchdog // state (heat-state level @0x140, watched-voltage alarm level @0x198) used // by the per-frame update. The shared base object occupies bytes 0..0x1D8; // HUD's own members begin at 0x1D8. Total object size 0x2A4 (matches // mech.cpp factory allocation for the 0xBD6 case). // #if !defined(HUD_HPP) # define HUD_HPP #if !defined(POWERSUB_HPP) #include "powersub.hpp" #endif //########################################################################## //####################### HUD::SubsystemResource ##################### //########################################################################## // // Extends the PowerWatcher/HeatableSubsystem resource record. The HUD fields // begin at +0xF4 (see CreateStreamedSubsystem @004b81d4). // struct HUD__SubsystemResource: public PowerWatcher::SubsystemResource { Scalar flickerRate; // +0xF4 "FlickerRate" (defaults to -1.0 in the SegmentPage form) int segmentPageIndex; // +0xF8 resolved "SegmentPageName" (copied from +0x28) Scalar horizontalMovementPerSecond; // +0xFC "HorizontalMovementPerSecond" Scalar horizontalLimit; // +0x100 "HorizontalLimit" }; //########################################################################## //############################## HUD ################################# //########################################################################## class HUD: public PowerWatcher { friend struct HUDLayoutCheck; // live Watcher-branch re-base witness (hud.cpp) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Shared Data Support // // DefaultData @00511078, ClassDerivations @00511088 ("HUD"). // public: static Derivation *GetClassDerivations(); // @00511088 (engine moved to accessor form) static SharedData DefaultData; // @00511078 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Attribute Support // // AttributePointers IndexEntry table @005110c0 (each record binds a name // to an attribute id and an object offset, the offset encoded as // byte_offset|1 -- the same scheme used by sensor.hpp). Recovered: // id 4 "RotationOfTorsoHorizontal" -> @0x1D8 // id 5 "HorizontalTorsoLimitRight" -> @0x1DC // id 6 "HorizontalTorsoLimitLeft" -> @0x1E0 // id 7 "SpeedOfTorsoHorizontal" -> @0x1E4 // id 8 "RangeToTarget" -> @0x1E8 // id 9 "Visible" -> @0x1EC // id 10 "Lock" -> @0x1F4 // id 11 "HotBoxVector" -> @0x1F8 // id 12 "ThreatVector" -> @0x1FC (Vec3) // id 13 "CompassHeading" -> @0x208 (Vec3) // (FlickerRate name ptr @005110bc heads the table as the category label.) // // CONFIRMED (task #37): the recovered reticle Execute @004cdcf0 binds and // USES ids 4/5/6/8/0xA/0xB/0xC/0xD exactly per these names -- // RotationOfTorsoHorizontal drives the twist tape over the // HorizontalTorsoLimit full-scales, RangeToTarget the range caret, Lock // the spinning lock ring, HotBoxVector the target box (eye-space vec3), // ThreatVector the compass threat trail, CompassHeading the rose // rotation. (The earlier note about @0x1D8/@0x1EC/@0x1F8 usage remains // for the ctor-side seeds only.) // public: enum { RotationOfTorsoHorizontalAttributeID = PowerWatcher::NextAttributeID, // 4 HorizontalTorsoLimitRightAttributeID, // 5 HorizontalTorsoLimitLeftAttributeID, // 6 SpeedOfTorsoHorizontalAttributeID, // 7 RangeToTargetAttributeID, // 8 VisibleAttributeID, // 9 LockAttributeID, // 10 HotBoxVectorAttributeID, // 11 ThreatVectorAttributeID, // 12 CompassHeadingAttributeID, // 13 NextAttributeID }; private: static const IndexEntry AttributePointers[]; // @005110c0 protected: static AttributeIndexSet AttributeIndex; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Local data. Offsets are byte offsets into the shipped object; names are // best-effort from the attribute pool + ctor/HudSimulation usage. // protected: Scalar flickerRate; // @0x1D8 resource +0xF4 (flicker / blink period threshold) // Torso / target read-outs sampled each construction from the linked // targeting entity (owner Mech +0x438 -> this->linkedEntity @0x234): Scalar torsoLimitRight; // @0x1DC <- linkedEntity +0x1D8 Scalar torsoLimitLeft; // @0x1E0 <- linkedEntity +0x1DC Scalar torsoSpeed; // @0x1E4 <- linkedEntity +0x1E0 Scalar rangeToTarget; // @0x1E8 <- linkedEntity +0x1E8 (and recomputed in sim @0x1EC) Scalar targetRange; // @0x1EC computed line-of-sight distance to the target int lockFlag; // @0x1F4 init 1 int visible; // @0x1F8 set 0/1 from heat + line-of-sight each frame Point3D threatVector; // @0x1FC init (0,0,0) ("ThreatVector") Point3D compassHeading; // @0x208 init (0,0,0) ("CompassHeading"); see SetCompassHeading Scalar hotBoxScalar; // @0x214 init 0 Scalar blinkTimer; // @0x218 accumulates time, reset against flickerRate Scalar flickerTimer; // @0x21C int blinkState; // @0x224 init 1 (visible phase of the blink) int transitionFlag; // @0x22C init 0 Scalar previousHorizontal; // @0x230 int linkedEntity; // @0x234 owner Mech +0x438 (active weapon/reticle source) HeatAlarm statusAlarm; // @0x238 2-level page/status indicator (Initialize/SetLevel surface) // Free-aim / reticle-slew demand: WRITTEN by MechControlsMapper::InterpretControls // (@004afd10 cockpit+0x28c <- stick yaw when the torso's horizontal twist is // disabled; zeroed in Basic mode). Was placeholder-named flickerPhase (init-only). Scalar freeAimSlew; // @0x28C public: void SetFreeAimSlew(Scalar v) { freeAimSlew = v; } // mapper write (@004afd10 cockpit+0x28c) protected: Scalar scratch290; // @0x290 init 0 Scalar horizontalTorsoOffset; // @0x294 init 0; clamped to +/- horizontalLimit, written to owner +0x36C Scalar horizontalMovementPerSecond; // @0x298 resource +0xFC Scalar horizontalLimit; // @0x29C resource +0x100 int flickerActive; // @0x2A0 current flicker on/off (UpdateFlicker @004b7ed4) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Simulation Support // public: typedef void (HUD::*Performance)(Scalar time_slice); void SetPerformance(Performance performance) { Check(this); activePerformance = (Simulation::Performance)performance; } void HudSimulation(Scalar time_slice); // @004b7830 (Performance, PTR @00511170) void SetCompassHeading(const Point3D &heading); // @004b7810 (writes compassHeading @0x208) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Subsystem virtual overrides (vtable @00511510) // public: Logical HandleMessage(int message); // slot 9, @004b7780 (body not captured) void ResetToInitialState(Logical powered = True); // slot 10, @004b77bc //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Test Class Support // public: static Logical TestClass(Mech&); Logical TestInstance() const; // @004b81b8 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construction and Destruction // public: typedef HUD__SubsystemResource SubsystemResource; HUD( Mech *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data = DefaultData ); // @004b7f94 ~HUD(); // @004b816c static int CreateStreamedSubsystem( // @004b81d4 NotationFile *model_file, const char *model_name, const char *subsystem_name, SubsystemResource *subsystem_resource, NotationFile *subsystem_file, const ResourceDirectories *directories, int passes = 1 ); protected: // Flicker helper @004b7ed4: drives flickerActive (@0x2A0) toward 0, // returns non-zero while still flickering. Logical UpdateFlicker(Scalar time_slice); // @004b7ed4 // // Reconstruction accessors for the inherited watchdog state read by // HudSimulation: heat-watcher flag (this+0x40), watched-voltage alarm // level (@0x198) and heat-state level (@0x140). The PowerWatcher / // HeatWatcher base in this header set does not expose these, so they are // best-effort placeholders that let the per-frame page-gating logic // compile; a human should bind them to the real inherited members. // (See CROSS-FAMILY NEEDS.) // int HeatWatcherFlag() const { return 0; } int WatchedVoltageLevel() const { return 0; } int HeatStateLevel() const { return 0; } }; #endif