//===========================================================================// // File: thermalsight.cpp // // Project: BattleTech // // Contents: ThermalSight (thermal / infra-red vision mode) subsystem // //---------------------------------------------------------------------------// // 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). Cluster @004b8718..@004b881c. Each method cites its @ADDR. // // Helper-function name mapping: // FUN_004b18a4 PowerWatcher base constructor (powersub.cpp) // FUN_004b198c PowerWatcher::CreateStreamedSubsystem (powersub.cpp) // FUN_004b181c PowerWatcher base per-frame update (powersub.cpp) // FUN_004b179c PowerWatcher::HandleMessage (slot 9) (powersub.cpp) // FUN_004b1804 PowerWatcher::ResetToInitialState (slot10) (powersub.cpp) // FUN_004b1930 ~PowerWatcher (powersub.cpp) // FUN_0041b9ec AlarmIndicator(levels) // FUN_0041baa4 ~AlarmIndicator // FUN_0041bbd8 AlarmIndicator::SetLevel(n) // FUN_0041a1a4 IsDerivedFrom(classDerivations) // FUN_0045fe44 ToggleGlobalThermalVision (flips _DAT_004f1ab8 "pvision", // prints "pvision ON/OFF", re-applies the view palette) // FUN_004022d0 operator delete / global free // PTR_DAT_004fd4b8 the active L4 application/viewport (its +0x48 flag is // non-zero only when THIS mech is the locally-viewed mech) // #include #pragma hdrstop #if !defined(THERMALSIGHT_HPP) # include #endif #if !defined(APP_HPP) # include #endif #if !defined(TESTBT_HPP) # include #endif //########################################################################### // Shared Data Support // Derivation ThermalSight::ClassDerivations( // @00511238 PowerWatcher::GetClassDerivations(), "ThermalSight" ); Receiver::MessageHandlerSet ThermalSight::MessageHandlers; ThermalSight::AttributeIndexSet ThermalSight::AttributeIndex; ThermalSight::SharedData ThermalSight::DefaultData( // @00511228 &ThermalSight::ClassDerivations, ThermalSight::MessageHandlers, ThermalSight::AttributeIndex, ThermalSight::StateCount ); //########################################################################### // Construction -- @004b8718 // // Chains to the PowerWatcher ctor (FUN_004b18a4) with &DAT_00511228, installs // the ThermalSight vtable (PTR_FUN_00511498), builds the 2-level state // AlarmIndicator (@0x1E0). When this is a live (non-copy) segment with the // has-performance flag set it registers ThermalSightSimulation // (this[7..9] <- PTR_FUN_00511290). // ThermalSight::ThermalSight( Mech *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data ): PowerWatcher(owner, subsystem_ID, subsystem_resource, shared_data) { Check(owner); Check_Pointer(subsystem_resource); segmentFlags = 0; hostShutDown = False; watchedVoltageLevel = 4; // Ready heatStateLevel = 0; // NormalHeat thermalActive = 0; // @0x1D8 requestedOn = 0; // @0x1DC stateAlarm.Initialize(2); // FUN_0041b9ec(this+0x1E0, 2) if (((GetSegmentFlags() & 0xC) == 0) && ((GetSegmentFlags() & 0x100) != 0)) { SetPerformance(&ThermalSight::ThermalSightSimulation); // this[7..9] <- PTR_FUN_00511290 } Check_Fpu(); } // // Destruction -- @004b8794 (vtable slot0). Reinstalls the vtable, tears down // the AlarmIndicator (@0x1E0), chains to ~PowerWatcher (FUN_004b1930), frees // the block when the deleting-dtor bit is set. // ThermalSight::~ThermalSight() { Check(this); stateAlarm.Finalize(); // FUN_0041baa4(this+0x1E0, 2) Check_Fpu(); } //########################################################################### // TestInstance -- @004b881c // Logical ThermalSight::TestInstance() const { return IsDerivedFrom(ClassDerivations); // FUN_0041a1a4(**this[3], 0x00511238) } Logical ThermalSight::TestClass(Mech &) { return True; // BEST-EFFORT (family convention) } //########################################################################### // ThermalSightSimulation -- @004b8648 (Performance) // // Same power/heat gating as the Searchlight, but the watched quantity is the // thermal-vision mode, and when the active state CHANGES on the locally-viewed // mech it toggles the global "pvision" render flag: // * base tick (FUN_004b181c). // * thermalActive follows requestedOn (@0x1DC) unless the host is shut down // (this[0x40] == 1), in which case it is forced off. // * the watched-voltage alarm level (@0x198) must read Ready(4); else blank. // * heat-state level (@0x140): <2 keeps it, ==2 blanks it. // * push on/off into the AlarmIndicator (@0x1E0). // * if the state changed AND this mech is the one being viewed // (PTR_DAT_004fd4b8 -> +0x48 != 0), call ToggleGlobalThermalVision // (FUN_0045fe44) to flip the cockpit IR view. // void ThermalSight::ThermalSightSimulation(Scalar time_slice) { Check(this); PowerWatcher::Simulation(time_slice); // FUN_004b181c (base per-frame update) int previous = thermalActive; // @0x1D8 thermalActive = (HostShutDown()) ? 0 : requestedOn; // this[0x40]==1 ? 0 : @0x1DC if (WatchedVoltageLevel() == 4) // @0x198 == Ready thermalActive = (thermalActive != 0); else thermalActive = 0; if (HeatStateLevel() < 2) // @0x140 thermalActive = (thermalActive != 0); else if (HeatStateLevel() == 2) thermalActive = 0; stateAlarm.SetLevel(thermalActive); // FUN_0041bbd8(this+0x1E0, thermalActive) if ((previous != thermalActive) && (LocalViewport()->viewingThisMech != 0)) { ToggleGlobalThermalVision(); // FUN_0045fe44 } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CreateStreamedSubsystem -- ThermalSight @004b87d4 // // Chains to PowerWatcher::CreateStreamedSubsystem (FUN_004b198c) then stamps // classID 0x0BDE (+0x20) and model size 0xF4 (+0x24). No thermal-specific // fields are read. // int ThermalSight::CreateStreamedSubsystem( NotationFile *model_file, const char *model_name, const char *subsystem_name, SubsystemResource *subsystem_resource, NotationFile *subsystem_file, const ResourceDirectories *directories, int passes ) { if ( !PowerWatcher::CreateStreamedSubsystem( // FUN_004b198c model_file, model_name, subsystem_name, subsystem_resource, subsystem_file, directories, passes ) ) { return False; } subsystem_resource->subsystemModelSize = 0xF4; // +0x24 subsystem_resource->classID = RegisteredClass::ThermalSightClassID; // 0x0BDE, +0x20 return True; }