Files
TeslaRel410/restoration/source410/BT/TORSO.HPP
T
CydandClaude Fable 5 bd1070110b BT410 5.3.71: torso button commands wired into the sim; residual fault rate measured
TorsoSimulation now carries the donor's digital command handling (binary
@004b5cf0): elevate up/down, twist left/right with limit clamps, the
centre-button recenter latch slewing home across frames, and the ramp
machinery kept verbatim including the binary's punchline -- the shipped build
unconditionally overwrites the ramp with 1.0f, authored dead weight preserved
as the binary's shape.  recenterActive carved from the dynamicsState reserve.
With 5.3.68's table fix the RIO/TM twist buttons land in these members and
move the torso, and the canopy eye rides the twist chain.

Also corrected in the roadmap: the 5.3.70 TriggerState 'wart' was not a wart
-- CheckFireEdge already compares fireImpulse's bit pattern as a signed int,
sign-correct for button ints and floats alike, and the donor binds and types
the member identically.

Fault rate, measured: riostreak.sh ran four consecutive vRIO-live runs --
CLEAN/CLEAN/FAULT/CLEAN, faults only ever in the load window (ticks 42-53k),
clean runs always past launch.  Post-fix tally 8 runs / 2 faults (~25%; was
3/3 before the Torso fix).  Our load window is ~60s where shipped's is ~15s:
if the residual is a constant-rate hazard during load, shipped's expected
per-run rate is only ~7% -- 'shipped survives' may be exposure luck, and the
residual is most likely an emulator-fork serial/DPMI interaction rather than
a game defect.  Next probe: hook the fork's page-fault path on the fixed cr2
and dump recent serial-IRQ deliveries + guest cs:ip history, plus a
shipped-exe streak for the baseline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 15:44:12 -05:00

210 lines
7.3 KiB
C++

