Files
TeslaRel410/restoration/source410/BT
CydandClaude Fable 5 3629755d90 BT410 5.3.92: the gait slot map -- the clip array is bigger than the name table, and the "gimp" members are the REVERSE figures
Went to source animationClips[] and found two things: a bug in what 5.3.91
committed, and a naming trap that has already cost BT411 a shipped defect.

THE BUG, MINE.  I sized animationClips[AnimationCount] -- 0x1d, from the enum.
Wrong.  The name table stops at 0x1d but the ARRAY does not: slot 0x20
(mech+0x64c) is the bump/crash clip the mech binds on a hard wall impact.  So
the array is [AnimationSlotCount] = 0x21 and Set*Animation's Verify bounds
against that instead.  Sizing a real array off a name table that stops earlier
reads fine and corrupts whatever sits next door; caught by reading the clip
loader, not by the compiler.

THE SLOT MAP, recovered from LoadLocomotionClips and now written down in full
(suffix, meaning, and which measured constant each clip yields):

   5      swr        stand -> walk        standSpeed
   6/7    wwr/wwl    forward walk CYCLE   walkStrideLength = (s6+s7)/(d6+d7)
   8/9    wsr/wsl    walk -> stand
   10/11  wrr/wrl    walk -> run          reverseSpeedMax
   12/13  rrr/rrl    run CYCLE            reverseStrideLength
   14/15  rwr/rwl    run -> walk
   16/17  sbr/sbl    stand -> back        gimpSpeedMax
   18/19  bbr/bbl    reverse CYCLE        gimpStrideLength (NEGATED here)
   20/21  bsr/bsl    back -> stand
   22/23  wgl/wgr    walk -> limp         gimpLeft/RightSpeedMax
   24/25  ggr/ggl    limp CYCLE           gimpLeft/RightStrideLength
   26/27  gsl/gsr    limp -> stand
   0x20   bmp        bump / crash stagger

THE TRAP: THE "gimp*" MEMBERS ARE THE REVERSE FIGURES, NOT THE LIMP ONES.
gimpSpeedMax and gimpStrideLength are measured from sbr and bbr/bbl -- the
reverse gait.  The real limp has its own gimpLeft*/gimpRight* pair.  This is
the same bad naming that produced the states-16-19 misreading recorded in
5.3.91, and it has now caused the same error twice from two directions.

Also settled: gimpStrideLength's negative sign is applied AT MEASUREMENT, not
authored into the data -- which is where the fold in the transition machines
comes from.  And the limp clips are OPTIONAL: the loader probes for wgl and
leaves hasGimpClips 0 with slots 22-27 unfilled if the model lacks it, so the
deferred gimp branch must check that before routing into the limp machine.

THE ENUM IS NOT THE SLOT MAP, and MECH.HPP now says so at the enum itself.
The names are verbatim from the binary and authoritative AS NAMES, but slot
0x0e takes the run-to-walk clip while the table calls it RightReverseAnimation,
and the forward walk alternates 6/7 rather than the pair the WalkForward names
suggest.  Read the slot map for "what does this play"; read the enum for "what
did the original call this index".

ATTRIBUTION NOTE: the four clip helpers (ResolveAnimationClip @004a7f50,
MeasureClipStride @004a8054, LoadLocomotionClips @004a80d4,
LoadLocomotionClipsExt @004a86c8) are exactly the four addresses the manifest
lists under mech2.cpp that BT411 files under mech3.  The manifest's attribution
comes from the binary's own file tagging, so they belong here -- which also
accounts for all 12 of mech2's functions.

BT 51/51.  Still nothing calls the gait.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 08:15:17 -05:00
..