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:
co-authored by
Claude Fable 5
parent
abaa145b6f
commit
cb85517ede
+27
-23
@@ -213,9 +213,10 @@ extern Subsystem *CreateMyomersSubsystem(Mech *, int, void *); // 0xBC6 (WAVE 6
|
||||
extern Subsystem *CreateProjectileWeaponSubsystem(Mech *, int, void *); // 0xBCD (WAVE 7 -- ammoBinLink 0xC, layout locked; FireWeapon no-spawn Phase A)
|
||||
extern Subsystem *CreateMissileLauncherSubsystem(Mech *, int, void *); // 0xBD0 (WAVE 7 -- shadows deleted, layout locked; FireWeapon no-spawn Phase A)
|
||||
extern Subsystem *CreateGaussRifleSubsystem(Mech *, int, void *); // 0xBCE (WAVE 7 -- Emitter subclass, no-op FireWeapon; dedicated bridge)
|
||||
// CreateGyroSubsystem (0xBC4) is reconstructed + ready in gyro.cpp (layout re-based,
|
||||
// joint I/O real), but NOT wired -- the gyro ctor/integrator reconstruction is
|
||||
// incomplete (garbage output); see the 0xBC4 case below.
|
||||
extern Subsystem *CreateGyroSubsystem(Mech *, int, void *); // 0xBC4 (task #56 -- ctor/integrators byte-exact, ENABLED)
|
||||
extern void GyroFrameJointWrite(Subsystem *, Scalar, int, int); // task #56 -- mech-performance joint-write dispatch (mech4.cpp)
|
||||
extern void GyroBindExternalPitch(Subsystem *, Scalar *); // task #56 -- post-stream gyro+0x258 = &torso twist
|
||||
extern Scalar *BTGetTorsoTwistAddr(Subsystem *); // torso.cpp bridge (complete-type TU)
|
||||
|
||||
// Post-stream entity glue + cosmetic objects.
|
||||
struct StandingAnimation { template<class...A> StandingAnimation(A&&...) {} };
|
||||
@@ -839,6 +840,10 @@ Mech::Mech(
|
||||
hudSubsystem = 0; // this[0x16d] (0xBD6 -> HUD; was misnamed mechTechSubsystem)
|
||||
forwardThrottleScale = 1.0f; // @0x5c0 mapper speed scale (writer not in decomp; neutral)
|
||||
sensorSubsystem = 0; // this[0x1f7] (0xBBE) -- same hazard, zero it too
|
||||
deathAnimationLatched = 0; // @0x650 -- same 0xCDCDCDCD hazard: the gyro joint-write
|
||||
// dispatch (task #56) gates on it every frame; garbage
|
||||
// nonzero silently disabled the writers until death anims ran
|
||||
legResetLatch = 0; // @0x654 -- same latch family, same fill hazard
|
||||
attrPad = 0.0f; // shared read pad for un-populated gauge attributes
|
||||
linearSpeed = 0.0f; // live forward ground speed (LinearSpeed gauge); set per frame
|
||||
radarRange = 1000.0f; // radar display scale (SetTargetRange is stubbed;
|
||||
@@ -1017,17 +1022,17 @@ Mech::Mech(
|
||||
break;
|
||||
|
||||
case GyroClassID: // 0xBC4 -> real class Gyroscope (ctor @004b3778)
|
||||
// WAVE 5 DEFERRED: the layout re-base + joint I/O ARE done (gyro
|
||||
// constructs, resolves real joints jointlocal/jointeye, WriteMechJoint
|
||||
// fires -- CreateGyroSubsystem is ready in gyro.cpp). BUT the gyro's
|
||||
// ctor field-init + integrator field-MAPPING are incomplete in the
|
||||
// reconstruction (binary ctor @004b3778 puts springConstant@0x1E8,
|
||||
// dampingConstant@0x1F4, etc.; the recon mislabels these and leaves the
|
||||
// accumulators uninitialised) -> live output is 0xCDCDCDCD/NaN written
|
||||
// to the ROOT joint. Keep the stub until the ctor+integrator are
|
||||
// faithfully reconstructed from @004b3778. See CLAUDE.md §10d.
|
||||
subsystemArray[id] = (Subsystem *)
|
||||
new (Memory::Allocate(0x3d0)) Gyro(this, id, seg); // FUN_004b3778 (stub)
|
||||
// RE-ENABLED (task #56). The old NaN revert's root causes are fixed
|
||||
// byte-exact against @004b3778/@004b2ec0/@004b30ec: the ctor field map
|
||||
// (springConstant@0x1E8 / dampingConstant@0x1F4 were mislabelled, the
|
||||
// 0x254-0x2B3 block was missing so everything after was mis-offset,
|
||||
// clamps/accumulators were left as 0xCD fill) and the integrator
|
||||
// semantics (state-minus-target displacements, componentwise damping
|
||||
// OVERWRITE, IntegrateBody X/Z crossings) -- all static_assert-locked.
|
||||
// The joint writers now dispatch from the MECH performance tail
|
||||
// (GyroFrameJointWrite bridge; binary calls @0x4aaf74/0x4aaf83), NOT
|
||||
// from GyroscopeSimulation.
|
||||
subsystemArray[id] = CreateGyroSubsystem(this, id, seg); // ctor @004b3778 (real)
|
||||
gyroSubsystem = subsystemArray[id]; // Wword(0x14a)
|
||||
break;
|
||||
|
||||
@@ -1139,16 +1144,15 @@ Mech::Mech(
|
||||
weaponCount = 2; // Wword(0x112) reset to base index (sentinels 0,1)
|
||||
|
||||
//
|
||||
// Cross-link the gyro to the torso twist (sinkSourceSubsystem+0x1D8 ==
|
||||
// Torso::currentTwist) so the gyro can fold torso yaw into the mech joint.
|
||||
// ⚠ DEFERRED (WAVE 5): the recon SubProxy::linkTarget sits at gyro+4 (an engine
|
||||
// base field), NOT the real gyro torso-link offset (which the gyro layout has
|
||||
// not yet mapped) -- writing here would STOMP the live gyro base. Skipped until
|
||||
// the gyro's torso-link field is recovered; harmless meanwhile (the Blackhawk
|
||||
// torso is disabled, so there is no twist to couple). See CLAUDE.md §10d.
|
||||
// Cross-link the gyro to the torso twist (task #56, binary bt_mech tail:
|
||||
// gyro+0x258 = torso+0x1D8 == Torso::currentTwist; the gyro damage-response
|
||||
// @004b2980 reads it per hit). Done through the two complete-type-TU bridges
|
||||
// (GyroBindExternalPitch / BTGetTorsoTwistAddr) -- the old raw
|
||||
// SubProxy::linkTarget write landed at gyro+4 (an engine base field) and would
|
||||
// have stomped the live gyro base; that landmine is retired.
|
||||
//
|
||||
// if (sinkSourceSubsystem != 0 && gyroSubsystem != 0)
|
||||
// ((SubProxy *)gyroSubsystem)->linkTarget = (char *)sinkSourceSubsystem + 0x1d8;
|
||||
if (sinkSourceSubsystem != 0 && gyroSubsystem != 0)
|
||||
GyroBindExternalPitch(gyroSubsystem, BTGetTorsoTwistAddr(sinkSourceSubsystem));
|
||||
|
||||
//
|
||||
// Build the capability sub-rosters by IsDerivedFrom() class tests.
|
||||
|
||||
Reference in New Issue
Block a user