D173/D292: cross-reference D243's chrUpdateAnim mechanism finding

The Dam abseil cutscene investigation (D243 M-160/M-164/M-165) traced a
general pattern likely shared by the whole "third-person world model
transform/lifecycle" bug family already flagged at M-145: chrUpdateAnim
reads a puppet's animated root-joint position back into its logical
position, so a transition that moves the puppet without also updating
its animation state produces a position that visibly lags/diverges,
tracking the stale animation instead of the intended spot. Plausible
explanation for D173's level-start float and D292's death-sink, not
confirmed for either -- flagged as the thing to test with a live capture
using the same aidx=/animframe= technique D243 M-166 just added, rather
than re-deriving a new mechanism from scratch next time either is
investigated.
This commit is contained in:
James Dansereau committed 2026-09-17 12:50:42 -04:00
1 parent d9c7705654
commit e4a870484b
1 file changed
+3 -1
+3 -1
View File
@@ -10444,6 +10444,8 @@ crash class C2 (Facility `-level_34`, Runway `-level_35`): `import_texture_i8` A
**Status (from §F table):** OPEN — observed, not investigated. **M-87 user playtest: still present** — "Bond floating in the sky / cutscene glitch thing still exists." Related, newly reported: **in some cutscenes Bond spins in circles** (named instance: end of Cradle, when Trevelyan falls) — likely the same actor-position/anim-root class rather than a new bug; logged under D148/D160 (`GRAPHICS-BACKLOG.md`) since it's cutscene-triggered. **M-106 investigation (static only — no build/runtime access in this worktree, see note below):** checked the two most D209-shaped candidates for a puppet Y-position aliasing bug and RULED OUT both. (1) `chrSpawnAtPad`/`chrSpawnAtCoord`/`chrAdjustPosForSpawn` (`src/game/chraction.c:10653-10794`) — the puppet-spawn path a cutscene `guard_play_animation`-style AI cmd would use. `PadRecord.stan` (`src/bondtypes.h:1744-1751`) is a ROM-serialized *pointer* field (`StandTile *stan` at offset 0x28) — exactly the tail-pointer shape D122/D126/D132 warn about — and `tools_pc/d88_emit.py`'s `emit_pad()` zeroes it on conversion with a comment claiming it's "dead-on-load, always set before use." **Verified this claim is TRUE, not a converter bug**: every `PadRecord` literal in the N64 source asset tables (checked `assets/obseg/setup/UsetupdamZ.c:37-51`) initialises `stan` to the literal `0` — the ROM binary never carries a live pointer there on N64 either, so zeroing it on PC is byte-identical behaviour, not a regression. `chrAdjustPosForSpawn` receiving a NULL seed `StandTile*` is therefore the original game's normal case, not a port defect. (2) The anim-root-motion Y-accumulation chain (`modelTickAnim`→`modelSetAnimFrame2WithChrStuff`, `model.c:3060+`, `pos24 = pos34 + rotate(pos)` at `model.c:3322`) was already exhaustively audited for exactly this class of bug during D193/D209 (M-80/M-81) and found self-consistent, with the `padding[]`-union sweep that found D209/D210 explicitly noting `act_anim`/`act_dead` (the union arms active during a played-animation/dead puppet) are "layout-stable" (`porting-notes.md` §A, D210 entry) — i.e. that sweep already covers the cutscene-puppet actiontype, and it came back clean. So the two most probable D209-style aliasing sites for this specific symptom are both cold. **Did not find the actual root cause.** Did not get to: the *separate* Cuba end-credits case (`front.c` `init_menu18_displaycast`/`constructor_menu18_displaycast`, `front.c:7821-8320`+ — a **different**, single-actor "cast roster" display model shared by the intro roster and the credits roster, using `getsuboffset`/`subcalcpos`/`cast_rootpos_smoothed` root-motion smoothing, not the in-level chr path at all) — spot-checked `getsuboffset` (`model.c:684-700`) and it is `#MATCH`-verified clean, but did not trace the smoothing math or confirm this is even the code path the "JB above Natalya" report hits (that report implies two actors on screen at once, which this single-`cast_model` code doesn't obviously support — may be a distinct, not-yet-located two-actor cutscene-puppet path). **Confidence: LOW-MEDIUM that this is the D209-style struct-aliasing family at all** — the two most likely aliasing sites check out clean, which argues *against* the shared-root-cause theory for D173 specifically (unlike D160, where the analogous check also came back clean but for a different reason — no pointer fields to alias in the first place). Next investigator: get a live Cradle (`-level_41`) capture of Trevelyan's chr during the death sequence with a position-logging probe (none shipped yet — would need a new `#ifdef PORT` env-gated trace, not added this session per the no-build-verification constraint), and separately locate the actual two-actor Cuba credits code path (grep for wherever `intro_char_table`/cast display is invoked with two simultaneous models, if it exists — not found this session). **M-141: no new lead this session** (see D243's M-141 entry) — checked whether D243's stale-memory front-end/menu bug could share a mechanism with this puppet-position bug; no code-level link found, kept as an unconfirmed hypothesis to watch for during the next live cutscene capture, not a new suspect to chase on its own. **M-141: Steam Deck playtest confirmation** — user reports Bond floating at level start on both Dam and Facility ("chemical plant"), "but fine when it moves to first person" (matches this row's own framing exactly: player spawn/first-person is correct, only the third-person render-side puppet floats). No new mechanism; corroborates the bug is general across levels, not Dam-specific. **User confirms D292** (Bond sunk into the floor on death) **is the same underlying bug**, a third instance alongside level-start floating and the Cradle cutscene spin — see D292 for the consolidated cross-reference. **M-145 (see D243):** the Dam end-cutscene double-Bond + camera shake is now traced to the same family — the exit script moves Bond's own third-person model vLine truncated
**M-160/M-164/M-165 (2026-09-17, see D243): the shared mechanism is now understood in much more depth, though still not confirmed as the actual PC/N64 divergence.** D243's investigation this session traced the general pattern this whole family plausibly shares: `chrUpdateAnim` (`chr.c:2398-2424`) doesn't move a puppet's world position directly — it advances whatever animation is currently attached (`modelTickAnim`), then reads the model's root-joint transform back into `prop->pos` via `getsuboffset` (`model.c:684`). When something else (a teleport, a spawn, a death transition) moves the puppet's *logical* position without also resetting/updating its *animation state* to match, the next `chrUpdateAnim` call overwrites the new position with wherever the stale animation's root motion happens to be — producing exactly "floats/sinks/shakes relative to where it should be, in a way that tracks the animation, not the intended position." This is a strong candidate mechanism for D173's level-start float (an animation not yet settled/attached correctly at spawn) and D292's death-sink (the death-pose transition possibly not resetting the model's root anchor the way the collision/death logic expects) — **but D243's own parallel investigation (M-165) found this same mechanism may be entirely decomp-faithful**, with the actual PC-specific divergence being *which phase* of an animation a chr happens to be on at the moment of transition (inherited from real-time-dependent prior gameplay, not deterministic) rather than a code-path difference. **Do not treat this as solved** — it reframes what to look for (an animation-identity/phase mismatch at the transition moment, not a position-write bug per se) and gives a concrete technique (`GE_D193A`'s `aidx=` reverse-resolve + a `model->animframe1` phase read, see D243 M-166) for whoever gets live access to test D173/D292 the same way D243's `GE_D243M`/`GE_D243X2` probes now do.
## D179 — Packaged build crashes after the logos — the D43/D69 model + bg sidecars are ROM-derived and absent from any build that has no ROM (M-34, alpha-release QA).
**Packaged build crashes after the logos — the D43/D69 model + bg sidecars are ROM-derived and absent from any build that has no ROM (M-34, alpha-release QA).** The first `goldeneye-pc-port-*-win64.zip` from CI (bundle-win.sh) shows the Rare/Nintendo logos (compiled-in `assets/rarewarelogo.c`) then AVs at `0x6b157a88`/`0x70157a88` — symbolised: `modelPromoteNodeOffsetsToPointers` (`model.c`) ← `load_object_fill_header` (`objecthandler_2.c`) ← first prop/item model load. Root cause is **not** a code regression: the port loads PC-layout model geometry from `data/pcmodels-<region>/{pcmodels.bin,manifest.csv}` and stage bg/stan from `data/pccg-<region>/{pccg.bin,manifest.csv}`, both produced offline by `tools_pc/d43_emit.py` / `d69_emit.py` from the ROM (see `port/src/pcmodels.c` / `pccg.c`; `pcmodelsReserveSize` logs *"pcmodels.bin not found — model loads will fail"* and returns 0). CI has no ROM so it never runs the emit scripts, and the two `data/` dirs are (correctly) gitignored ROM-derived game data — **cannot be committed or shipped** (converted Nintendo/Rare geometry, DLs, collision, stan nav; = distributing assets). A local build with those dirs present runs clean (verified M-34: 1741 frames, `romdataInit ... mapped at 0x10000000`, `pcmodels: 512 sidecars`, `pccg: 73 sidecars`, no crash — so `0x10000000` is *not* the problem here). The `docs/building.md` sidecar-gen step was also missing entirely. **Fix = release-side, backlogged** (`docs/BACKLOG.md` → "Alpha release"): bundle the emit scripts + their committed inputs as a pure-stdlib-Python asset-prep tool the user runs once against their own ROM (~5 MB output, no MIPS toolchain). Secondary/latent: the fixed-address `VirtualAlloc((LPVOID)0x10000000)` in `romdata.c` has no working fallback (`"using heap copy — direct ROM reads will fail"` then limps into the same crash) — didn't bite M-34 but will on a machine where something occupies `0x10000000`; harden separately (reserve earliest in `main`, or retry low bases and derive all segment math from the base obtained).
@@ -11151,7 +11153,7 @@ Cross-referencing M-145's already-established architecture: `AI_TRYTeleportingCh
**Death animations are glitched — Bond is often sunk halfway into the floor (M-141, Steam Deck user playtest).** **User confirms this is the same broader "Bond's world model is positioned wrong" problem as D173** — not a new/separate mechanism, another surface of the same known-but-under-investigated bug. The umbrella is already tracked: `GRAPHICS-BACKLOG.md` D148 is explicitly "the tracking entry for the whole cutscene-reliability problem," already lists D173 (floating at level start / Cuba credits) and a Cradle instance ("Bond spins in circles" during the Trevelyan-falls cutscene) under it — findings.md's D173 entry has the fullest investigation detail (M-106's two ruled-out D209-style struct-aliasing candidates, LOW-MEDIUM confidence that class is even the right one). Nothing has actually been lost — the write-up just isn't concentrated in one place (split across `GRAPHICS-BACKLOG.md` D148/D173 and `findings.md` D173), which reads as "known but not detailed" unless you go looking. Sunk-into-floor is a third concrete instance of the family (level-start floating, cutscene spin, now death-pose sinking) — worth keeping as one thread when it's next investigated live, since a single root cause (most likely the render-side puppet/joint transform, not collision) could explain all three.
**Status (from §F table):** OPEN — same status as D173 (observed, not root-caused). Cross-ref D173/D148 as one investigation thread, not three separate bugs, next time someone has a live session to chase it.
**Status (from §F table):** OPEN — same status as D173 (observed, not root-caused). Cross-ref D173/D148 as one investigation thread, not three separate bugs, next time someone has a live session to chase it. **2026-09-17 addendum (see D173's M-160/M-164/M-165 note, and D243's own entry):** the D243 abseil-cutscene investigation this session found a well-evidenced general mechanism for this whole family — `chrUpdateAnim` reads a puppet's model-root position back into its logical position after advancing whatever animation is attached, so a transition (teleport/spawn/death) that doesn't also update the animation state produces exactly this "position lags/diverges from the animation" symptom. Not confirmed as D292's actual cause (needs its own live capture), but worth trying the same `GE_D193A`-style `aidx=`/`animframe=` technique (D243 M-166) on a death-sequence capture before assuming a new mechanism.
## D293 — QoL ask: no discoverable way to quit the game from the UI (M-141, Steam Deck user playtest — "couldn't see a way to exit the game. Maybe build this into the…