MP: the Mech-level update records @0x4a0c2c/@0x4a1232 -- all 9 types byte-exact (task #1)

- Writer transcribed from the recovered disasm; reader rewritten from
  part_012.c with every Wword absorber promoted to named engine/port members
  (updateOrigin/updateVelocity/projectedOrigin/projectedVelocity/nextUpdate/
  lastUpdate + bodyTargetSpeed/latches/alarms).  Wire sizes verified live:
  0x14/0x20/0x2c/0x78.
- movementMode UNIFIED with Simulation::simulationState (binary mech+0x40 =
  StateIndicator@0x2c currentState) -- death/limbo/airborne now replicate in
  every record header.  Three mislabels of the same binary fns retired:
  SetInstanceFlags + RequestActionFlags -> Mech::ForceUpdate (updateModel |=
  mask, 0xfe03 disabled filter); IsNetworkCopy -> IsDisabled.
- Senders wired byte-exact: gait transitions Force(8), knockdown Force(1|0x20),
  death Force(1|0x40), Reset Force(0x1f) + binary zero-set, perf-loop
  deadbands (speed type 2, orientation type 4, heat type 7).
- 2-node verified: types 2/3/4 flow while driving; kill -> type-6 record
  (simState=9) -> the OBSERVER's replicant runs the wreck sink loop with no
  double death transition; respawn 0x1f burst snaps + un-wrecks the peer;
  walking replicant un-regressed (run 12, cycle tracking); solo clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-11 11:38:49 -05:00
co-authored by Claude Fable 5
parent 3c34ae6de6
commit c9f0c2a7f1
6 changed files with 641 additions and 185 deletions
+15 -22
View File
@@ -242,18 +242,11 @@ void
}
//
// @004a4c54 -- OR action-request bits into actionRequestFlags. A disabled
// mech may only request a restricted subset (mask 0xFE03).
//
void
Mech::RequestActionFlags(Word bits)
{
if (IsDisabled()) // FUN_0049fb54(this)
{
bits &= 0xFE03;
}
actionRequestFlags |= bits; // this+0x18
}
// (@004a4c54 lives inline in mech.hpp as Mech::ForceUpdate -- the "action
// request bits" ARE the updateModel record-request mask; the old
// RequestActionFlags name wrote a dead side-member the update emitter never
// read. The call sites below keep their binary-exact masks: 8 = 1<<3 the
// leg-state/stability record.)
//###########################################################################
@@ -285,7 +278,7 @@ Scalar
{
// airborne branch (movementMode 3/4 && jumpCapable) -> FUN_004a6344 (deferred; safe
// no-op while grounded -- the test mech never jumps).
if ((m->movementMode == 3 || m->movementMode == 4) && m->jumpCapable)
if ((m->MovementMode() == 3 || m->MovementMode() == 4) && m->jumpCapable)
return 0.0f;
const Scalar fcr = m->forwardCycleRate; // 0x344
@@ -425,7 +418,7 @@ Scalar
Mech::LegClipFinished(Mech *m, unsigned /*a2*/, Scalar carryover, int mj)
{
// airborne branch (movementMode 3/4 && jumpCapable) -> FUN_004a7970 (deferred).
if ((m->movementMode == 3 || m->movementMode == 4) && m->jumpCapable)
if ((m->MovementMode() == 3 || m->MovementMode() == 4) && m->jumpCapable)
return 0.0f;
// The binary reads edx = *(mech+0x128) then [edx]+0x128: subsystemArray[0]
@@ -549,7 +542,7 @@ Scalar
//
if (!deathAnimationLatched)
{
switch (movementMode) // this+0x40
switch (MovementMode()) // this+0x40 = simulationState
{
case 5: SetLegAnimation(0x1c); deathAnimationLatched = 1; break;
case 6: SetLegAnimation(0x1d); deathAnimationLatched = 1; break;
@@ -642,14 +635,14 @@ Scalar
if (standSpeed < commandedSpeed)
{
legStateAlarm.SetLevel(0);
RequestActionFlags(8); // FUN_004a4c54(this,8)
ForceUpdate(8); // FUN_004a4c54(this,8): type-3 record
break;
}
distance = 0.0f;
if (commandedSpeed < ZeroSpeed)
{
legStateAlarm.SetLevel(0);
RequestActionFlags(8);
ForceUpdate(8); // type-3 record
break;
}
goto advance_normally;
@@ -816,7 +809,7 @@ Scalar
if (!deathAnimationLatched) // this+0x650
{
switch (movementMode) // this+0x40
switch (MovementMode()) // this+0x40 = simulationState
{
case 5: SetBodyAnimation(0x1c); deathAnimationLatched = 1; break;
case 6: SetBodyAnimation(0x1d); deathAnimationLatched = 1; break;
@@ -969,7 +962,7 @@ Scalar
if ((unsigned)(state - 6) < 2 || (unsigned)(state - 0x0c) < 2
|| (unsigned)(state - 0x12) < 2)
{
if (movementMode == 3) // run jump
if (MovementMode() == 3) // run jump
{
if (bodyTargetSpeed > jumpRunSpeedMax) bodyTargetSpeed = jumpRunSpeedMax; // 0x53c
}
@@ -1071,7 +1064,7 @@ Scalar
case 0x18: case 0x19: // FallForward / FallBackward (jump)
{
Scalar ratio;
if (movementMode == 3) // run jump: caps 0x53c / 0x544
if (MovementMode() == 3) // run jump: caps 0x53c / 0x544
{
if (bodyTargetSpeed <= bodyCycleSpeed)
{
@@ -1144,7 +1137,7 @@ Scalar
{
ReconMotionSource *motionSource = *(ReconMotionSource **)(this->controlSource); // **(this+0x128)
Scalar distance = 0.0f;
int mode = movementMode; // this+0x40
int mode = MovementMode(); // this+0x40 = simulationState
int state = legAnimationState; // this+0x3b0
//
@@ -1196,7 +1189,7 @@ Scalar
if (standSpeed < motionSource->commandedSpeed)
{
legStateAlarm.SetLevel(0);
RequestActionFlags(8);
ForceUpdate(8); // type-3 record
break;
}
goto advance_normally;