Mech: THE 0xBD3 UNTANGLE -- real SubsystemMessageManager in [0x10d], the mapper's one true home is roster slot 0 (task #7)
Binary census [T1]: mech+0x434 has exactly 2 writers (ctor init + factory case 0xBD3) and ONE reader (@0x4b984b in MechWeapon::SendDamageMessage @004b9728) -- pure message-manager semantics, nothing mapper-like. The factory case now builds the real SubsystemMessageManager (ctor @0049bca4, 0x130, ConsolidateAndSendDamage Performance); the misbuilt MechControlsMapper squatter is evicted. Every mapper consumer re-pointed to MappingMapper() (roster slot 0 = the binary's **(mech+0x128); SetMappingSubsystem @0049fe40 touches ONLY slot 0 -- its [0x10d] mirror removed). Non-viewpoint mechs get a slot-0 demand LATCH (base mapper, [T3] accommodation -- the binary leaves slot 0 NULL off-viewpoint but never drives/animates those paths; ours does). Verified: solo drive+gait clean; MP replicant gait through the latch (full run lifecycle); 3x kill/respawn cycle with type-6 records on the observer. Remaining (task #7 tail): the messmgr's consolidated TakeDamageStream send + weapon-path routing (@004b9728 real body). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
8ed6184d65
commit
afefaeece5
@@ -153,7 +153,8 @@ void Mech::SetMappingSubsystem(Subsystem *subsystem)
|
|||||||
delete subsystemArray[0];
|
delete subsystemArray[0];
|
||||||
}
|
}
|
||||||
subsystemArray[0] = subsystem;
|
subsystemArray[0] = subsystem;
|
||||||
controlsMapper = (MechControlsMapper *)subsystem;
|
// (task #7: no [0x10d] mirror -- the binary FUN_0049fe40 touches ONLY
|
||||||
|
// slot 0; the 0x434 cache belongs to the SubsystemMessageManager.)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bring-up): raise a mech-level status alarm of the given id.
|
// TODO(bring-up): raise a mech-level status alarm of the given id.
|
||||||
|
|||||||
+32
-10
@@ -389,6 +389,12 @@ template<class...A> inline void ParseVector(A&&...) {}
|
|||||||
template<class...A> inline int ParseJointResource(A&&...) { return 0; }
|
template<class...A> inline int ParseJointResource(A&&...) { return 0; }
|
||||||
template<class...A> inline int CreateModelResourceBase(A&&...){ return 0; }
|
template<class...A> inline int CreateModelResourceBase(A&&...){ return 0; }
|
||||||
template<class...A> inline void StreamDamageZone(A&&...) {}
|
template<class...A> inline void StreamDamageZone(A&&...) {}
|
||||||
|
|
||||||
|
// task #7: the factory-case enum under its true name (0xBD3 was mislabeled
|
||||||
|
// MechControlsMapperID; the mapper never streams).
|
||||||
|
enum { SubsystemMessageManagerID = 0xBD3 };
|
||||||
|
class SubsystemMessageManager;
|
||||||
|
extern Subsystem *CreateMessageManagerSubsystem(Mech *owner, int id, void *seg);
|
||||||
template<class...A> inline void StreamDamageLookup(A&&...) {}
|
template<class...A> inline void StreamDamageLookup(A&&...) {}
|
||||||
|
|
||||||
|
|
||||||
@@ -988,7 +994,7 @@ Mech::Mech(
|
|||||||
Wword(0x12e) = (int)((Wword(0xba).max - Wword(0xba).min) * UpdatePositionScale);
|
Wword(0x12e) = (int)((Wword(0xba).max - Wword(0xba).min) * UpdatePositionScale);
|
||||||
Wword(0xbb).field8 += (float)Wword(0x12e);
|
Wword(0xbb).field8 += (float)Wword(0x12e);
|
||||||
weaponCount = 0; // Wword(0x112)
|
weaponCount = 0; // Wword(0x112)
|
||||||
controlsMapper = 0; // Wword(0x10d)
|
messageManager = 0; // Wword(0x10d)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Instantiate one Subsystem per segment, dispatching on its streamed
|
// Instantiate one Subsystem per segment, dispatching on its streamed
|
||||||
@@ -1108,10 +1114,14 @@ Mech::Mech(
|
|||||||
++weaponCount;
|
++weaponCount;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MechControlsMapperID: // 0xBD3
|
case SubsystemMessageManagerID: // 0xBD3 -> the REAL class (task #7):
|
||||||
subsystemArray[id] = (Subsystem *)
|
// the per-mech damage/explosion consolidation hub (ctor
|
||||||
new (Memory::Allocate(0x130)) MechControlsMapper(this, id, seg, MechControlsMapper::DefaultData); // FUN_0049bca4
|
// @0049bca4, 0x130 bytes, ConsolidateAndSendDamage Performance
|
||||||
controlsMapper = (MechControlsMapper *)subsystemArray[id]; // Wword(0x10d)
|
// @0049b784). The old MechControlsMapper build here was the
|
||||||
|
// mapper/messmgr conflation -- the mapper never streams; it is
|
||||||
|
// installed into roster slot 0 by SetMappingSubsystem.
|
||||||
|
subsystemArray[id] = CreateMessageManagerSubsystem(this, id, seg); // FUN_0049bca4
|
||||||
|
messageManager = (SubsystemMessageManager *)subsystemArray[id]; // Wword(0x10d)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GaussWeaponClassID: // 0xBD4 -> real Emitter (PPC, mislabeled)
|
case GaussWeaponClassID: // 0xBD4 -> real Emitter (PPC, mislabeled)
|
||||||
@@ -1541,6 +1551,18 @@ Mech::Mech(
|
|||||||
}
|
}
|
||||||
dir->Add(this); // (**(dir[4]+4))(dir+4,this)
|
dir->Add(this); // (**(dir[4]+4))(dir+4,this)
|
||||||
|
|
||||||
|
// SLOT-0 DEMAND LATCH (task #7; see BTBuildMapperDemandLatch): every mech
|
||||||
|
// gets a base mapper in roster slot 0 so the drive harness + replicant
|
||||||
|
// gait have a demand latch; the viewpoint mech's is replaced by the real
|
||||||
|
// device mapper (SetMappingSubsystem).
|
||||||
|
{
|
||||||
|
extern Subsystem *BTBuildMapperDemandLatch(Mech *mech);
|
||||||
|
if (GetSubsystemCount() > 0 && GetSubsystem(0) == 0)
|
||||||
|
{
|
||||||
|
subsystemArray[0] = BTBuildMapperDemandLatch(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// @0049f788 -- distribute coolant flow across the condensers (post-init pass).
|
// @0049f788 -- distribute coolant flow across the condensers (post-init pass).
|
||||||
// The real RecomputeCondenserValves; sets each condenser's coolantFlowScale to
|
// The real RecomputeCondenserValves; sets each condenser's coolantFlowScale to
|
||||||
// valveState/sum(valveState) so the ValveSetting gauge reads the authentic 1/N
|
// valveState/sum(valveState) so the ValveSetting gauge reads the authentic 1/N
|
||||||
@@ -1877,12 +1899,12 @@ void
|
|||||||
Mech::WriteUpdateRecord(Simulation::UpdateRecord *message, int record_type)
|
Mech::WriteUpdateRecord(Simulation::UpdateRecord *message, int record_type)
|
||||||
{
|
{
|
||||||
// The binary stamps *(subsystemArray[0] + 0x128) = the controls mapper's
|
// The binary stamps *(subsystemArray[0] + 0x128) = the controls mapper's
|
||||||
// speedDemand into every record tail. Our live mapper handle is
|
// speedDemand into every record tail -- roster slot 0, the mapper's one
|
||||||
// controlsMapper (the [0x10d] cache); replicants have no pilot input.
|
// true home (task #7 untangle; the old [0x10d] cache is the message
|
||||||
// (Bridge fn: this TU carries a local recon stub under the mapper's name,
|
// manager). (Bridge fn: this TU carries a local recon stub under the
|
||||||
// so the bridge is type-erased; mechmppr.cpp casts to the real class.)
|
// mapper's name, so the bridge is type-erased.)
|
||||||
extern Scalar BTMapperSpeedDemandRaw(void *mapper);
|
extern Scalar BTMapperSpeedDemandRaw(void *mapper);
|
||||||
Scalar speedDemand = BTMapperSpeedDemandRaw((void *)controlsMapper);
|
Scalar speedDemand = BTMapperSpeedDemandRaw((void *)MappingMapper());
|
||||||
|
|
||||||
static const int s_mrecLog = getenv("BT_REPL_LOG") ? 1 : 0;
|
static const int s_mrecLog = getenv("BT_REPL_LOG") ? 1 : 0;
|
||||||
if (s_mrecLog && record_type != 0)
|
if (s_mrecLog && record_type != 0)
|
||||||
|
|||||||
@@ -529,6 +529,15 @@ struct ShotDescriptor
|
|||||||
// Gyro accessor (task #56): the firing-recoil kick (projweap.cpp,
|
// Gyro accessor (task #56): the firing-recoil kick (projweap.cpp,
|
||||||
// binary @4bc194) reads mech+0x528.
|
// binary @4bc194) reads mech+0x528.
|
||||||
Subsystem *GetGyroSubsystem() { return gyroSubsystem; }
|
Subsystem *GetGyroSubsystem() { return gyroSubsystem; }
|
||||||
|
// The mapper's ONE true home (task #7): roster slot 0 -- the binary's
|
||||||
|
// SetMappingSubsystem @0049fe40 installs there, and every binary
|
||||||
|
// mapper consumer reads **(mech+0x128). Null-safe: the binary never
|
||||||
|
// ran these paths mapper-less; our reachability is wider.
|
||||||
|
MechControlsMapper *MappingMapper()
|
||||||
|
{
|
||||||
|
return (GetSubsystemCount() > 0)
|
||||||
|
? (MechControlsMapper *)GetSubsystem(0) : 0;
|
||||||
|
}
|
||||||
Subsystem *GetHudSubsystem() { return hudSubsystem; }
|
Subsystem *GetHudSubsystem() { return hudSubsystem; }
|
||||||
// Reachable horizontal firing half-arc (radians) the mech's torso can bring
|
// Reachable horizontal firing half-arc (radians) the mech's torso can bring
|
||||||
// its guns to bear -- the wider torso twist limit, or 0 for a fixed torso.
|
// its guns to bear -- the wider torso twist limit, or 0 for a fixed torso.
|
||||||
@@ -543,7 +552,15 @@ struct ShotDescriptor
|
|||||||
// controls mapper (@004afd10 writes cockpit+0x28c -- past MechTech's alloc,
|
// controls mapper (@004afd10 writes cockpit+0x28c -- past MechTech's alloc,
|
||||||
// inside the HUD's). Was misnamed mechTechSubsystem.
|
// inside the HUD's). Was misnamed mechTechSubsystem.
|
||||||
Subsystem *hudSubsystem; // @0x5b4 this[0x16d] (0xBD6 -> real HUD)
|
Subsystem *hudSubsystem; // @0x5b4 this[0x16d] (0xBD6 -> real HUD)
|
||||||
MechControlsMapper *controlsMapper; // @0x434 this[0x10d] (0xBD3)
|
// THE UNTANGLE (task #7): binary [0x10d]/mech+0x434 caches the
|
||||||
|
// SubsystemMessageManager (0xBD3, the per-mech damage/explosion
|
||||||
|
// consolidation hub, ctor @0049bca4) -- NOT a controls mapper. The
|
||||||
|
// binary-wide census found exactly ONE reader (@0x4b984b in
|
||||||
|
// MechWeapon::SendDamageMessage @004b9728) and it is pure
|
||||||
|
// message-manager semantics. The old `controlsMapper` name/type was
|
||||||
|
// the misread that made the whole drive lean on this cache. The
|
||||||
|
// REAL mapper's one true home is roster slot 0 (MappingMapper()).
|
||||||
|
class SubsystemMessageManager *messageManager; // @0x434 this[0x10d] (0xBD3)
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Pose / kinematics (subset touched by the recovered slice)
|
// Pose / kinematics (subset touched by the recovered slice)
|
||||||
|
|||||||
@@ -422,9 +422,10 @@ Scalar
|
|||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
// The binary reads edx = *(mech+0x128) then [edx]+0x128: subsystemArray[0]
|
// The binary reads edx = *(mech+0x128) then [edx]+0x128: subsystemArray[0]
|
||||||
// (the roster's ControlsMapper slot) -> speedDemand. controlsMapper is the
|
// (the roster's ControlsMapper slot 0) -> speedDemand; null (no mapper)
|
||||||
// typed mirror of that slot; null (no mapper) reads demand 0 -> the mech idles.
|
// reads demand 0 -> the mech idles. (task #7: read the REAL slot-0 mapper.)
|
||||||
const Scalar spd = (m->controlsMapper != 0) ? m->controlsMapper->speedDemand : 0.0f;
|
MechControlsMapper *mppr2 = m->MappingMapper();
|
||||||
|
const Scalar spd = (mppr2 != 0) ? mppr2->speedDemand : 0.0f;
|
||||||
const Scalar fcr = m->forwardCycleRate; // 0x344
|
const Scalar fcr = m->forwardCycleRate; // 0x344
|
||||||
const Scalar gts = m->globalTimeScale; // 0x5a8
|
const Scalar gts = m->globalTimeScale; // 0x5a8
|
||||||
const Scalar cyc = m->legCycleSpeed; // 0x348
|
const Scalar cyc = m->legCycleSpeed; // 0x348
|
||||||
@@ -528,8 +529,9 @@ Scalar
|
|||||||
// RECONCILED: the old draft double-deref'd the never-initialized controlSource
|
// RECONCILED: the old draft double-deref'd the never-initialized controlSource
|
||||||
// alias (an AV); controlsMapper is the typed mirror of roster slot 0. A mech
|
// alias (an AV); controlsMapper is the typed mirror of roster slot 0. A mech
|
||||||
// with no mapper reads demand 0 (idles) -- matching a zeroed binary roster.
|
// with no mapper reads demand 0 (idles) -- matching a zeroed binary roster.
|
||||||
|
MechControlsMapper *mppr = MappingMapper(); // roster slot 0 (task #7)
|
||||||
Scalar commandedSpeed =
|
Scalar commandedSpeed =
|
||||||
(controlsMapper != 0) ? controlsMapper->speedDemand : 0.0f;
|
(mppr != 0) ? mppr->speedDemand : 0.0f;
|
||||||
Scalar distance = 0.0f;
|
Scalar distance = 0.0f;
|
||||||
|
|
||||||
// binary: legAnimationState@0x3b0 IS legStateAlarm's level (one field; the
|
// binary: legAnimationState@0x3b0 IS legStateAlarm's level (one field; the
|
||||||
@@ -585,10 +587,10 @@ Scalar
|
|||||||
// Standing on a live turn demand with no speed demand. The clip's
|
// Standing on a live turn demand with no speed demand. The clip's
|
||||||
// finished-callback drops back to stand; while the demand persists
|
// finished-callback drops back to stand; while the demand persists
|
||||||
// this trigger re-arms it (a looping pivot step).
|
// this trigger re-arms it (a looping pivot step).
|
||||||
if (hasCrashSet != 0 && controlsMapper != 0
|
if (hasCrashSet != 0 && mppr != 0
|
||||||
&& ZeroSpeed <= commandedSpeed
|
&& ZeroSpeed <= commandedSpeed
|
||||||
&& (controlsMapper->turnDemand > 0.05f
|
&& (mppr->turnDemand > 0.05f
|
||||||
|| controlsMapper->turnDemand < -0.05f))
|
|| mppr->turnDemand < -0.05f))
|
||||||
{
|
{
|
||||||
SetLegAnimation(4); // turn-in-place (trn)
|
SetLegAnimation(4); // turn-in-place (trn)
|
||||||
goto advance_normally;
|
goto advance_normally;
|
||||||
|
|||||||
@@ -1376,7 +1376,8 @@ void
|
|||||||
// cadence matches the replicated speed (residual foot-slip is the
|
// cadence matches the replicated speed (residual foot-slip is the
|
||||||
// inherent dead-reckoning artifact). The state machine self-arms
|
// inherent dead-reckoning artifact). The state machine self-arms
|
||||||
// stand->walk / winds down from the demand exactly as on the master.
|
// stand->walk / winds down from the demand exactly as on the master.
|
||||||
if (!IsMechDestroyed() && controlsMapper != 0)
|
MechControlsMapper *replMppr = MappingMapper(); // roster slot 0 (task #7)
|
||||||
|
if (!IsMechDestroyed() && replMppr != 0)
|
||||||
{
|
{
|
||||||
const Vector3D &wv = updateVelocity.linearMotion;
|
const Vector3D &wv = updateVelocity.linearMotion;
|
||||||
float spd = sqrtf((float)(wv.x * wv.x + wv.z * wv.z));
|
float spd = sqrtf((float)(wv.x * wv.x + wv.z * wv.z));
|
||||||
@@ -1384,7 +1385,7 @@ void
|
|||||||
localToWorld.GetFromAxis(Z_Axis, &zAxR);
|
localToWorld.GetFromAxis(Z_Axis, &zAxR);
|
||||||
const float fdot = -((float)wv.x * (float)zAxR.x
|
const float fdot = -((float)wv.x * (float)zAxR.x
|
||||||
+ (float)wv.z * (float)zAxR.z); // mech faces -Z
|
+ (float)wv.z * (float)zAxR.z); // mech faces -Z
|
||||||
controlsMapper->speedDemand = (fdot < 0.0f) ? -spd : spd;
|
replMppr->speedDemand = (fdot < 0.0f) ? -spd : spd;
|
||||||
// Prime the same clip-advance scalars the master's gait block sets
|
// Prime the same clip-advance scalars the master's gait block sets
|
||||||
// each frame -- uninitialized on a replicant they read 0, freezing
|
// each frame -- uninitialized on a replicant they read 0, freezing
|
||||||
// the clip at advance-time dt*0 (observed: legState engaged at 11,
|
// the clip at advance-time dt*0 (observed: legState engaged at 11,
|
||||||
@@ -1843,22 +1844,23 @@ void
|
|||||||
// mode clamps, torso axes, HUD free-aim) is the real reconstructed tick,
|
// mode clamps, torso axes, HUD free-aim) is the real reconstructed tick,
|
||||||
// which runs in the subsystem-roster walk below (un-skipped under this env).
|
// which runs in the subsystem-roster walk below (un-skipped under this env).
|
||||||
static const int s_realControls = BTEnvOn("BT_REAL_CONTROLS", 1); // default ON (=0 to disable)
|
static const int s_realControls = BTEnvOn("BT_REAL_CONTROLS", 1); // default ON (=0 to disable)
|
||||||
if (s_realControls && controlsMapper != 0)
|
MechControlsMapper *mppr = MappingMapper(); // roster slot 0 (task #7)
|
||||||
|
if (s_realControls && mppr != 0)
|
||||||
{
|
{
|
||||||
// Diagnostic: what the ENGINE controls push left in the attribute since
|
// Diagnostic: what the ENGINE controls push left in the attribute since
|
||||||
// our last write (a stale device element overwriting the bridge shows
|
// our last write (a stale device element overwriting the bridge shows
|
||||||
// here as pre != our previous write).
|
// here as pre != our previous write).
|
||||||
float preThrottle = controlsMapper->throttlePosition;
|
float preThrottle = mppr->throttlePosition;
|
||||||
(void)preThrottle;
|
(void)preThrottle;
|
||||||
controlsMapper->throttlePosition = (throttle >= 0.0f) ? throttle : -throttle;
|
mppr->throttlePosition = (throttle >= 0.0f) ? throttle : -throttle;
|
||||||
controlsMapper->reverseThrust = (throttle < 0.0f) ? 1 : 0; // ControlsButton: >=1 engaged
|
mppr->reverseThrust = (throttle < 0.0f) ? 1 : 0; // ControlsButton: >=1 engaged
|
||||||
controlsMapper->stickPosition.x = turn; // Basic mode: turn = stick yaw
|
mppr->stickPosition.x = turn; // Basic mode: turn = stick yaw
|
||||||
controlsMapper->stickPosition.y = 0.0f;
|
mppr->stickPosition.y = 0.0f;
|
||||||
// Consume the PREVIOUS frame's interpreted demands (the mapper ticks in
|
// Consume the PREVIOUS frame's interpreted demands (the mapper ticks in
|
||||||
// the roster walk after this block -- one frame of input latency).
|
// the roster walk after this block -- one frame of input latency).
|
||||||
// turnDemand is the mode-shaped steering; speedDemand (world u/s, sign =
|
// turnDemand is the mode-shaped steering; speedDemand (world u/s, sign =
|
||||||
// reverse) feeds the gait target below.
|
// reverse) feeds the gait target below.
|
||||||
turn = controlsMapper->turnDemand;
|
turn = mppr->turnDemand;
|
||||||
// BT_GOTO steering must reach the orientation integration DIRECTLY: the
|
// BT_GOTO steering must reach the orientation integration DIRECTLY: the
|
||||||
// mapper round-trip (stickPosition -> turnDemand) zeroes out in -net mode
|
// mapper round-trip (stickPosition -> turnDemand) zeroes out in -net mode
|
||||||
// (the key-bridge only shapes the local viewpoint mech there), which froze
|
// (the key-bridge only shapes the local viewpoint mech there), which froze
|
||||||
@@ -1871,15 +1873,15 @@ void
|
|||||||
if (s_mpprLog >= 1.0f)
|
if (s_mpprLog >= 1.0f)
|
||||||
{
|
{
|
||||||
s_mpprLog = 0.0f;
|
s_mpprLog = 0.0f;
|
||||||
DEBUG_STREAM << "[mppr] in thr=" << controlsMapper->throttlePosition
|
DEBUG_STREAM << "[mppr] in thr=" << mppr->throttlePosition
|
||||||
<< " pre=" << preThrottle
|
<< " pre=" << preThrottle
|
||||||
<< " rev=" << controlsMapper->reverseThrust
|
<< " rev=" << mppr->reverseThrust
|
||||||
<< " stickX=" << controlsMapper->stickPosition.x
|
<< " stickX=" << mppr->stickPosition.x
|
||||||
<< " -> speedDemand=" << controlsMapper->speedDemand
|
<< " -> speedDemand=" << mppr->speedDemand
|
||||||
<< " turnDemand=" << controlsMapper->turnDemand
|
<< " turnDemand=" << mppr->turnDemand
|
||||||
<< " mode=" << controlsMapper->controlMode
|
<< " mode=" << mppr->controlMode
|
||||||
<< " mapper=" << (void*)controlsMapper
|
<< " mapper=" << (void*)mppr
|
||||||
<< " &mode=" << (void*)&controlsMapper->controlMode << "\n" << std::flush;
|
<< " &mode=" << (void*)&mppr->controlMode << "\n" << std::flush;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2018,8 +2020,8 @@ void
|
|||||||
// while the animation transitioned gradually (the "physics don't
|
// while the animation transitioned gradually (the "physics don't
|
||||||
// line up with the animation" desync). Signed, the SM decelerates
|
// line up with the animation" desync). Signed, the SM decelerates
|
||||||
// through stop -> reverse-entry exactly like the leg channel.
|
// through stop -> reverse-entry exactly like the leg channel.
|
||||||
if (s_realControls && controlsMapper != 0)
|
if (s_realControls && MappingMapper() != 0)
|
||||||
bodyTargetSpeed = controlsMapper->speedDemand;
|
bodyTargetSpeed = MappingMapper()->speedDemand;
|
||||||
else
|
else
|
||||||
bodyTargetSpeed = ((throttle < 0.0f) ? -1.0f : 1.0f)
|
bodyTargetSpeed = ((throttle < 0.0f) ? -1.0f : 1.0f)
|
||||||
* (wantGait ? reverseSpeedMax : walkStrideLength);
|
* (wantGait ? reverseSpeedMax : walkStrideLength);
|
||||||
@@ -2593,8 +2595,8 @@ void
|
|||||||
// Commanded-speed deadband (binary @0x4aac88): the mapper's live
|
// Commanded-speed deadband (binary @0x4aac88): the mapper's live
|
||||||
// speedDemand vs the last-replicated bodyTargetSpeed -> the tiny
|
// speedDemand vs the last-replicated bodyTargetSpeed -> the tiny
|
||||||
// type-2 record. This is the AUTHENTIC replicant-gait feed.
|
// type-2 record. This is the AUTHENTIC replicant-gait feed.
|
||||||
if (controlsMapper != 0
|
if (MappingMapper() != 0
|
||||||
&& controlsMapper->speedDemand != bodyTargetSpeed)
|
&& MappingMapper()->speedDemand != bodyTargetSpeed)
|
||||||
{
|
{
|
||||||
ForceUpdate(1 << MechSpeedUpdateModelBit); // type 2
|
ForceUpdate(1 << MechSpeedUpdateModelBit); // type 2
|
||||||
}
|
}
|
||||||
@@ -3229,13 +3231,13 @@ void
|
|||||||
Subsystem *subsystem = subsystemArray[i];
|
Subsystem *subsystem = subsystemArray[i];
|
||||||
if (subsystem == 0)
|
if (subsystem == 0)
|
||||||
continue;
|
continue;
|
||||||
if (subsystem != (Subsystem *)controlsMapper)
|
if (i != 0) // slot 0 = the mapper (task #7)
|
||||||
++subsystemsPresent;
|
++subsystemsPresent;
|
||||||
if (!subsystem->IsNonReplicantExecutable())
|
if (!subsystem->IsNonReplicantExecutable())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// The controls-mapping subsystem (roster slot 0 via Mech::SetMapping
|
// The controls-mapping subsystem (roster slot 0 via Mech::SetMapping
|
||||||
// Subsystem, mirrored to controlsMapper) is TICKED under BT_REAL_CONTROLS
|
// Subsystem -- the [0x10d] mirror is GONE, task #7) is TICKED under BT_REAL_CONTROLS
|
||||||
// -- its InterpretControls chain is now reconciled: FillPilotArray reads
|
// -- its InterpretControls chain is now reconciled: FillPilotArray reads
|
||||||
// the local player via application->GetMissionPlayer() (the old wild
|
// the local player via application->GetMissionPlayer() (the old wild
|
||||||
// application+0x6c read was THE bypass-causing AV), and the main tick
|
// application+0x6c read was THE bypass-causing AV), and the main tick
|
||||||
@@ -3245,7 +3247,7 @@ void
|
|||||||
// stands (default behavior unchanged).
|
// stands (default behavior unchanged).
|
||||||
{
|
{
|
||||||
static const int s_realControlsTick = BTEnvOn("BT_REAL_CONTROLS", 1);
|
static const int s_realControlsTick = BTEnvOn("BT_REAL_CONTROLS", 1);
|
||||||
if (!s_realControlsTick && subsystem == (Subsystem *)controlsMapper)
|
if (!s_realControlsTick && i == 0) // slot 0 = the mapper (task #7)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1242,6 +1242,31 @@ void *BTResolveRosterPilot(int slot)
|
|||||||
// sees only the forward declaration of MechControlsMapper, so the read
|
// sees only the forward declaration of MechControlsMapper, so the read
|
||||||
// lives here in the complete-type TU (the house databinding pattern).
|
// lives here in the complete-type TU (the house databinding pattern).
|
||||||
//
|
//
|
||||||
|
//###########################################################################
|
||||||
|
// BTBuildMapperDemandLatch -- slot-0 latch (task #7)
|
||||||
|
//
|
||||||
|
// The binary leaves roster slot 0 NULL except on the viewpoint mech
|
||||||
|
// (MakeViewpointEntity installs the real device mapper via
|
||||||
|
// SetMappingSubsystem @0049fe40). Our port drives NON-viewpoint masters
|
||||||
|
// (the BT_GOTO/BT_AUTODRIVE harness) and animates replicant gait through
|
||||||
|
// mapper demand fields, so every mech gets a default-data BASE mapper as a
|
||||||
|
// demand LATCH at ctor end; SetMappingSubsystem deletes + replaces it on
|
||||||
|
// the viewpoint mech exactly as the binary replaces slot 0. [T3
|
||||||
|
// accommodation -- relocates the retired 0xBD3 squatter's role to the slot
|
||||||
|
// the binary actually reads.] Complete-type TU (the mech.cpp caller
|
||||||
|
// carries a local stub under the mapper's name).
|
||||||
|
//
|
||||||
|
Subsystem *BTBuildMapperDemandLatch(Mech *mech)
|
||||||
|
{
|
||||||
|
static MechControlsMapper::SubsystemResource latch_resource;
|
||||||
|
Str_Copy(latch_resource.subsystemName, "ControlsMapper",
|
||||||
|
sizeof(latch_resource.subsystemName));
|
||||||
|
latch_resource.classID = (RegisteredClass::ClassID)0xf; // TrivialSubsystemClassID (btl4app idiom)
|
||||||
|
latch_resource.subsystemModelSize = sizeof(latch_resource);
|
||||||
|
return new MechControlsMapper(mech, 0, &latch_resource,
|
||||||
|
MechControlsMapper::DefaultData);
|
||||||
|
}
|
||||||
|
|
||||||
Scalar BTMapperSpeedDemandRaw(void *mapper)
|
Scalar BTMapperSpeedDemandRaw(void *mapper)
|
||||||
{
|
{
|
||||||
// void* signature: mech.cpp's TU carries a local recon stub type under the
|
// void* signature: mech.cpp's TU carries a local recon stub type under the
|
||||||
|
|||||||
@@ -486,3 +486,17 @@ void
|
|||||||
// resources beyond the base.
|
// resources beyond the base.
|
||||||
//
|
//
|
||||||
// SubsystemMessageManager::DamageInformation::~DamageInformation() {} // @0049c3e3
|
// SubsystemMessageManager::DamageInformation::~DamageInformation() {} // @0049c3e3
|
||||||
|
|
||||||
|
//###########################################################################
|
||||||
|
// CreateMessageManagerSubsystem -- factory bridge (task #7)
|
||||||
|
//
|
||||||
|
// mech.cpp's streamed-subsystem factory (case 0xBD3) calls this in the
|
||||||
|
// house complete-type-TU pattern (cf. CreateEmitterSubsystem et al).
|
||||||
|
//
|
||||||
|
Subsystem *CreateMessageManagerSubsystem(Mech *owner, int id, void *seg)
|
||||||
|
{
|
||||||
|
return new (Memory::Allocate(0x130)) SubsystemMessageManager(
|
||||||
|
owner, id,
|
||||||
|
(SubsystemMessageManager::SubsystemResource *)seg,
|
||||||
|
SubsystemMessageManager::DefaultData);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user