Merge gameplay crash fixes and native board adjustment

This commit is contained in:
chazmm committed 2026-09-09 19:25:48 +01:00
commit 2611f9ccc4
19 files changed
+700 -21

No files matched your search

+66
View File
@@ -0,0 +1,66 @@
# BoardAdjust native lifecycle and release
The cleanup-only change `fd280fd` was reverted in `411260a` after a user
reported a snap during return to neutral. This replacement ports the complete
BoardAdjust lifecycle, rather than changing animation timing to hide the snap.
## Reference and observed behavior
Read-only sources under `Documents/Skate3Research/research/reverse-engineering`:
- `generated/skate3_animation_research_recomp.71.cpp`, SHA-256
`a4b47427402cfc4fc6aa0a6e5b08d4fe81b974da669c107e610a960ec2652257`.
- `XexDump/default_82000000_011B0000.bin`, SHA-256
`f4aa113eb541bfba03dbc108cf5ab43f58c965b20fa3b82f9c40938a0ad841c4`.
- The same guest instructions decoded with IDA 9.3 in a disposable database.
- Stock ActionGraph BoardAdjust includes, `MotionGraphIncludes/air.xml`, and
`MotionGraphIncludes/BoardAdjusts/T_BoardAdjust.xml` from `MiscloadState`.
Addresses below are TU3 guest virtual addresses (image base `0x82000000`), not
addresses in the Windows reference executable. The reference installation was
located at `C:/CLEAN/Skate3CustomEngineLayer-0.1.0-preview.18-Windows`;
its `skate3.exe` SHA-256 is
`4d5234b2297fa7f1e02808ce2780ad37c960e4da6d26ae5004591cba91fe6904`.
It was not launched or modified; no runtime parity claim is made for that build.
Observed in recompilation and corroborated by IDA:
| Callback | Guest address | Behavior |
|---|---|---|
| Constructor | `82BA2A30` | Magnitude name at object+28, angle name at +52, angle filter at +76, mirror-negation default **true** at +80. |
| Allocate | `82BA2F48` | Separate 16-byte instance for each behavior. |
| Begin | `82BA2BA8` | Clear instance wrap mode at +8 and previous raw angle at +12. No intent publication. |
| Update | `82BA2BC8` | Require both source intents; copy magnitude, filter angle, optionally negate for mirrored stance, apply persistent angle seam logic. |
| Missing input | `82BA2E88` | If either source is missing, remove both outputs and clear both instance fields. Present zero remains a valid value. |
| End | `82BA2EB8` | Remove both authored outputs; no instance reset here. |
The seam logic at `82BA2D70` detects a sign change when the previous raw angle
has absolute value greater than pi/2 (`822538BC`, bits `3FC90FDB`). In mode 0,
crossing from negative enters mode 1, crossing from positive enters mode 2.
Mode 1 holds -pi (`822F8908`, bits `C0490FDB`), mode 2 holds +pi
(`82060C44`, bits `40490FDB`). Crossing back from the opposite side clears
the mode. Every successful update stores the **raw filtered angle**, even while
the published angle is held at pi. This state was missing from the Rust host.
## Release and animation handoff
The stock graph filters missing axes toward zero with blendOut 0.08,
clampAcc 0.03, clampVel 0.2. Recompilation `82BB17D0` agrees with the existing
filter arithmetic, including the missing-input branch. The board-adjust state
exits when the directional intent is absent and both absolute filtered values
are below 0.4. The default airborne tree is `B_AIR_CYC` with authored time 0.2
and transitionUnder enabled. Blend evaluation/weight functions `82B961F8` and
`82B963D8` agree with the existing blend progression. No duration, threshold,
filter coefficient, pose offset, or extra smoothing has been fitted or changed.
The new tests cover the native seam branches, mirror signs, separate instances,
entry/update/exit, partial input loss, present zero, stock constructor defaults,
and the stock filtered release followed by its 0.2-second animation-tree blend.
These are source-level tests, not a replay of the user's controller sequence.
The reported visual snap's precise cause remains unconfirmed until gameplay
validation; the additional native discrepancies are independently established.
Validation (Windows MSVC release/static CRT): seven action-host tests passed,
including stock graph parsing; the stock release-to-air animation test passed.
That test observes a zero-weight incoming tree at handoff and the authored blend
progression to full weight. It does not measure rendered bone-pose continuity.
+117
View File
@@ -12,6 +12,123 @@ Coverage limits: a Windows unhandled-exception filter attempts a fixed, allocati
For manual UI validation, run the executable with `--crash-report-preview`. This generates a clearly synthetic report and opens the popup without initializing the game, setup, Steam or assets. Check Copy report, clipboard text, Open folder, saved UTF-8 text and Close. Static tests do not validate desktop presentation.
## Mixed-worktree dependency in f96be1d (2026-09-09)
The DownTown report at tick1020 repeats the nonfinite walking result before
the swept-line rejection. The full local stderr retains the finite GroundJob
and tiny surface components omitted from the bounded report.
The matching shipped PDB establishes that `movement_velocity/math.rs` was
compiled from worktree `8186`, with SHA-256
`4652072df4a51a6bf8eb2dd837e61d4fb6e01710d984334af8073deb4c4449ac`.
That source lacks the earlier subnormal refinement fix. The intended source
in this worktree has SHA-256
`76de0780adb5ea015c57fa4118105669f1897ef01eafb611eed14cc829c5eda1`.
The game build ID identified the game crate, but did not establish the identity
of reused path dependencies. Matching EXE/PDB GUIDs alone did not catch this.
`tools/build_verified_windows.ps1` now builds into a private
`target/verified-windows` under the current worktree. Its verification step
reads PDB source checksums and requires both current-worktree paths and matching
SHA-256 for referenced project crates and vendored Bevy sources. It fails closed
when required game/core/data source records are missing. The old shipped PDB
fails this check (619 mismatched path/checksum entries).
Use this build script for subsequent crash-test builds and retain its
`source-checks.json` with the staged EXE/PDB and existing import/hash manifest.
Do not share Cargo artifact directories between independently edited worktrees.
This repair changes build provenance, not gameplay rules or collision validation.
## Walking velocity convergence (2026-09-09)
Observed user failure: clean revision `dff672a`, build timestamp
`1788969088174193000`, report timestamp `1788969335`. At tick4059 in
BipedGround on University, `OFFBOARD_GROUND_RESULT_NONFINITE` precedes
`Invalid offboard swept-line request`. The job has finite spatial inputs;
the controller publishes NaN velocity/position, a NaN right delta and a
forward delta of approximately `-3.11e-43`. The collision query then rejects
NaN XYZ coordinates. Its validation is correct and remains intact.
The walking velocity limiter's portable reciprocal-square-root refinement
formed `r*r` from a positive subnormal squared length. A finite correction
of `1e-21` produces squared bits `0x000002CA` and a finite inverse root near
`9.997e20`, whose square overflows to infinity. The two refinements then
produce NaN. A focused pre-fix regression reproduced an all-NaN limited
velocity from otherwise finite vectors. This establishes the numerical
failure independently of the collision system; it is not a replay of all
4059 input ticks.
The fix normalizes only positive subnormal squared lengths by the exact
power of two `2^24`, retains both refinement stages, and rescales the inverse
root by `2^12`. It preserves the ordinary-input path, movement limits and
invalid-input propagation. No global floating-point mode changes, collision
bypass, arbitrary epsilon, or replacement player state are involved. This
is a stability correction for the existing portable PC arithmetic, not a
claim of bit-exact Xenon instruction emulation.
Regressions cover the failing finite vectors, powers-of-two across the
subnormal/normal boundary, limiting tiny corrections, steady walking updates,
and the complete ground-controller publication (including position, lean and
cadence). Zero and NaN checks ensure invalid inputs are not silently repaired.
The report, matching stderr and arithmetic evidence are retained privately
with the test builds. Gameplay validation remains with the user.
Validation: the finite-delta regression failed before the arithmetic change
with `[NaN, NaN, NaN, NaN]`. Afterward all 11 movement-velocity tests passed,
followed by all 202 offboard library tests in the release MSVC configuration
(`cargo test --release --locked --target x86_64-pc-windows-msvc -p skate-core
--lib player::offboard::`). No game or renderer was launched.
## FingerFlipOut (2026-09-09)
Observed user failure: clean revision `1a6e95b`, build timestamp
`1788967727931108700`, report timestamp `1788968141`, University fingerprint
`c911af6099e02b65`. At tick3467 in KnownAir, MotionGraph behavior3080 returned
`MotionGraph stock gameplay producer FingerFlipOut is not implemented`.
This was an explicit unsupported-operation exit, with no recorded panic or
native exception. The matching launch stderr contains the same error.
Native recovery from the TU3 image mapped at `0x82000000`:
- Factory82BC7C18 binds authored `grabintent` and literal `Grabbing`.
Vtable8232072C allocates a private float through82BBCB50, calls
Begin82BB3198, Update82BB7C40 and empty End82B61BB8.
- Begin sets the float to zero. Update reads the MotionGraph intent map
through Actor20/virtual16. Membership lookup82454FD8 counts a zero-valued
intent as present. Presence subtracts the time-service delta; absence adds
it. This does not read raw ActionGraph or filtered tweak input.
- Update clamps the retained time to layout190/198, evaluates eight curve
keys at1A0 and values at1C0 through PointGraph82481E10, then writes
`Grabbing` through ISkaterAnim80 (unnormalized, sequence -1).
- Global constructor8289FD10..30 selects collection `41DB0C4F82003A15` at
offset164. Helper8289D4E8 identifies class `anim_motion`. The retail schema
independently maps layout190 to field `E0C1407B688858AD`, type
`Sk8::PointNegGraphData8`. Its stock timer bounds are 0 and 0.5 seconds,
with a descending grab blend from 1 to 0. Numeric names remain supported
directly; no shared asset edit or invented curve is required.
The implementation retains one timer per bound behavior and publishes only
on Update. Begin resets time; End leaves the last parameter alone. Other
unimplemented operations still report errors.
Evidence identities (SHA-256): TU3 mapped image
`f4aa113eb541bfba03dbc108cf5ab43f58c965b20fa3b82f9c40938a0ad841c4`;
tested stock MotionGraph
`806b2665e435be4e313d70a06fab4538e0adf60a2dfd3e80e82ae8d0b4a2e7c1`.
Bounded decoded instructions, schema lookup and the original report are
retained privately with this test build. IDA changes were confined to a
disposable database copy. The instruction/data mapping is observed;
successful gameplay reproduction after the fix remains user validation.
Focused regressions cover release/regrab timing, clamping, entry reset,
the actual stock behavior3080, zero-valued intent membership, raw-input
separation, independent behavior instances and Begin/End publication rules.
They do not launch the renderer or replay the user's full input sequence.
Validation: `cargo test --release --locked --target x86_64-pc-windows-msvc
-p skate-game --bin skate3rust --no-default-features finger_flip --
--include-ignored` passed both tests against the prepared assets (0.18 seconds).
## SetDeckPitchAndYaw (2026-09-08)
The supplied report stopped in KnownAir at tick4813, MotionGraph behavior3373: