# MECH4 — pre-TU reconstruction notes **Status: no MECH4.CPP exists yet.** The ground snap, frame rejection, knockdown stagger and collision economy that the binary keeps in mech4's master performance are currently RE-HOSTED inside `Mech::Simulate` ([[MECH]], 5.3.98–100) at seams marked STAGED. This file carries the decode work for the pieces not yet written, so it survives session boundaries. ## Mech::ProcessCollision (@004abb40) — decoded, not yet reconstructed The override of the engine's protected virtual (`MOVER.CPP:1354`), called per contact by `Mover::ProcessCollisionList`. The decomp (part_012.c:15206–15416) reads as the BASE function plus four additions: 1. **The base head, verbatim**: `collisionVolume->ProcessCollision(collision, worldLinearVelocity, lastCollisionList, &damage->surfaceNormal, &penetration)`; on a miss NOTHING runs. Clamp penetration to the slice, ratio = pen/dt, `damage->damageAmount = StaticBounce(old, dt, r, normal, &elasticity, minimumBounceSpeed, &friction)` with the elasticity/friction locals seeded from the mover's coefficients. 2. **The Mover-family branch** (owner = the collided solid's owner entity, solid+0x1c; family test FUN_0041a1a4 against the "Mover" derivation GUID @0x4e4518): * SEPARATING-CONTACT GATE: `(ourWorldVel − other->WorldVel[vtbl+0x20]) · normal < −1e-4` (`_DAT_004ac044`) → return, no damage, no dispatch. * If the other's classID == **0xbb9** (mech), build a TakeDamage message (raw wire shape `{id, len, inflictor = DAT_0050b9ac global, zone −1, the Damage verbatim}`) and Dispatch it AT THE OTHER — the mech-vs-mech ram. Use our `Entity::TakeDamageMessage` ctor as the weapon path does. 3. **The CulturalIcon branch** (GUID @0x4e7038): * `stopping = other->instanceFlags & 0x8000` (the StoppingCollisionVolume flag, entity+0x28). * Same separating gate against a ZERO other-velocity (icons are static). * Dispatch the crunch TakeDamage at the icon (crushable props have no zones → their base handler no-ops it, but the dispatch is real). * If NOT stopping: `damage->damageAmount = 0.00123f` (bits 0x3aa137f4) — the WALK-THROUGH SENTINEL. The caller (the response block in Simulate) must treat exactly 0.00123f as "the move stands": restore the post-snap saves, zero the amount, feed the gyro crunch (torque 0.4 along the normalized force, upward impulse 0.2 — binary @4aa81e/@4aa86c). 4. **The material tail**: the elasticity/friction OUT values from StaticBounce are compared against `_DAT_004ac048`; sets `collisionTemporaryState` (+0x44c) to 1, or 2 when both match and the state was 0. The state is pushed into the `collisionState` StateIndicator once per frame by the response block (0→1 fires the impact sound). Needs the `_DAT_004ac048` constant identified before writing (likely the default-material coefficient — check the literal pool at 0x4ac048). ## Two hazards the donor fought that DO NOT apply here * **Compounded StaticBounce reflections**: our engine's `Mover::ProcessCollisionList` (MOVER.CPP:1203) restores `worldLinearVelocity = initial_velocity` and position PER CONTACT before each ProcessCollision call, and averages the results. The port's `frameEntryWorldVelocity` economy guard has no counterpart hazard in this engine — do not import it. * **The AlarmIndicator ODR split**: a port-only problem; our tree reads `MovementMode()` / the alarms directly. ## Already re-hosted in Mech::Simulate (move here when mech4.cpp exists) | piece | binary | landed | |---|---|---| | ground probe + snap | @4aa630–4aa6cc | 5.3.98 | | frame rejection + crash self-damage + knockdown | @4aa6cf–4aab0b | 5.3.99 | | collision economy divert + distributor | @0x4a0368 → @0049ffcc | 5.3.100 (in the damage hub, where the binary has it) | | status→mode limp promotion | master perf (un-decompiled) | 5.3.97, STAGED | | forwardCycleRate re-pick (ground/airborne) | IntegrateMotion head | partially — the ctor sets it once; the per-frame re-pick needs +0x3f4 | ## Still to decode * `FUN_004a9b5c` — the master performance. **ISOLATED AND MAPPED (2026-08-04):** one single 5,676-byte body @004a9b5c..@004ab168 (one `ret`), hidden inside the manifest's mis-sized @004a9770 entry (that fn is really the stream-builder's 6.6KB name→SharedData strcmp resolver, and Ghidra swallowed everything to @004ab188 behind it). Registration proven from the ctor decomp: `(flags & 0xC) == 4` → replicant perf, else master @004a9b5c. Recipe: extract CODE bytes (va 0x1000 → file 0xe00), `ndisasm -b 32 -o 0x4a9b5c`. **5.3.121 corrections: the DECOMP has both perfs in plain C (master = part_013.c:3059, and @004ab430 IS the complete replicant perf — my "@004ab9d8 hidden inside it" note was its CONSTANT POOL @004ab9c8.. right after the body). Replicant perf read (not yet landed): zero +0x1dc, IntegrateMotion(dt, flavor 1); ret 1 (fresher update present) → quaternion slerp +0x10c toward the update target +0x26c with t = dt/(update age + dt) + matching velocity lerps (+0x1d0 vs +0x2a4, +0x1f4 vs +0x298); either path applies the +0x598 error-offset vector smoothed over the @004ab9cc window while the +0x5a4 latch holds, then position ← the DR anchor +0x260; without flags&0x4000 it re-resolves its room via the world chain (@0040e36c on the +0x2e8 box) → +0x2f0; same ground clamp; `FUN_00421b6c`; same five ring publishes + acceleration tail; NO update-record writer.** **The ordered call skeleton (111 calls)** — blocks in execution order, matching our Simulate's structure and locating every staged gap: 1. controls/demand intake (mech.cpp helpers 0x4a4eab/0x4a4ee9/0x4a4f9e) 2. three cerr+SetLevel triplets — illegal-state alarm guards 3. **THE DUCK DRIVER** — DECODED + LANDED 5.3.120, live-verified (BT_FORCE_DUCK cycles down/hold/up continuously on the rig). The full system: DuckRequest message 0x1A (authentic name from the binary's handler table; roster = RealMaxSpeed 0x15, BalanceCoolant 0x16, SetBurningState 0x17, ClearBurningState 0x18, EjectPilot 0x19, DuckRequest 0x1A) latches one evaluation (+0x398, one-shot, Reset clears); the phase machine reads the RAW simulation state, the mapper's duck cell (+0x25c) and the analog demand (+0x79c, deadzone 1e-4 @0x4ab16c): gait 0/4 + input -> down (LEG slot 2, sqd), gait 1 -> up (slot 3, squ); limp modes 3/4 force stand-up; the collisionVolumeState alarm (+0x4c4; 1=standing, 0=ducked; "Whoa! Bad Collision Volume State!" guard, line 417) swaps the collision template's maxY (ExtentBox +0xc == the box TOP; the ground probe's minY untouched) between the ctor-captured height and 0.6x it (the double @004a2d38); duckState publishes for the cockpit selector. Still open here: the two MarkUpdate masks (8 then 1) ride our ForceUpdate no-op, and the mapper duck cell's streamed binding id awaits a BT_MAP_LOG audit on a duck-bound RES. 4. verify-guarded state read (mech4 accessors + Fail 0x40385c) 5. gyro feed a (vec pair → gyro_b 0x4b2de4, gyro_a 0x4b2d8c) 6. death GUARD on the advance dispatch: InDeathTransition 0x49fb54; 0x4a71f4 = AdvanceLegAnimationGimp (modes 3/4 + 0x580), 0x4a5028 = AdvanceLegAnimation -- NOT a death advancer (5.3.121 correction) 7. ~~status→mode LIMP PROMOTION~~ -> the STREAMED MODE-REQUEST COUNTERS (see the 5.3.121 section; landed) 8. update-record block (0x421bac/0x40e5f0/0x4227e0/0x41db7c/0x422bac + Point3D copies) — the dead-reckon/update writer 9. collision → gyro crunch (gyro feeds + alarms) 10. knockdown/bump arms (EntityID pair + two SetAnim/Mark/SetLevel arms) 11. IntegrateMotion @004ab1c8 + position dirty marks 12. pose/joint tail: gyro_d/gyro_c → **Torso::UpdateJoints @004b66b4** → five StateIndicator::SetState publishes + four GetState reads 13. frame close (position latch) **MarkUpdate = FUN_004a4c54 (×20!)** — the update-record dirty-mask OR (death strips motion bits); our `ForceUpdate(int)` is an EMPTY STUB, so none of these marks exist in our tree yet (MP replication feed). Next sitting: instruction-level read of blocks 3 and 7 (the two STAGED items), then the mark masks. * `@004ab430` ReplicantPerformance (1432B) — the replicant-side interior. * `@004ab1c8` IntegrateMotion — decoded (see 5.3.95 notes) but only partially re-hosted: the local-velocity/orientation integration and the dead-reckon latency fold (+0x778/+0x77c) remain. **`+0x598` is a Point3D** (its replicant branch writes it with a vector subtract), so `motionEventName` in MECH.HPP is mistyped as CString — fix when this lands. ## 5.3.121 -- THE DECOMP HAS THE MASTER PERF (ledger correction + full C read) **`part_013.c:3059` = `@004a9b5c file=bt/mech4.cpp` -- the ENTIRE master performance is in the BT411 decomp as plain C.** Every "never decompiled / raw-disasm-only" note above is superseded; the asm read (scratchpad masterperf.asm) and the C agree line for line where both were done. Rule for the rest of this file: read the C first, keep ndisasm for byte-level checks. (`@004ab1c8` IntegrateMotion and `@004ab188` -- its dead-reckon position fold -- are decompiled right below it; the replicant-perf interior sits inside `@004ab430` from part_013:3804 with the SAME five ring publishes at :3948.) ### The movement-mode carrier (the big one) * **mech+0x2c is the entity MOVEMENT-MODE AlarmIndicator; +0x40 is its LEVEL cell.** Everything we had read as "raw simulationState at +0x40" is this alarm's level. It is entity-BASE machinery: the engine seeds it from the class descriptor's state count (`@0041bdf0`, `FUN_0041b9ec(entity+0x2c, *(desc+0xc))`). * Mode roster so far: 0 DefaultState, 2/9 death transition (InDeathTransition `@0049fb54` == 2||9 exactly), 3 GimpLeft, 4 GimpRight, 5-8 the four fall variants (the body machine `@004a5678` head arms body clips 0x1c-0x1f from them, one-shot latched by +0x650), 9 killed. WHO WRITES 2 and 5-8 is still undecoded (the death FSM brick). Mode 1: seen only as "not standing" in duck gates; identity open. * **The damage path writes the mode DIRECTLY**: TakeDamage `@0049c690` calls `FUN_0041bbd8(mech+0x2c, ...)` -- half-gone right leg -> 4 (`@0x49c8fb`), left -> 3 (`@0x49c926`), leg destroyed while already limping -> 9 (`@0x49c88f`/`@0x49c8c5`), vital zone -> 9 (`@0x49c83c`), gated by the REAL `InDeathTransition`. The old model (statusAlarm@0x714 as damage carrier + a Simulate "promotion") was a misconstruction -- RETIRED in 5.3.121; MECHDMG now writes the mode, and the @0x714 alarm is ONLY the body-graphic clip selector (level = body clip index 0..0x20, 0x3c-stride name table at 0x50cfe8 "StandingAnimation"...). * **Block 7 truth**: not a promotion. Three STREAMED request counters -- +0x334 DefaultState / +0x338 GimpLeft / +0x33c GimpRight (authentic names, traced to the debug stream as consumed) -- re-assert the mode alarm every frame they are positive. Writers: the creation-stream ctor `@004b3778` (record +0x1c0/1c4/1c8) and the update-record appliers; zeroed by ctor `@004a1674` and Reset `@0049fb74` (which also drops the mode alarm to 0 and zeroes +0x328/+0x32c/+0x330 -- those three cells still unidentified). LANDED with the authentic traces; inert until the MP stream feed exists. ### Corrected field identities (from the C) * **+0x79c = the MOBILITY SCALE**, not a duck analog: zeroed each frame, then MAX of item+0x31c over the +0x7ac leg roster (count via the iterator); throttle command (mapper+0x128) *= it; |scale| <= 1e-4 also ZEROES the turn command (mapper+0x12c). The duck-down pick reads it as the "legs still work" gate. Our tree HOLDS it at 1.0 ([T1]) until the leg-roster scan is reconstructed. * **+0x3f4 = the REVERSE/BRAKE flag** (the "airborne re-pick" note was wrong): set when speedCmd < 0 while +0x348 (current speed) > 0, cleared otherwise; +0x344 (the accel rate the body advancers slew by) picks +0x5b8 forward / +0x5bc reverse accel (sentinel -1.1f @0x4ab174 = whole system disabled; IntegrateMotion re-derives the pick at its head). Entering reverse: MarkUpdate(0x100), gyro kick (0,0,+/-rand)@0.4 (50% sign flip via 0x408050 rand + 0.5f compare @0x4ab170). While reversing above the walk threshold (+0x534 < +0x348): pitch kick (0,1,0)@0.2 on a 0.4s countdown (+0x5c4) -- the braking shudder. NOT YET LANDED. * +0x654 = the legResetLatch (saved at frame top, cleared, compared at frame end -> MarkUpdate(8) on change). +0x584 = squat-capable, +0x588 = turn-clip-capable, +0x580 = gimp-clip-capable. * +0x574/+0x578 = walk/run turn rates; turn attenuation: speed >= +0x538 -> t=(speed-+0x534)/(+0x34c-+0x534), lerp A->B, t>1 -> B/t^2; clamp >=0; x mapper turn cmd (+0x12c); ZERO while fallen (+0x650) or legState 1/2/3; result -> +0x1d4. * +0x348 = current speed, +0x34c = max run speed, +0x350 = min(?) speed clamp in the shortfall term, +0x7a0 = real max speed (5-notch throttle quantizer: cmd = round(5*cmd/+0x7a0 + 0.5)/5 * +0x7a0... exact rounding via ftol of +0.5f), +0x6b4/+0x6b8 = body-channel demand/speed pair. * Perf head: `FUN_0049fa1c` = the combat-effectiveness census -> +0x414: walks roster slots 2.., classID 0xBBE (generator) charge fraction +0x12c/+0x128, 0xBC1 count with state != 1 && +0x210 != 4 (working coolant units), RTTI-gated weapon count (excluding launchers with +0x364 == 7); +0x414 = 1 when weapons < +0x448 min, no coolant, charge below threshold, or limping with the duck cell 0. Consumer unknown. * Perf head one-shot: +0x7a4 set && +0x7a8 clear -> sends the **RealMaxSpeed message (0x15, 0x20 bytes)** carrying +0x7a0, then latches +0x7a8 -- the network share of the computed real max speed (pairs with the 0x15 handler @0049f604, still to land). * Link plug at +0x418: first bound entity's distance -> +0x400, presence -> +0x3fc (identity of the link: open). * Mission-list y-compare -> +0x394 (the old "verify-guarded read" block): compares *(+0x67c) against a mission-chain entry's position y when legState not 0/1 -- identity open (in-water / off-pad flag?). ### Block 8 (move/collide) -- decoded, NOT yet landed Ground clamp `FUN_0040e5f0(+0x2f0, pos)` (penetration -> pos.y and the +0x2e8 box y/z); save old basis/pos; `FUN_004227e0(this,0)` volume; +0x44c = 0; `FUN_00422bac(this, vol, dt, &oldpos, &probe)` = THE MOVE. Outcomes on probe[1] (local_1c8): == sentinel @0x4ab180 -> restore pos+basis, gyro kick along normal @0.4 + pitch @0.2, CollisionState alarm (+0x450, 3 levels) -> 0; <= 0 -> alarm 0; else REAL HIT: partner material *(partner+0x24) -> +0x4a4, world->body normal -> +0x4a8, closing speed -(n . v) -> +0x4b4 (the CollisionMaterialType / CollisionNormal / CollisionSpeed attribute cells), alarm <- +0x44c, STOP at old pos (basis <- identity const @0x4e0f74), then **collision damage = a SELF-DISPATCHED TakeDamage message (id 0x12, 100 bytes, damage type DAT_0050b9ac, attacker = own entity id +0x184)** via vtbl+0xc; slow (speed^2 <= @0x4ab184) -> legs to 0 + legResetLatch=1 (+ MarkUpdate(1| 0x40) if +0x464 == 1), fast -> stagger clip 0x20 + MarkUpdate(1|0x20). After: +0x464 changed over frame -> MarkUpdate(0x80); vel.y = pos.y - oldpos.y (raw delta); `FUN_00421b6c`; IntegrateMotion(dt, 0); dirty thresholds (+0x768 pos-xz^2, +0x76c turn-delta, +0x770 heading-delta -> MarkUpdate(0x10)/(1); mapper cmd != +0x6b4 -> MarkUpdate(4)). ### The tail (decoded, partially ours already) Instability accumulator +0x3f0, THREE terms then clamp 1.0: (|accelvec +0x82c| / +0x784 * +0x788)^2 + speed-shortfall (clamped cmd vs +0x348, relative) * +0x78c + (legState==4 ? +0x798 : 0); -> gyro+0x3a8 when gyro exists. Gyro churn `FUN_004b2eac(gyro, dt)` only when legState != 0 && +0x57c == 0, then `FUN_004b34ec(gyro)` always -- both gated !fallen(+0x650). Torso::UpdateJoints(+0x438, &+0x360) gated !fallen. `FUN_0049fe80(this)` (a second roster census -- damage-side; decode parked). Five RING BUFFERS (FUN_0043ade4 = ring push, 0x43ae47/ 0x43ae0b = ring reduces): +0x7e0<-vel.z, +0x7ec<-vel.y, +0x7f8<-vel.x, +0x804<-turn rate, +0x810<-dt; smoothed values -> acceleration vector +0x1dc (delta/sum-dt vs prevs +0x81c..+0x828) -> copied to +0x82c (the instability input). `FUN_00421b2c` opens AND closes the frame (called twice); the mobility iterator is destroyed at the very end (`FUN_004a4ffb`). ### Landed in 5.3.121 MECHDMG kill/limp writes retargeted to the mode (SetSimulationState); IsMechDestroyed reads the mode (>= 9); the staged promotion replaced by the authentic counter block (+ ctor/Reset zeroes + Reset mode drop); the duck driver moved to its authentic slot (counters -> duck -> limp standup -> volume swap -> advance) and its gate renamed mobilityScale; the advance dispatch death-guarded. SIDE EFFECT: `Mech::InDeathTransition` and the camera director's cut-away are now LIVE (mode 9 is finally written on kills) -- the director path needs a rig eyeball when a pod is back. ## 5.3.122 -- the message roster fills (three of the six landed) Landed: **RealMaxSpeed** (@0049f604: adopt streamed +0x7a0 while +0x7a4 clear; wire payload at +0x1c, sender EntityID stamped at +0xc by Entity's network send @0041f640 = {stamp id, msg+0x14 <- entity+0x194, EntityManager (app+0x30) send @00434ea0}), **SetBurningState** (@0049f674: park the wreck at (localHostID x 10000, localHostID x -1000) -- constants @0049f6fc/f8, host id = HostManager::GetLocalHostID, THE accessor the instance dispatch compares against ownerID -- then MODE 2 = BURNING, the second InDeathTransition state's missing writer, + ForceUpdate(1) + AlwaysExecute), **ClearBurningState** (@0049f700: mode 0 + same pair). simulationFlags bit 1 == DontExecuteFlag (SIMULATE.HPP) -- the binary's `&= ~2` IS AlwaysExecute(). Still to land from the roster: * **BalanceCoolant @0049f728 -- LANDED 5.3.123** (equal-split press + RedistributeCoolantShares @0049f788 + the heatable ctor sweep that populates the heatableSubsystems chain + ctor/Reset redistribute calls; soak: 20 heatables, first share 0.05, ctor + BT_PRESS_BALANCE both renormalize, crash-sig 0). UNIFIED 5.3.124: MoveValve steps the heatable-base coolantPriority and calls the mech's RedistributeCoolantShares; valveState and the condenser-local renormalization are retired (RecomputeValves survives only as the [T3] conduction-flow bridge -- the fight-verified pump consumes a CONDENSER-relative fraction, refreshed from the redistribute tail; the ratios are numerically identical to the old math since non-condenser priorities cancel). REGISTRATION CAVEAT: the @0x50e534 name table sits in the HEAT TU statics but its owning class (heatable base vs Condenser) is NOT proven -- our registration stays Condenser id 4 (the live-verified streamed binding); revisit if a non-condenser valve binding ever surfaces. ValveSetting attribute still publishes coolantFlowScale (the displayed fractions are unchanged). * **EjectPilot @0049f854 -- LANDED 5.3.125** with the census (@0049fa1c -> combatIneffective, the master perf's opening call). Census truths, all pinned: 0xBBE = the AGGREGATE HEATSINK BANK (its coolant fraction +0x12c/+0x128 < 0.05 @0049fb50 = crippled term; my earlier "generator charge" reading was wrong), 0xBC1 = GENERATOR (working = state != 1 && generator state != 4 = GeneratorFailed -- our enum matches), weapons by RTTI with dry launchers excluded (+0x364 == 7 == our NoAmmoState exactly), minimum weapon count = mech+0x448 = CTOR-HARDCODED 2 (part_012.c:15749), limping without the crouch cell completes the roster of crippled terms. The eject: mode 10 + mapper ejectLatch (+0x258) + self-dispatched explosive TakeDamage (type 2, zone -1 -> cylinder resolver, impact = own position). STAGED, recorded: the damage amount (binary reads *(*(mapper+0x208)+0x1c), a bound/cached pointer with NO game-side writer in the decomp -- needs the mapper ctor binding-loop decode) and the score notify (@00429078 accessor + app+0x20 vcall, event code 5 -- same poster idiom as the player-side @004c1044 throttle). Dev kit: BT_FORCE_CRIPPLED=1 + BT_PRESS_EJECT=1 (pod_render_eject.conf). THE AUTHENTIC MESSAGE ROSTER IS NOW 6/6. Mode roster: 0 default, 2 burning, 3/4 gimp L/R, 5-8 falls, 9 killed, 10 ejected; writers of 5-8 still open. ## 5.3.127 -- THE SUPER STOP + THE INSTABILITY MODEL (landed) **The model resource's own field names decoded these blocks.** The ctor loads (part_012.c:15798-15804) tie the master perf's anonymous offsets to the authored names our `Mech__ModelResource` already carried: | model rec | mech | name (authentic, from the struct) | |---|---|---| | +0x44 | +0x344, +0x5b0, +0x5b8 | `maxAcceleration` (live rate + forward figure) | | +0x48 | +0x5bc | **`superStopAcceleration`** | | +0x4c | +0x5c0 | `throttleAdjustment` | | +0x80 | +0x784 | `maxUnstableAcceleration` | | +0x84 | +0x788 | `unstableAccelerationEffect` | | +0x88 | +0x78c | **`unstableGunTheEngineEffect`** | | +0x8c | +0x790 | `unstableSuperStopEffect` (streamed, consumer OPEN) | | +0x90 | +0x794 | `unstableHighVelocityEffect` (streamed, consumer OPEN) | | +0x94 | +0x798 | **`unstableStopedTurnEffect`** | That naming is what made the instability formula legible: the term added when the leg gait state is 4 is `unstableStopedTurnEffect` and gait 4 IS turn-in-place; the speed-shortfall term is `unstableGunTheEngineEffect`. The names confirm the arithmetic, and the arithmetic confirms the names. **The super stop** (@0x4aa353): the throttle going negative while the mech still rolls forward is a hard brake, not a reverse. Edge -> swap +0x344 from the forward rate to `superStopAcceleration`, MarkUpdate(0x100), and ONE random-signed lurch through both gyro channels at weight 0.4 (magnitude roll + a 0.5 coin flip @0x4ab170). While it holds above the walk threshold, a (0,1,0)@0.2 pitch kick every 0.4s. Release restores the forward rate. `superStopAcceleration == -1.1` (@0x4ab174) DISABLES the system for that chassis -- the sentinel must survive the model read unguarded. **The instability accumulator** (tail @0x4aab8e): three weighted terms, clamped to 1, into `unstablePercentage` (+0x3f0 -- ALREADY a published cockpit attribute in our tree, so this lights a live gauge) and republished to gyro+0x3a8. The gyro's own tip/sway machinery (@004b275c) reads that sum against its +0x3bc threshold -- that consumer is the next gyro brick. Term 1 rides the ring-buffer acceleration (+0x82c) and stays inert [T1] until the rings land. **CORRECTION to 5.3.122**: `realMaxSpeed` was a DUPLICATE member for mech+0x7a0, which our tree already carried as `runSpeedMax` (the myomers raise it). Merged; the 0x15 handler writes `runSpeedMax`. And the +0x7a4 "we computed our own" flag is set by the ctor's MYOMERS sweep (part_012.c:15874) -- i.e. a mech with myomers broadcasts its cap, a mech without adopts the streamed one. **Gyro primitives already existed**: FUN_004b2d8c == our `Gyroscope::ApplyDamageImpulse` (eyeForce), FUN_004b2de4 == our `ApplyDamageTorque` (bodyForce). OPEN, worth a look: the binary's torque zeroes bodyForce.y then negates ONLY .x (+0x308); ours negates the whole vector, so the .z sign may differ. ## 5.3.128 -- THE TELEMETRY RINGS (landed) The five ring buffers ARE the engine's `AverageOf`, and our tree already carried them: `telemetryFilter[5]`, sized 15 in the ctor since the Mech-layout wave, fed by nothing until now. `FUN_0043ade4` = `Add` (with wraparound), `FUN_0043ae0b` = `CalculateAverage`, and `FUN_0043ae47` = **`CalculateOlympicAverage`** -- sum minus min minus max over count-2, the authentic name for a judge-style trimmed mean. Feeds: vel.z / vel.y / vel.x / turn rate / frame slice. The derived acceleration is the change in FILTERED values over the FILTERED slice, which is why instability answers a sustained shove and not one noisy frame. TWO ODDITIES KEPT VERBATIM (the binary is explicit; do not tidy them): the vel.y ring is fed every frame and never reduced, and the acceleration's components are a mongrel -- x from mean vel.x, y from MEAN vel.z, z from OLYMPIC vel.z. Only the LENGTH is consumed, so behaviour is unaffected. LIVE RESULT + A FREE DIAGNOSTIC: `unstablePercentage` now moves over its whole range (0 -> 1.0 clamp) on the rig. Walking, it pins near 0.84-0.99, dominated by the gun-the-engine term -- because the mech demands 35.9 u/s and the reconstructed gait delivers 7.0. Whether that gap is authentic acceleration or a gait shortfall is a SEPARATE open question, and the new gauge is now the instrument for answering it (BT_TELEMETRY_LOG). ## 5.3.129 -- THE MOBILITY SCAN (landed; the mobilityScale [T1] retired) **Chain identity PROVEN, not inferred.** My 5.3.122 note pinned the +0x7ac chain to Myomers "by static-layout adjacency to the string pool" -- a weak argument that nearly went wrong, because the first cell I checked (+0x31c) is a MechWeapon trigger in the weapon TU. The decisive evidence is arithmetic: the Myomers cap-raise @004b8ef0 (our `Myomers::RegisterMaxOutput`) reads `seekVoltage` at +0x330 indexed by `maxSeekVoltageIndex` at +0x32c. Walking OUR member order backwards -- maxSeek 0x32c, minSeek 0x328, recommended 0x324, current 0x320 -- lands `speedEffect` exactly on +0x31c, the cell the scan maxes. GUID 0x51155c == Myomers, confirmed. (0x511830 == MechWeapon was independently confirmed by the census, which tests it and then tests 0x5121a8 for the dry-launcher exclusion.) The scan: max `speedEffect` over the chain -> the mobility scale, applied straight to the mapper's command cells (throttle *= scale; a scale inside the 1e-4 deadzone ALSO zeroes the turn -- a mech with dead muscles cannot even pivot). It is the same cell the duck driver reads as "the legs still work". Guarded by the myomer count, so a chassis without them is untouched. SAFE BY CONSTRUCTION: the mapper reassigns its demands from scratch in InterpretControls, which ticks before the mech's own performance, so the in-place multiply cannot compound frame to frame. The ctor's myomer sweep is also what sets +0x7a4 -- so a mech WITH myomers computes and broadcasts its own top speed, and one without adopts the streamed value. Both halves now land together. Soak: `[mobility] scale 1 over 1 myomers` on an undamaged bhk1 -- throttle unscaled, drive unchanged (demand 35.9, speed 7.0), zero faults.