//===========================================================================//
// File: torso.hpp //
// Project: BattleTech Brick: Mech subsystems //
// Contents: Torso -- the torso twist / weapon-elevation subsystem //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(TORSO_HPP)
# define TORSO_HPP
# if !defined(POWERSUB_HPP)
# include <powersub.hpp>
# endif
//##################### Forward Class Declarations #######################
class Mech;
class Joint;
//###########################################################################
//##################### Torso Model Resource ###########################
//###########################################################################
struct Torso__SubsystemResource:
public PowerWatcher::SubsystemResource
{
Scalar horizontalRotationPerSecond;
Scalar verticalRotationPerSecond;
Scalar horizontalLimitRight;
Scalar horizontalLimitLeft;
Scalar verticalLimitTop;
Scalar verticalLimitBottom;
char torsoHorizontalJoint[32];
char torsoHorizontalShadowJoint[32];
Logical torsoHorizontalEnabled;
Scalar buttonAccelerationPerSecond;
Scalar buttonAccelerationStartValue;
};
//###########################################################################
//############################### Torso ################################
//###########################################################################
//
// Drives torso twist (horizontal) and weapon elevation (vertical). The
// tuning rates/limits come from the resource; the live twist/elevation state
// and the resolved skeleton joints are advanced by the per-frame
// TorsoSimulation (staged) once the Mech skeleton link is live.
//
class Torso:
public PowerWatcher
{
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
typedef void
(Torso::*Performance)(Scalar time_slice);
void
SetPerformance(Performance performance)
{
Check(this);
activePerformance = (Simulation::Performance)performance;
}
static Logical
TestClass(Mech &);
Logical
TestInstance() const;
Scalar
CurrentTwist() const { Check(this); return currentTwist; }
Scalar
CurrentElevation() const { Check(this); return currentElevation; }
Logical
GetHorizontalEnabled() const{ Check(this); return horizontalEnabled; }
//
// Analog aim inputs (written by MechControlsMapper::InterpretControls;
// consumed by TorsoSimulation to slew the twist/elevation each frame).
//
void
SetAnalogElevationAxis(Scalar axis) { Check(this); analogElevationAxis = axis; }
void
SetAnalogTwistAxis(Scalar axis) { Check(this); analogTwistAxis = axis; }
void
TorsoSimulation(Scalar time_slice);
void
TorsoCopySimulation(Scalar time_slice);
public:
typedef Torso__SubsystemResource SubsystemResource;
Torso(
Mech *owner,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &shared_data = DefaultData
);
~Torso();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute publication. The shipped string pool lists this class's
// attribute names contiguously after the class name "Torso":
//
// RotationOfTorsoVertical RotationOfTorsoHorizontal
// HorizontalLimitRight HorizontalLimitLeft
// SpeedOfTorsoVertical SpeedOfTorsoHorizontal
//
// The FULL authentic table, ids 3..15, confirmed twice over: the BT411
// donor's decompiled enum carries these names WITH binary member offsets
// (torso.hpp 111-124, @0x1E4..@0x20C), and BTL4.RES's own streamed
// control mappings bind ids 12/13 as DIRECT button destinations on
// subsystem 17 = Torso (the [map] audit).
//
// An earlier revision declared "TorsoUp/Down/Left/Right/Center are
// MESSAGES, not attributes" and stopped at 7 entries with MotionState at
// id 9. That was WRONG in a specifically nasty way: the ids are the
// binding key for the streamed mappings, so Thrustmaster's buttons
// (12/13) resolved NULL -- the boot write-fault at
// ControlsInstanceDirectOf<int>::Update+0xE -- and the RIO's ANALOG
// StickPosition (9) resolved to our motionState StateIndicator, letting
// every analog update from a live RIO smash a watcher-socketed object
// with raw floats.
//
// The chain -- PowerWatcher -> HeatWatcher -> MechSubsystem -- publishes
// nothing of its own, so these start at MechSubsystem::NextAttributeID.
//
public:
enum {
RotationOfTorsoVerticalAttributeID = MechSubsystem::NextAttributeID,
RotationOfTorsoHorizontalAttributeID,
HorizontalLimitRightAttributeID,
HorizontalLimitLeftAttributeID,
SpeedOfTorsoVerticalAttributeID,
SpeedOfTorsoHorizontalAttributeID,
StickPositionAttributeID,
TorsoUpAttributeID,
TorsoDownAttributeID,
TorsoLeftAttributeID,
TorsoRightAttributeID,
TorsoCenterAttributeID,
MotionStateAttributeID,
NextAttributeID
};
static const IndexEntry AttributePointers[];
static AttributeIndexSet AttributeIndex;
protected:
int isDamagedCopy;
int statusFlags;
Logical horizontalEnabled;
Scalar baseTwistRate;
Scalar baseElevationRate;
Scalar horizontalLimitRight;
Scalar horizontalLimitLeft;
Scalar verticalLimitTop;
Scalar verticalLimitBottom;
Scalar twistCenterHigh;
Scalar twistCenterLow;
Scalar elevationCenter;
Scalar elevationHalfBottom;
Scalar buttonAccelerationPerSecond;
Scalar buttonAccelerationStart;
int buttonRampActive;
Scalar buttonRamp;
Joint *horizontalJointNode;
Joint *horizontalShadowJointNode;
Scalar currentTwist;
Scalar currentElevation;
Scalar analogElevationAxis;
Scalar analogTwistAxis;
//
// MUST BE A StateIndicator. The authored watcher for a *State
// name is an AudioStateWatcher, which is AudioWatcherOf<StateIndicator>
// and whose ctor immediately runs
// Cast_Object(StateIndicator*, attributePointer)->AddAudioWatcher(this)
// (AUDWTHR.CPP:891). Point it at a plain int and that call goes
// through garbage -- the pod dies on the extender.
//
StateIndicator motionState; // authored watcher
//
// The five BUTTON COMMAND destinations (donor torso.hpp @0x1F8-0x208).
// The streamed control mappings bind these BY ID as DIRECT WRITE
// targets -- LBE4ControlsManager::CreateStreamedMappings registers
// GetAttributePointer(attributeID) as the destination a device poll
// writes through (L4CTRL.CPP:1936). Carved from the front of the
// dynamicsState reserve so the class size is unchanged.
//
int elevateUpCommand;
int elevateDownCommand;
int twistLeftCommand;
int twistRightCommand;
int centerCommand;
//
// Recenter latch (donor @0x268-adjacent family): armed by the centre
// button, cleared by a twist button or on arrival at centre.
//
int recenterActive;
//
// Twist/elevation dynamics accumulators advanced by TorsoSimulation.
// Reserved until the per-frame sim is reconstructed (phase 5).
//
Scalar dynamicsState[16];
};
#endif