Gyro: byte-exact re-enable -- ctor map, integrators, jointeye writers (task #56)

The Gyroscope subsystem is LIVE again (was a stub since the NaN revert).
Reconstructed byte-exact from @004b3778 / @004b2ec0 / @004b30ec / @004b33e0 /
@004b34ec + the byte-verified dispatch in the unexported Mech performance
FUN_004a9b5c (calls @0x4aaf74/0x4aaf83):

- ctor field map corrected: springConstant@0x1E8 / dampingConstant@0x1F4 were
  mislabelled (the old 'eyeOrientation = r->springConstant' poison line), the
  0x254-0x2B3 block (externalPitchPtr, work matrix, placement) was missing so
  everything after was mis-offset, and clamps/accumulators were 0xCD fill --
  every field now initialised per the binary; 33 offsets static_assert-locked,
  sizeof == 0x3D0 exact
- integrators: state-minus-target displacements, componentwise damping
  OVERWRITE (FUN_004086d0 is a component multiply, not a cross), position step
  without dt, clamp to [posSpring, negSpring]; IntegrateBody's X/Z-crossed
  force + integration terms
- writers: WriteMechJoint drives ONE node ('jointeye', type 5): TRANSLATION =
  eyePosition spring, ROTATION = bodyOrientation spring; WriteEyeJoint is a
  multiplicative sway attenuator on 'jointlocal' (post-anim only)
- dispatch moved out of GyroscopeSimulation into the Mech performance tail
  (GyroFrameJointWrite bridge, mech4.cpp) with the binary gates; gyro<->torso
  pitch link wired (gyro+0x258 = &torso currentTwist) via complete-type-TU
  bridges, retiring the SubProxy::linkTarget landmine
- Mech ctor: deathAnimationLatched/legResetLatch were never initialised --
  0xCDCDCDCD gated the writers off silently

Runtime-verified: joints resolve (both BallTranslation), Performance installs,
WriteMechJoint finite from frame 0 (no NaN), Madcat cockpit un-regressed,
combat targeting healthy. Empirical: spring targets are SYMMETRIC -> eye
equilibrium (0,0,0), clamps +/-0.1-0.15u -- the gyro is the hit-BOUNCE
mechanism, not a steady eye offset (hypothesis disproven, recorded in KB).

Pending (task #56 tail): the damage->gyro fan-out FUN_004b2980 (unexported
gap) so hits actually kick the springs; the mech+0x3F0 overspeed sway model;
the torso-pitch EyepointRotation writer (FUN_004b66b4) + glance-look states.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-11 06:47:22 -05:00
co-authored by Claude Fable 5
parent abaa145b6f
commit cb85517ede
7 changed files with 373 additions and 158 deletions
+22 -9
View File
@@ -69,12 +69,14 @@ authentic path scoped.
- **Cockpit HUD leftovers (tasks #35-#38 residue, 2026-07-08)** — the reticle + 7 weapon pips +
ALL the instrument dynamics are LIVE (the Execute @004cdcf0 gap was RECOVERED via capstone
disasm, task #37; the authentic Lock producer + the simple-X mode landed in #38 — see
[[gauges-hud]] for the full instrument map). Remaining: (a) the **blx_cop canopy shell**: it is
the torso segment's SkeletonType_A mesh and fully encloses the eye; it renders as a black box
because the skeleton-branch render path isn't giving it its texture + the PUNCH cutout (the
canopy WINDOWS are punch texels — with punch live the black pane texels become holes and the
world shows through the frame). Fix lives in the [[rendering]] skeleton/punch branch, not the
HUD; hidden by name filter until then (`BT_INSIDE_COCKPIT=1` shows it). (b) the **3D marker
[[gauges-hud]] for the full instrument map). Remaining: (a) the **`*_cop` canopy shell** —
SOLVED for the Madcat (task #55, see [[cockpit-view]]): authentic eye (baseOffset + parent-DCS +
inverse view) + single-sided inward-wound lattice + dark `softer` ramp = the dark frame with the
world through the openings, verified vs gameplay footage; shows by DEFAULT now
(`BT_HIDE_COCKPIT=1` hides). NOTE the old claim here ("canopy windows are punch texels") was
WRONG — the shell has no texture; the openings are geometry. STILL OPEN: the non-Madcat mechs'
views are blocked because the resting eye sits ~0.6u inside the canopy wall — the missing
gyro eye-joint steady offset (task #56, [[cockpit-view]] §gyro). (b) the **3D marker
chain** ([0x31c]/[0x320] dpl objects + the PNAME1-8.bgf player-name meshes over the locked
target — matters for MP). (c) the compass rotation SIGN is derived-not-verified [T3] (turn
left → the stem should swing right; flip the sin sign in Draw if footage disagrees).
@@ -82,9 +84,20 @@ authentic path scoped.
BTPlayer+0x1dc is never populated → MessageBoard is empty (authentic for bring-up). What
resolves it: wire the pool + decode `AddStatusMessage @0042e580` + the `Player__StatusMessage`
record ({messageId@+0xc, nameEntity@+0x10}).
- **Gyroscope (0xBC4)**layout + joint-I/O reconstructed, but the ctor field-init + the two
integrators (IntegrateEyeJoint @004b2ec0 / IntegrateBody @004b30ec) are incomplete → writes NaN
to the root joint. Reverted to a stub. A full subsystem-sim reconstruction (bigger than Torso).
- **Gyroscope (0xBC4) — RE-ENABLED LIVE (task #56, 2026-07-10).** The NaN revert's root causes
are fixed byte-exact (ctor field map @004b3778 — springConstant@0x1E8/dampingConstant@0x1F4
were mislabelled, the 0x254-0x2B3 block was missing, clamps/accumulators uninitialised; the
integrators' state-minus-target/componentwise-damping-overwrite/X-Z-crossing semantics; the
writers' one-node-two-channels form; dispatch from the MECH performance tail, not the gyro
Performance). Layout locked (sizeof==0x3D0); runtime clean (joints type 5, finite state, no
NaN). Empirical: spring targets are SYMMETRIC → eye equilibrium (0,0,0) → the gyro is a
±0.1-0.15u BOUNCE mechanism, NOT a steady offset (the earlier hypothesis is disproven).
REMAINING (task #56 tail): (a) the damage→gyro fan-out **FUN_004b2980** (0x4b2980-0x4b2d8b,
unexported gap; called @0x4a02fb + direct crunch kicks) — without it no hit-bounce fires;
(b) the mech+0x3F0 overspeed sway model (swayBias fed 0); (c) the per-frame
`EyepointRotation.pitch = torso pitch` writer (FUN_004b66b4) + mapper glance-look states
(FUN_004afd10 — yaw/pitch from mech+0x564..0x570). Also: `deathAnimationLatched`/`legResetLatch`
were never ctor-initialised (0xCDCDCDCD gate bug, fixed in mech.cpp ctor). See [[cockpit-view]].
- **MechControlsMapper look/eyepoint commit** — reconstructed but its offsets collide with declared
members; arbitrate before enabling (no port consumer yet). The fire-trigger-through-mapper is
still the `gBTWeaponTrigger` bring-up.