D243 M-162..M-166: corrected decisive experiment + deep root-cause tracing

Two third-party reviews caught a real flaw in the earlier M-161 negative
experiment: it restored prop->pos AFTER chrTick() returned, but
render_pos/field_488.pos are computed INSIDE that same call -- so M-161's
"no change" result never actually tested M-160's overwrite hypothesis.
Verified this directly against the capture data (a clean period-4
same-frame before/after-chrTick offset proves the lane-advance happens
entirely inside chrTick) before accepting the review.

M-162: corrected save/restore placement (chr.c), Z-only. Live playtest
confirmed the mechanism -- Z went smooth in the log -- but the visible
glitch persisted because that capture's chr cycled on Y instead.

M-163: widened the experiment to the whole prop->pos vector. Built and
smoke-tested; not yet live-playtested (exe was busy/user stepped away) --
this is the ready-to-test build for the next session.

M-164/M-165/M-166 (static tracing, no build needed): chrUpdateAnim reads
the model's root-joint position back into prop->pos after advancing
whatever animation is attached (getsuboffset) -- not an arbitrary
overwrite. The cutscene's teleport (AI_TRYTeleportingChrToPad) re-anchors
the root joint but never touches animation state; the real rappel
animation commands target a separate invisible driver chr (M-145), not
the visible one. Traced the Dam exit script (UsetupdamZ.c) directly and
found no animation-set command for Bond anywhere in it -- his head
animation gets forced back to an idle/walk loop by
bondviewFrozenMoveBond's own tick, but the *phase* within that loop is
inherited, not reset. This raises a real possibility that the mechanism
is decomp-faithful and the actual PC/N64 divergence is upstream of the
cutscene code entirely (which animation phase Bond happens to be on when
the cutscene grabs him). Extended D243M: onscreen with aidx=/animframe=
(reusing GE_D193A's reverse-resolve technique) so the next live capture
can test this directly.

Docs updated throughout (findings.md, findings-index.csv,
GE-ENV-PROBES.md); HANDOFF.md refreshed with full session state (local,
gitignored).
This commit is contained in:
James Dansereau committed 2026-09-17 12:49:19 -04:00
1 parent fec396f53b
commit d9c7705654
4 files changed
+113 -6

No files matched your search

+2 -1
View File
@@ -45,7 +45,8 @@ Two classes:
| `GE_D160` | `src/boss.c:744`, `src/game/bondview2.c:791`, `src/aicommands.def:10055,10181,10236,10242,10247` (all `#ifdef PORT`) | Dam exit-cutscene (D148/D160) diagnostic: trace points in `bossReturnTitleStage`, `bondviewSetCameraMode`, and AI cmds `EndLevel`/`exit_level`/`CameraLookAtBondFromPad`/`CameraSwitch`. **Investigation in progress** — user owes a `GE_D160=1` Dam run. | **live** |
| `GE_D243` | `src/game/front.c` (`menu_init`, cached `s_d243`) | Per-menu-transition trace with a local per-tick frame counter (D243 stale-DL-burst screen identification). Counter is NOT numerically identical to the port's internal frame count — cross-reference by elapsed offset. | **live** (D243) |
| `GE_D243CAM` | `src/game/bondview2.c` (`bondviewFrozenCameraTick`, three `CAMERAMODE_POSEND` branches) | Dumps eye/look-at positions (+theta/verta on the `gBondViewCutscene` branch, +dt/angle/pad on the orbit branch) per call. **Found M-143**: the `gBondViewCutscene` branch fires and its look-at (`field_3C4/8/C`) sweeps through a filter catch-up after the cutscene warp — the shake mechanism. | **live** (D243) |
| `GE_D243M` | `src/game/bondview2.c` (`solo_char_load`, `bondviewRemovePlayerBody`, `playerTick`; cached `d243mEnabled`) + `src/game/objecthandler.c` (`drawjointlist`, both region variants) + `src/game/chr.c` (`chrTick`, `after_position_update:`) | M-151/M-154/M-159 probe for the Dam-abseil "frozen Bonds + shake": `D243M: CREATE/REMOVE` at both `bodyModel` sites; `D243M: tick` (idx/model/**propptr/chrptr**/cam modes/`prop->pos`/`field_488.pos`/`field_3B8`/`field_3C4-8-C`/**rp** = render_pos pointer, **never dereferenced** — M-154 fix 2: tick-time `render_pos` holds arbitrary stale slot contents until the first draw pass, so the pre-view root translation is logged by `chrdraw` only) while the model exists or POSEND/INTRO is active; `D243M: draw` per on-screen player render submission; `D243M: chrdraw` — M-154 per-frame model-draw census, one line per CHR render submission (Model* + raw root translation) while a scripted camera mode (POSEND/INTRO/SWIRL/FADESWIRL) is active; a second Bond instance = extra lines with *distinct* model pointers at the same frame (same model is drawn twice/frame — two passes — dedupe by (frame, model)); `D243M: onscreen` (M-159, `chr.c`) — one line per `chrTick` call while the probe is active: `vis=` `posIsOnScreen`'s result (the gate that controls whether `render_pos` refreshes that tick) + the live `prop->pos`, to test whether freeze/teleport boundaries in the tick/chrdraw data line up with `vis` flipping 0→1. Silent during FPS play. Note: `field_3B8` x/z read at 10× world units in the smoke capture — not plain world position. | **live** (D243) |
| `GE_D243M` | `src/game/bondview2.c` (`solo_char_load`, `bondviewRemovePlayerBody`, `playerTick`; cached `d243mEnabled`) + `src/game/objecthandler.c` (`drawjointlist`, both region variants) + `src/game/chr.c` (`chrTick`, `after_position_update:`) | M-151/M-154/M-159 probe for the Dam-abseil "frozen Bonds + shake": `D243M: CREATE/REMOVE` at both `bodyModel` sites; `D243M: tick` (idx/model/**propptr/chrptr**/cam modes/`prop->pos`/`field_488.pos`/`field_3B8`/`field_3C4-8-C`/**rp** = render_pos pointer, **never dereferenced** — M-154 fix 2: tick-time `render_pos` holds arbitrary stale slot contents until the first draw pass, so the pre-view root translation is logged by `chrdraw` only) while the model exists or POSEND/INTRO is active; `D243M: draw` per on-screen player render submission; `D243M: chrdraw` — M-154 per-frame model-draw census, one line per CHR render submission (Model* + raw root translation) while a scripted camera mode (POSEND/INTRO/SWIRL/FADESWIRL) is active; a second Bond instance = extra lines with *distinct* model pointers at the same frame (same model is drawn twice/frame — two passes — dedupe by (frame, model)); `D243M: onscreen` (M-159/M-162/M-163/M-166, `chr.c`) — one line per `chrTick` call while the probe is active: `vis=` `posIsOnScreen`'s result (M-159's frustum hypothesis, REFUTED by M-160) + the live `prop->pos` + `actiontype=`/`anim=` (M-160/M-164: which of `chrTick`'s branches fired, the attached-animation pointer) + `aidx=`/`animframe=` (M-166: the animation reverse-resolved to its `animation_table_ptrs1` index, GE_D193A's technique, + its current playback phase — tests whether the visible chr's animation *phase* at cutscene-entry, not just its identity, is what differs from N64) + `x2active=`/`x2raw=` (M-162/M-163, gated on `GE_D243X2`: whether the decisive save/restore experiment ran this tick, and the raw pre-restore position it overrode — the whole `prop->pos` vector as of M-163, not just Z). Silent during FPS play, silent on the `GE_D243X2` fields unless that env var is also set. Note: `field_3B8` x/z read at 10× world units in the smoke capture — not plain world position. | **live** (D243) |
| `GE_D243X2` | `src/game/chr.c` (`chrTick`, gated additionally on `d243mProbeActive()`) | **Not a probe — a decisive behavioral experiment, off by default, NOT a fix.** M-162/M-163: saves `prop->pos` right before `chrTick`'s position-update dispatch (`chr.c:2541-2617`) runs, restores it at `after_position_update:` — before the render-matrix computation later in the same tick can see the cycled value (unlike M-161, which restored too late to have any effect). Tests whether `chrTick`'s own animation-position write (M-160/M-164) is what produces the Dam-abseil shake. M-162 was Z-only (confirmed the mechanism on that axis, but the visible glitch persisted because that capture's chr cycled on Y instead); M-163 widened it to the whole vector. Always pair with `GE_D243M=1` so the `x2active=`/`x2raw=` fields on `D243M: onscreen` show whether/what it overrode — judge by those numbers, not by eye (a lesson from M-161's inconclusive-by-eye negative). Revert once the experiment reports; do not ship. | **live, test-only** (D243) |
| `GE_D193` | `src/game/frametiming.c` (`waitForNextFrame`, `#ifdef PORT`) | Per-wall-second line: `render=` rendered frames, `sim=` sim ticks delivered (Σ of the `deltaFrames`/`g_ClockTimer` fed downstream), `clamped=` frames whose catch-up hit `FRAMETIMING_PORT_MAX_CATCHUP`, `maxraw=` largest pre-clamp delta. Healthy steady state = `render=30 sim=60 clamped=0 maxraw=2` (measured M-80, all levels idle). Use to check whether the wall-clock timer under-advances under real AI load (D193). Cheap; safe for a full playtest. | **live** (D193) |
| `GE_D193A` | `src/game/chr.c` (`chrTick` → `d193aSample`, plus `d193aMoved` in `chrUpdateAnim`; `#ifdef PORT`) | Per-wall-second per-ticked-chr locomotion telemetry (D193/D209): `chr=` chrnum, `act=` ACT_TYPE, `speed=` world-units travelled/s, `gtd=` g_GlobalTimerDelta, `tier=` `act_gopos.unk59` SPEED tier (0 walk / 1 run / 2 sprint; `-1` when not ACT_GOPOS), `gspd=` `act_gopos.speed` (**a turn rate, not a travel rate** — 0 means running straight), `typ=` PROP_TYPE (3=CHR, 6=VIEWER), `tick=`/`move=`/`frz=` chrTick entries vs `chrUpdateAnim` calls vs freeze-gated (move « tick = the chr is being visibility-culled out of its own locomotion; `move=0` at high `speed` = WAYMODE_MAGIC), `hid=` CHRFLAG_HIDDEN, then the root-motion scalars `scale` / `xlscale` / `animrate` / `playspeed` / `mspeed` (model->speed) / `endframe` / `anim` ptr / `aidx=` that pointer reverse-resolved to its `animation_table_ptrs1` index (40 walking, 41 sprinting, 42 running, 107 walking_unarmed — map via `src/game/initanitable.c`). `GE_D193A_CHR=<n>` restricts to one chrnum. **This probe found D209**: Cradle showed `tier=1` (RUN) with `aidx=40/107` (walk anims) on every sample. | **live** (D193/D209) |
| `GE_D193B` | `src/game/model.c` (`sub_GAME_7F06D3F4`, `#ifdef PORT`) | Rate-limited (1/97) raw anim root-motion decode trace (D193): `joint=` / `flip=` / `base=` mtx channel index / `frame=` / `tmp=` decoded s16 translation triple from the anim bitstream / `angle=` / `anim` ptr / `bd=`+`bs=` the D32 u32 bitDescriptors/bitStream addresses / `njoints`. M-80 Facility: `base=0`, `angle=0` **always** (root-motion facing delta never non-zero — top lead), `tmp` ≈ (±small, ~1086 hip-height, ±small). Compare `tmp`/`angle` magnitudes against a clean N64 decomp build of the same anim+frame. | **live** (D193) |
+1 -1
View File
@@ -139,7 +139,7 @@ D239,?,"QoL ask (M-106, user QA):",CLOSED — executed in the v0.2.0 prep pass (
D240,OPEN,"Player gunshot SFX timing/cadence reportedly does not match the N64 original's rate (M-106, user QA report).","OPEN — not root-caused; static call-site tracing only, no runtime verification possible in this environment."
D241,OPEN,Player gunshot SFX goes silent under some conditions —,"OPEN — not newly root-caused; high confidence this is D207 reproduced, not an independent bug."
D242,?,Player-death sequence UX regression vs N64 original:,NOT A PORT-LOGIC BUG as far as static analysis can tell.
D243,FIXED,"Dam end-of-level cutscene (the abseil/bungee sequence, D148/D160's subject):","PARKED (M-161, diminishing returns after ~15 session-passes; resume only with a new lead —"
D243,OPEN,"Dam end-of-level cutscene (the abseil/bungee sequence, D148/D160's subject):","OPEN, M-166 build ready for next live session (M-163:"
D245,OPEN,IsWater water: two competing patterns with a visible seam that moves as the player looks around (mouse/aim) —,"OPEN — REOPENED, M-142 headless probe found the tc-shift k measurably flips during ordinary view rotation (new root-cause evidence); an opt-in GE_D245_FIXEDSHIFT candidate is build-verified but needs…"
D246,OPEN,"Tiny pixel strips at the left and right edges of the screen, ""like overscan"" —","OPEN — one candidate ruled out (M-116 follow-up), root cause not found."
D247,RESOLVED,Black bars top and bottom of screen —,"NOT A BUG — confirmed faithful, unmodified N64 decomp behaviour, no code change made."
1 # GENERATED by tools_pc/gen_findings_index.py -- do not hand-edit.
139 D240
140 D241
141 D242
142 D243
143 D245
144 D246
145 D247
+31 -1
View File
@@ -546,7 +546,7 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
| D240 | **Player gunshot SFX timing/cadence reportedly does not match the N64 original's rate (M-106, user QA report).** — full `## D240` entry at file tail | **OPEN — not root-caused; static call-site tracing only, no runtime verification possible in this environment.** Confidence LOW-MEDIUM that this is a *new* bug distinct from the D155/D186/D193/D204/D209 timing-keystone family (all of which gate the identical `deltaFrames→speedgraphframes→g_ClockTimer→g_GlobalTimer` chain this SFX trigger consumes).… |
| D241 | **Player gunshot SFX goes silent under some conditions — reported on Bunker with the alarm sounding, "or some other factor" — but only for PP7 and AK47, Klobb…** — full `## D241` entry at file tail | **OPEN — not newly root-caused; high confidence this is D207 reproduced, not an independent bug.** Recommend folding this repro into D207 (or closing D241 as a duplicate once D207 is reopened) rather than tracking separately.… |
| D242 | **Player-death sequence UX regression vs N64 original: PC requires an LMB click to proceed to the mission-failed/file-select screen; user recalls N64 auto-plays…** — full `## D242` entry at file tail | **NOT A PORT-LOGIC BUG as far as static analysis can tell.** Confidence HIGH that the LMB-click skip path is faithful original behavior (Z_TRIG-mapped, exists unmodified in `bondview2.c`), not a defect to remove.… |
| D243 | **Dam end-of-level cutscene (the abseil/bungee sequence, D148/D160's subject): the camera violently shakes/"spazzes" during each of the scripted camera-angle…** — full `## D243` entry at file tail | PARKED (M-161, diminishing returns after ~15 session-passes; resume only with a new lead — see below) — M-144: CONFIRMED PC-only (user, direct N64 comparison) — real N64 does not show this shake. Mechanism (M-143): the `gBondViewCutscene` look-at branch reads `field_3C4/8/C`, a leaky-integrator low-pass filter of Bond's real position that isn't reset when the scripted cutscene warps him, producing a ~1s look-at snap. Filter math is decomp-exact and `g_ClockTimer`-scaled, so the bug must be upstream: either the position warp itself is wrong/bigger on PC, or a call-ordering desync around the `CAMERAMODE_INTRO` transition. M-153: live `GE_D243M` capture (full Dam → abseil; `scratch/d243/m153_dam_abseil_capture.log`) REFUTES the double-instance hypothesis (single model, one draw/frame, no remove/recreate window) and shows the real divergence: the model's rendered position (`field_488.pos` = render readback) freezes on dam-surface points then locks into a strict period-4 cycle through four fixed world points, while `prop->pos` executes the smooth scripted void sweep — the lagged filter (`field_3C4`) chasing that cycle is exactly the observed shake. Next: code dive into `chrTick`→`render_pos` for what produces the four fixed points; D173/D292 are the same family. D146 still fully decoupled (zero hits, 4 runs). M-154: user sharpened the symptom (one new frozen Bond per shot; old copies persist); log re-read corrects M-153 — in phase 3 `prop->pos` itself cycles A,A,B,C through three z-lanes while y falls smoothly, and the rendered model tracks it (per-lane pose offsets), so it teleports every frame rather than freezing; H1 (multiple Model instances) vs H2 (framebuffer accumulation / subcam ghosts) now discriminated by a new `D243M: chrdraw` per-frame model-draw census in `drawjointlist` + extended tick fields (propptr/chrptr/rp); probe crashed twice inside its own `render_pos` read (stale slot contents, not a uniform tombstone) — final fix: tick probe never dereferences render_pos (raw= moved to chrdraw-only where the game guarantees validity); awaiting re-capture. M-159 (static code-dive, no build): proposed `chrTick`'s frustum-visibility gate as the mechanism — REFUTED by M-160's live capture (`vis=1` throughout the observed freeze). M-160 (live `D243M: onscreen` capture, user playtest): found `chrTick` overwriting `prop->pos` with a stale/stepped value every tick via its own `chrUpdateAnim`/`modelTickAnim` animation-position logic (`chr.c:2578-2616`, no POSEND/cutscene check), downstream of and competing with the AI script's smooth write to the same field. **M-161 (decisive experiment, live playtest): NEGATIVE.** Neutralizing M-160's overwrite (save/restore `prop->pos` around `chrTick` during POSEND, `GE_D243X` env-gated hack, reverted after) produced **no visible change** — user: "still happened, looked the same as it always does." M-160's mechanism is real but is not the (or not the whole) visible cause. **Parked** per user's call (diminishing returns after ~15 session-passes) — see D148 umbrella; resume only with a specific new lead. |
| D243 | **Dam end-of-level cutscene (the abseil/bungee sequence, D148/D160's subject): the camera violently shakes/"spazzes" during each of the scripted camera-angle…** — full `## D243` entry at file tail | OPEN, M-166 build ready for next live session (M-163: full-vector suppression built/smoke-tested, awaiting a live playtest verdict; M-164/M-165/M-166 static work reframed the open question as "is the visible chr's inherited animation *phase* at cutscene-entry PC/N64-divergent" — not yet answerable without a live capture; M-166 extended the probe with `aidx=`/`animframe=` so one more playtest can answer it) — M-144: CONFIRMED PC-only (user, direct N64 comparison) — real N64 does not show this shake. Mechanism (M-143): the `gBondViewCutscene` look-at branch reads `field_3C4/8/C`, a leaky-integrator low-pass filter of Bond's real position that isn't reset when the scripted cutscene warps him, producing a ~1s look-at snap. Filter math is decomp-exact and `g_ClockTimer`-scaled, so the bug must be upstream: either the position warp itself is wrong/bigger on PC, or a call-ordering desync around the `CAMERAMODE_INTRO` transition. M-153: live `GE_D243M` capture (full Dam → abseil; `scratch/d243/m153_dam_abseil_capture.log`) REFUTES the double-instance hypothesis (single model, one draw/frame, no remove/recreate window) and shows the real divergence: the model's rendered position (`field_488.pos` = render readback) freezes on dam-surface points then locks into a strict period-4 cycle through four fixed world points, while `prop->pos` executes the smooth scripted void sweep — the lagged filter (`field_3C4`) chasing that cycle is exactly the observed shake. Next: code dive into `chrTick`→`render_pos` for what produces the four fixed points; D173/D292 are the same family. D146 still fully decoupled (zero hits, 4 runs). M-154: user sharpened the symptom (one new frozen Bond per shot; old copies persist); log re-read corrects M-153 — in phase 3 `prop->pos` itself cycles A,A,B,C through three z-lanes while y falls smoothly, and the rendered model tracks it (per-lane pose offsets), so it teleports every frame rather than freezing; H1 (multiple Model instances) vs H2 (framebuffer accumulation / subcam ghosts) now discriminated by a new `D243M: chrdraw` per-frame model-draw census in `drawjointlist` + extended tick fields (propptr/chrptr/rp); probe crashed twice inside its own `render_pos` read (stale slot contents, not a uniform tombstone) — final fix: tick probe never dereferences render_pos (raw= moved to chrdraw-only where the game guarantees validity); awaiting re-capture. M-159 (static code-dive, no build): proposed `chrTick`'s frustum-visibility gate as the mechanism — REFUTED by M-160's live capture (`vis=1` throughout the observed freeze). M-160 (live `D243M: onscreen` capture, user playtest): found `chrTick` overwriting `prop->pos` with a stale/stepped value every tick via its own `chrUpdateAnim`/`modelTickAnim` animation-position logic (`chr.c:2578-2616`, no POSEND/cutscene check), downstream of and competing with the AI script's smooth write to the same field. **M-161 (decisive experiment, live playtest): NEGATIVE.** Neutralizing M-160's overwrite (save/restore `prop->pos` around `chrTick` during POSEND, `GE_D243X` env-gated hack, reverted after) produced **no visible change** — user: "still happened, looked the same as it always does." M-160's mechanism is real but is not the (or not the whole) visible cause. **Parked** per user's call (diminishing returns after ~15 session-passes) — see D148 umbrella; resume only with a specific new lead. |
| D245 | **IsWater water: two competing patterns with a visible seam that moves as the player looks around (mouse/aim) — "looks almost exactly like skybox" (M-116, user…** — full `## D245` entry at file tail | OPEN — REOPENED, M-142 headless probe found the tc-shift `k` measurably flips during ordinary view rotation (new root-cause evidence); an opt-in `GE_D245_FIXEDSHIFT` candidate is build-verified but needs a live A/B, not shipped as default.… |
| D246 | **Tiny pixel strips at the left and right edges of the screen, "like overscan" — look like raw pixels, not 3D graphics (M-116, user QA report).** — full `## D246` entry at file tail | **OPEN — one candidate ruled out (M-116 follow-up), root cause not found.** Step (1) from the original plan is done… |
| D247 | **Black bars top and bottom of screen — possible aspect-ratio defect (M-116, user QA report).** — full `## D247` entry at file tail | **NOT A BUG — confirmed faithful, unmodified N64 decomp behaviour, no code change made.** `GE_PCDUMP` captures (both against the pre-existing save and a fresh-EEPROM run, to rule out a stale `Screen` option from earlier test sessions) show the exact same inset on Frigate… |
@@ -10919,6 +10919,36 @@ if that's recorded anywhere in the D280 write-up above.
**Status assessment after M-161:** this bug has now had ~15 session-passes (M-107 through M-161) across multiple sessions without a landed fix, each pass narrowing the mechanism further without closing it. Per the user's own call this session (diminishing returns, "going at this without much luck for a while"), **recommend parking D243 under the D148 umbrella** (general cutscene-bug tracking entry, `docs/dev/GRAPHICS-BACKLOG.md`) rather than continuing further open-ended diagnostic passes, unless a specific new lead or live capture surfaces. The mechanism knowledge gained (M-143's filter, M-145's teleport architecture, M-160's competing-writer bug) remains valid and should inform any *future* pass — this is a park, not a reset — but the next session should default to other backlog items unless the user explicitly wants another D243 cycle.
**UNPARKED same session: a third-party review found a real methodological flaw in M-161, and the corrected re-test (M-162) produced a genuinely new, decisive result — see below.**
**M-162 (2026-09-17, same session, after a second third-party review): M-161's negative result was invalid — the restore was placed AFTER `chrTick()` returned, but `render_pos`/`field_488.pos` are computed INSIDE that same call, from whatever `prop->pos` was at that point. So M-161 never actually prevented the stale value from reaching the render.** Verified directly (not just accepted from the review): compared `D243M: tick`'s pre-`chrTick` z-read against `D243M: onscreen`'s post-`chrTick` z-read for the **identical frame number** across the cycling window (`m160_dam_abseil_onscreen_capture.log`, frames 9600-9611) — the pattern is a clean, deterministic period-4 offset applied *within* the same tick: `-4.0, +543.8, +305.5, -855.2`, repeating exactly. This proves the lane-advance happens **inside** `chrTick`, every tick, unconditionally — the strongest evidence yet for M-160's mechanism.
Corrected the experiment: added `d243x2SavedPos`/`d243x2Active` (top-of-function locals, `chr.c:2451-2453`) — save `prop->pos.f[2]` (Z only, since M-160's capture showed X stable and Y the smooth AI-script descent) right before the `chrTick` position-update dispatch (`chr.c:2541-2617`, inside the `CHRFLAG_HIDDEN`-else block), restore it at `after_position_update:` — **before** the `D243M: onscreen` log line and before anything else in the tick can see the cycled value, unlike M-161. Also extended the probe with `actiontype=`/`anim=` (which of `chrTick`'s branches fired, model's current animation pointer) and `x2active=`/`x2rawz=` (whether suppression ran, and the raw cycled Z it overrode) so the result could be read from the log, not just judged by eye — per the reviewer's explicit "bake this in or risk another inconclusive negative" advice. Gated `GE_D243X2`, `#ifdef PORT`. Compiled clean, linked, 37,823-line bare-boot smoke test with zero crashes.
**Live playtest result: MIXED — confirms the mechanism, but reveals the fix (as scoped) was incomplete.** User played two full Dam runs with `GE_D243M=1 GE_D243X2=1`; visible glitch looked "about the same" both times. But the log (`scratch/d243/m162_dam_abseil_playtest.log`, second abseil CREATE at frame 11878) shows the suppression **worked exactly as designed this time**: `x2rawz` still shows the same violent period-4 Z-lane cycling (e.g. frames 12100-12130: raw z jumping between ≈-3111, ≈-2500-2570, ≈-1930-2260), but the final rendered `pos.z` is now smooth and monotonic (-2227.6 → -3111.6 → -3107.6 → ... declining ~4 units/frame, no lane jumps at all) — the Z suppression genuinely neutralized the Z-axis cycling this time, unlike M-161.
**But `pos.y` is violently cycling instead, completely untouched** (same window: `176.2 → -1174.6 → 175.6 → 176.2` repeating, amplitude ~1350 units, with an early transition spike to -12823.6) — this run's chr logged `actiontype=3` (not logged in the original M-160 capture, so no direct comparison, but evidently a different branch/state than whatever produced M-160's "Y descends smoothly, Z cycles" pattern). **This fully explains the unchanged visible glitch**: the Z-only suppression fixed exactly the axis that wasn't dominant in this particular playthrough. The underlying mechanism (chrTick overwriting `prop->pos` with a cycling value every tick, independent of any external input) is now confirmed on a second axis too — not refuted, just incompletely tested.
**Next (M-163, in progress): extend the suppression to the whole `prop->pos` vector** (not just Z) to test whether stopping cycling on every axis finally kills the visible shake. This will also freeze whatever legitimate motion exists (accepted for a decisive test, not viable as a real fix — see the M-162 code comment). If positive: the mechanism is airtight-confirmed, and the real work becomes root-causing *why* this decomp-faithful write path emits cycling values on PC (candidates per M-154/M-160: an attached keyframe animation without interpolation, a pad-table lookup, an actiontype/POSEND gate the port isn't honoring — `chr->actiontype`/`model->anim` are now logged and should narrow this). If the shake persists even with the whole vector pinned: the mechanism, while real, still isn't the (full) visible cause, and D243 goes back to parked with this ruled out more completely than M-161 managed.
**Both third-party reviews net assessment:** the first (local Qwen `triage` agent) made one fabricated/confused claim (conflating `g_CameraMode` with a same-numbered `subcam` flag) that I verified and refuted directly against capture data before acting on it — see the now-superseded framing above. The second (unspecified third-party agent) made a data-grounded, directly-verified, and ultimately correct critique of M-161's methodology that materially advanced the investigation. Both were checked against real captures before being trusted, per this project's own standing discipline (`docs/porting-notes.md` §E: verify a cited scratch/log actually contains what a claim says before trusting it) — worth noting as a working example of that discipline paying off in both directions (catching a wrong claim, and correctly accepting a right one).
**M-164 (2026-09-17, same session, static-only — no build, while the exe was locked by the user's own playtest): a complete mechanical theory tying M-145/M-154/M-160/M-162 together, naming a specific fix candidate.** M-162's capture logged `actiontype=3` for the visible Bond chr during the cycling — per `bondconstants.h:3945-3962`'s `ACT_TYPE` enum (`ACT_INIT`=0, `ACT_STAND`=1, `ACT_KNEEL`=2, `ACT_ANIM`=3), this is **`ACT_ANIM`**, one of the three branches M-160 traced the overwrite to (`chr.c:2578`: `else if ((chr->actiontype == ACT_ANIM) && ...)`, calling `chrUpdateAnim`). Traced `chrUpdateAnim` itself (`chr.c:2398-2424`): it is not an arbitrary overwrite — it calls `modelTickAnim` (advance the currently-attached animation), `subcalcpos` (recompute joint world transforms from that animation), then `getsuboffset(model, &prop->pos)` (`model.c:684`, `getpartoffset(objinst, objinst->obj->RootNode, offset)`) — i.e. it **faithfully reads the model's root-joint world position back into `prop->pos`**, which is exactly what this function is supposed to do for a normally-animating character. The "overwrite" is `chrUpdateAnim` doing its ordinary job on a chr whose animation state was never told about the cutscene.
Cross-referencing M-145's already-established architecture: `AI_TRYTeleportingChrToPad` (`chrai.c:4064-4119`, the `CHR_BOND_CINEMA` mechanism) writes `chr->prop->pos` **and** calls `setsubroty`/`setsuboffset(chr->model, &pos)` (`chrai.c:4105-4106`) — so the model's root-joint anchor genuinely is re-anchored to the new pad position at each teleport, confirmed by direct code read. **But nothing in that teleport touches `chr->act_anim`/`model->anim`.** M-145 already established that the actual rappel/exit `guard_play_animation` commands run on a separate, invisible "false GUARD" driver chr (`alloc_false_GUARDdata_to_exec_global_action`), not this visible one. **Putting these together: the visible Bond chr keeps ticking whatever animation it already had equipped from before the cutscene hijacked its position** (a locomotion/idle loop, going by `ACT_ANIM` + a real `model->anim` pointer being logged) — every tick, `chrUpdateAnim` advances that stale animation and reads its own root-motion cycle back into `prop->pos`, anchored at wherever the last teleport left the root joint. A short-period root-motion track (a walk-in-place or idle-sway loop) read back on top of a fixed anchor produces exactly the observed "period-4 cycling in place" — mechanically explaining M-153/M-154's lane pattern and M-162's Y-axis finding as two faces of the same thing (whichever axis that specific animation's root motion moves on).
**This reframes M-162/M-163's suppression experiments correctly: they are not "randomly neutralizing a bug," they are directly testing this exact theory** (block the stale-animation readback from reaching the render, see if the shake stops) — a positive M-163 result would be strong additional confirmation, not merely "the write stops," of this complete mechanism. **The real fix candidate this points to (not yet attempted, needs its own investigation pass):** find where/whether the cutscene AI script is supposed to change `chr->actiontype`/`chr->act_anim` (or otherwise silence `chrUpdateAnim`'s position write) for the *visible* chr when `AI_TRYTeleportingChrToPad` fires — the decomp symbol for `guard_play_animation` referenced in M-145 was not located this pass (grepped, no match for that exact name — likely a different actual symbol in `bondaicommands.c`/`aicommands2.c`; the AI command name is probably decoded/human-friendly, not literal). If N64 has a code path that either (a) redirects that animation command to the *visible* chr instead of the false-GUARD driver, or (b) sets `noTranslate`/freezes root motion on the visible chr during POSEND, and PC is silently skipping it — that is the actual bug, likely bucket (a)/(b) per the diagnosis framework, not a game-logic difference. **Next:** locate the real `guard_play_animation`/animation-assignment AI command handler and trace whether it's meant to target the chr that `AI_TRYTeleportingChrToPad` just moved.
**M-165 (2026-09-17, same session, static-only, continuing while the exe was locked): found the animation-command handler M-164 flagged as unlocated — it confirms the "wrong chr" targeting is a structural, likely decomp-faithful property of this AI-script design, which reframes where the real PC/N64 divergence must be.** `check_if_able_to_then_perform_animation` (`chraction.c:10263`, called from both `chrai.c:1084` and `aicommands.def:750`) is passed `ChrEntityp` — the AI list's own driver chr — as its `self`/target, not a resolved `CHR_NUM` lookup. Per M-145, the abseil's AI list runs on the invisible false-GUARD driver (`alloc_false_GUARDdata_to_exec_global_action`), so this command (and by extension `guard_play_animation`) **structurally can never reach the visible Bond chr `AI_TRYTeleportingChrToPad` teleports** — this is how the script is written, and since both are byte-identical decomp code, this mismatch is almost certainly present on N64 too, not a PC-only defect. Also checked whether any game-code path gates the visible chr's own `chrTick` animation dispatch during a scripted camera mode: grepped `chr.c` for `CAMERAMODE_POSEND`/`CAMERAMODE_INTRO` (zero hits — `chr.c` has no camera-mode awareness at all) and checked `PLAYERFLAG_NOCONTROL` (set by `AI_BondDisableControl`, `chrai.c:4040`) — it only drives HUD/UI display (`bondviewSetUpperTextDisplayFlag`, `hudmsgsSetOn`, `countdownTimerSetVisible`), never referenced in `chr.c`/`chraction.c`'s position-update path. **There is no game-code mechanism anywhere that suppresses the visible chr's ordinary locomotion-animation tick during a cutscene** — `chrTick` runs its normal dispatch on the player's chr throughout POSEND regardless.
**This reframes the open question, honestly: if the "wrong-chr animation targeting" and "no cutscene suppression" are both decomp-faithful (high confidence, direct code reads, not conjecture), then the mechanism itself may be completely harmless on N64 — simply because N64's chr happens to have a near-static animation attached (e.g. an idle stand pose with negligible root motion) at the exact moment the cutscene grabs it, while PC's chr has ended up with a different, more mobile animation attached due to some earlier, unrelated divergence in animation-state history** (input timing, dt/tick-count differences, or a genuinely separate bug upstream of the cutscene entirely) — not a bug in the cutscene/teleport code itself. This is a real, open possibility that M-160 through M-164's investigation has not yet ruled in or out, and would require either (a) knowing what animation SHOULD be attached at this moment (checking `ai_24`'s auto-walk-off-the-edge trigger, `chrai.c` — does it explicitly set a specific animation via `chrUpdateAnim`/`modelSetAnimation` as Bond is walked off the ledge, making it deterministic regardless of platform?), or (b) a live capture logging the actual animation ID (not just the `model->anim` pointer, which is opaque without a lookup) attached at the moment `g_CameraMode` flips to `POSEND`, cross-referenced against the animation-table index the same way `GE_D193A`'s `aidx=` field already does elsewhere in this codebase (`docs/dev/GE-ENV-PROBES.md`, `GE_D193A` row) — reusing that established technique here (reverse-resolve `model->anim` against `animation_table_ptrs1`) would let a future capture name the exact animation, not just its address, and settle whether it's a stand-still pose or something with real root motion.
**Status: genuinely open, not resolved by static reading alone.** This does not change M-162/M-163's experimental value (they still directly test whether suppressing the readback stops the visible symptom) but does mean a **positive M-163 result would not, by itself, prove this is a PC bug** — it would prove the mechanism, which M-164/M-165 have now shown could plausibly be decomp-faithful and only different in its *practical effect* (which animation happens to be attached) rather than its *code path*. Whoever picks this up next should treat M-163's live result as confirming/refuting the *mechanism*, and treat "is this actually a PC-vs-N64 divergence" as a still-separate, still-open question needing either N64 reference footage of this exact moment or the animation-ID capture described above.
**M-166 (2026-09-17, same session, while the exe stayed locked by the user's own playtest — local Qwen `triage` delegate dispatched to answer M-165's open question, findings spot-checked directly): the visible chr's animation *identity* during the level-exit walk-off is script-forced, but its *phase* is not — narrowing M-165's open question to a specific, testable claim.** Traced the Dam exit AI script directly (`assets/obseg/setup/UsetupdamZ.c`): `ai_24[]` (`:2622+`) — after `hud_hide_and_lock_controls_and_pause_mission_time`/`bond_equip_item`, calls `bond_set_locked_velocity(0x00, 0x04)` then loops on `if_bond_y_pos_less_than(0x98bd, ...)`/`if_local_timer_greater_than` until the fall completes, then `chr_hide_all` and on into the exit chain — **confirmed no animation-set command anywhere in this list** (spot-checked directly; the delegate's report cited slightly wrong hex parameters for `bond_set_locked_velocity`, `(0x0f,0xff)` vs the real `(0x00,0x04)`, a minor transcription error, but the structural claim — no animation command present — checked out on direct read). `AI_BondSetLockedVelocity` (`chrai.c:4259-4271` per the delegate, not independently re-verified this pass) only writes `g_ForceBondMoveOffset`; consumed by `bondviewFrozenMoveBond` (`bondview2.c:7868`+), which the delegate traced as calling `bondviewMoveAnimationTick(0,0,0)` → `bheadAdjustAnimation(0)` every frozen-walk frame. **Spot-checked:** `bheadAdjustAnimation` exists at `bondhead.c:396`, and `PTR_ANIM_bond_eye_walk` is a real symbol at `bondhead.c:21` (part of a breathing/head-animation table, `{PTR_ANIM_bond_eye_walk, 9.5f, 27.0f, 0.0f, 0.0f, 1.5f}`) — both confirmed to exist as cited. Per the delegate's (unverified-past-this-point) trace: at zero speed this function re-attaches `PTR_ANIM_bond_eye_walk` to the head model if it wasn't already the active animation, but computes the re-attach **startframe by phase-interpolating from whatever frame the previous animation was on** (`bondhead.c:411-416`) — i.e. the animation *identity* Bond ends up with during the fall is deterministic (always the idle/walk loop), but the exact **frame/phase** within that loop depends on real-time elapsed (`g_GlobalTimerDelta`-driven fall duration) and whatever animation state existed the instant `ai_24` grabbed control — neither guaranteed identical between N64 and PC.
**This sharpens M-165's open question into something a single targeted capture can answer.** If the visible shake tracks with animation *phase* drift (a few-frame difference in where the idle/walk loop happens to be when POSEND engages), that would explain a PC-specific divergence entirely upstream of the cutscene/teleport code, consistent with everything else being decomp-faithful. **Concrete next step, ready for the next live session:** extend the `D243M: onscreen` probe (`chr.c`) to log the animation's current frame/phase, not just the `model->anim` pointer — reuse the reverse-resolve-against-`animation_table_ptrs1` technique `GE_D193A`'s `aidx=` field already established elsewhere in this codebase (`docs/dev/GE-ENV-PROBES.md`, `GE_D193A` row) so the capture names an actual frame number, not an opaque address. This was not implemented this pass (probe-design work only, no code changed for this specific addition) — left for the next build/probe cycle alongside M-163's own live re-test.
**Status (from §F table):** **OPEN — M-109 re-analysis of the same session's raw logs corrects the timing/pattern claims above; the D134/pendingGfx race hypothesis is likely wrong.** Confidence MEDIUM on the correction, LOW-MEDIUM on the new lead. Re-reading `data/playtest_d160.log`/`_run2.log` at the `g_framesRendered` level (not just grepping for `D146`) shows the D146 burst fires **~1600-3900 frames (tens of real seconds) *after*** `bossReturnTitleStage`/the `camera_switch(7)` calls, not during them, in **both** runs — "right in the camera-cut window" and "run 1 only" are both wrong as stated above. This also weakens the D134/`pendingGfx` citation: `osSpTaskStartGo` runs `gfx_run()` synchronously and inline (`port/src/libultra.c:1232-1258`), so nothing from the cutscene's own DL submission is still in flight by the time any teardown code runs — the port doesn't have the async-RSP race the hypothesis above assumes. **New lead:** whatever screen renders in that multi-thousand-frame gap after mission-complete is the more likely site — probably `MENU_MISSION_COMPLETE` (`front.c:7267`, `constructor_menu0D_missioncomplete`) or an adjacent briefing/file-select screen in that chain, same general class as D75 (front-end model absence) / D141 (menu bad-pointer bug), not a cutscene-render race. Of the 4 repeating fault addresses, 3 read as literal zero words and only 1 matches the `0xfafbfbfc…` pattern, arguing against a deliberate poison-fill (none found anywhere in `port/`) and for either genuinely-unwritten memory or a decode landing inside unrelated valid data. Next: an env-gated `front.c` menu-transition trace (`MENU_*` id + `g_framesRendered` on every transition after `bossReturnTitleStage`) plus a `GE_PCDUMP` window over frames ~4500-8000 (not the camera-cut window) to name the exact screen/segment. Cross-ref D160 (this supersedes its stale "cutscene skipped" framing with a "cutscene renders corrupted" one, now further corrected to "corruption isn't in the cutscene render at all") and D173 (Cradle's Bond-floating/spinning cutscene bug — same subsystem family, unconfirmed shared root cause). **M-120: the `GE_D243` trace above was BUILT (statically, i.e. written) on branch `investigate/d243-cutscene-race` (`764a1f26`, pushed, not merged) — `src/game/front.c` only, `#ifdef PORT`, logs the target `MENU_*` name + a local per-tick counter on every `menu_init()` state transition. NOT build-verified: two independent sessions (the dispatched subagent, then this session re-verifying in a fresh worktree) both hit the same reproducible failure — `cmake`'s C-compiler ABI check fails with "Cannot create temporary file in C:\Windows\: Permission denied" when gcc is invoked *through* CMake/ninja, even though a bare `gcc -c` invocation from the same shell, same session, succeeds and correctly resolves its temp dir to `%TEMP%`. This is a genuine, reproducible environment issue distinct from the diff's content (static review of the diff found nothing wrong: enum cases all verified to exist in `bondconstants.h`, brace/`#ifdef` balance checked, follows the existing `GE_D160`/`GE_D178` env-gated trace idiom used elsewhere in the same file) — worth a session with a working toolchain investigating the CMake/ninja-vs-bare-gcc environment discrepancy itself as its own item, separate from D243. Next: build `investigate/d243-cutscene-race` on a session where `./build-pc.sh` actually completes, then run the `-level_33` Dam repro with `GE_D243=1` (and the existing `GE_D160`/`GE_PCDUMP` mechanisms) to correlate the trace against the D146 burst's frame range. **M-141: the M-120 toolchain blocker is EXPLAINED and worked around, GE_D243 is now build-verified.** The "Cannot create temporary file in C:\Windows\" failure isn't specific to CMake/ninja vs. bare `gcc -c` — it's this Claude Code session's `Bash` tool shell (Git-for-Windows Bash, not a real MSYS2 MINGW64 window) not exposing a usable `TMP`/`TEMP` to child processes the way an interactive MSYS2 shell does; a bare `gcc -c` from the same shell happened to not hit the temp-file path M-120 tested, which is why it looked clean while the full build wasn't. Fix: explicitly `export TMP=... TEMP=...` (Windows-style path) alongside the already-known `PATH=/c/msys64/mingw64/bin:/c/msys64/usr/bin:$PATH` fix, both before invoking `./build-pc.sh`/`ninja`/`cmake` — now also recorded in `porting-notes.md` §E as a general session-start gotcha, not just a D243-specific note. Cherry-picked the `GE_D243` trace commit (`764a1f26`) cleanly onto `release/v0.3.0` (branch `investigate/d243-fresh`), fixed one thing the original diff got wrong per this project's own D250 rule (`menu_init()` runs ~once/frame during front-end states — the diff's three `getenv("GE_D243")` calls were uncached; now a single cached `static int s_d243` check), and confirmed it builds clean. **Smoke-tested, not fully exercised:** a bare `-level_33` boot runs 1100+ frames with zero crashes and (correctly) zerLine truncated
## D244 — Self-hosted CI runner (`corpyvt6agent01`) link failure: `undefined reference to 'objectiveGetStatus_WEAK'` (2026-09-12, first-ever build attempt on the…
+79 -3
View File
@@ -2447,6 +2447,11 @@ s32 chrTick(PropRecord *prop)
s32 headSwitchVisible;
s32 headVisible;
s32 tickamount;
#ifdef PORT
int d243x2Active = 0; /* D243 M-162/M-163, see the CHRFLAG_HIDDEN else block below */
coord3d d243x2SavedPos = {0};
coord3d d243x2CycledPos = {0};
#endif
renderdata = D_8002CC6C;
chr = prop->chr;
@@ -2522,6 +2527,47 @@ s32 chrTick(PropRecord *prop)
}
else
{
#ifdef PORT
/* D243 M-162/M-163: corrected decisive experiment. M-161 restored
* prop->pos AFTER this chrTick() call returned -- but render_pos/
* field_488.pos are computed INSIDE this same call (subcalcmatrices,
* further down this function), from whatever prop->pos is at THAT
* point, so M-161 never actually prevented the stale value from
* being rendered -- its "no change" result was inconclusive, not a
* real falsification (see docs/dev/findings.md D243 M-162).
*
* Save pos right here, before the position-update dispatch below
* runs (chr.c:2541-2617, the ACT_PATROL/ACT_ANIM/ACT_STAND/else
* chain M-160 traced the overwrite to), and restore it at
* after_position_update -- before anything later in this tick
* (including the render-matrix computation) can see the cycled
* value.
*
* M-162 (Z-only) confirmed the mechanism -- Z stopped cycling and
* went smooth -- but the visible glitch was UNCHANGED, because this
* capture's chr (actiontype=3, different from M-160's capture) turned
* out to cycle Y instead of Z, and Y was left untouched. M-163: the
* whole vector, to see if suppressing every axis finally stops the
* visible shake. This DOES also freeze whatever legitimate motion
* exists on any axis (e.g. a real descent) -- acceptable for a
* decisive test, not for a fix.
*
* Gated on GE_D243X2 + the existing d243mProbeActive() cutscene-mode
* gate (POSEND/INTRO/SWIRL/FADESWIRL) -- g_CameraMode was verified
* POSEND for the entire abseil capture (GE_D243M data), so this is
* scoped correctly without needing a new g_CameraMode extern here.
*
* THIS IS A TEST, NOT A FIX. If it confirms the cycling stops: the
* real root cause is still open -- this is decomp-faithful game
* code, so find WHY it emits cycling values on PC before touching
* anything for real (rule #2's diagnosis-before-fix discipline).
* Revert this block once the experiment reports. */
extern int d243mProbeActive(void);
static int s_d243x2 = -1;
if (s_d243x2 < 0) { s_d243x2 = getenv("GE_D243X2") != NULL; }
d243x2Active = s_d243x2 && d243mProbeActive();
d243x2SavedPos = prop->pos;
#endif
if (((prop->type == PROP_TYPE_VIEWER) && (g_playerPointers[getPlayerPointerIndex(prop)]->cameramode == 1)) || (chr->chrflags & CHRFLAG_CULL_USING_HITBOX))
{
headSwitchVisible = 1;
@@ -2618,6 +2664,17 @@ s32 chrTick(PropRecord *prop)
after_position_update:
#ifdef PORT
/* D243 M-163: apply the save/restore decided above, BEFORE anything else
* in this tick (including the D243M: onscreen log right below, so it
* reports what will actually be used downstream -- and before the
* render-matrix computation further down this function) can see the
* cycled position. Whole vector this pass (M-162 was Z-only; see the
* comment at the save site for why). */
{
d243x2CycledPos = prop->pos;
if (d243x2Active) { prop->pos = d243x2SavedPos; }
}
/* D243 M-159/M-160: does render_pos only refresh on ticks that pass the
* on-screen visibility gate? Log the gate's result + the live prop
* position every chrTick call while a scripted cutscene camera is
@@ -2625,15 +2682,34 @@ after_position_update:
* in POSEND/INTRO/SWIRL/FADESWIRL, so this is silent during FPS play).
* If the freeze/teleport boundaries line up with headSwitchVisible
* flipping 0->1, this confirms the mechanism named in findings.md D243
* M-159. Diagnosis only; zero behaviour change when GE_D243M is unset. */
* M-159. M-162/M-163: actiontype= and anim= (current attached animation
* pointer) added -- M-160 flagged "which of chrTick's branches fires"
* as the open next step toward the actual root cause once the
* suppression experiment reports; x2active=/x2raw= show whether the
* suppression ran this tick and what raw position it overrode, so a
* positive result can be read straight from this log instead of by eye.
* Diagnosis only; zero behaviour change when GE_D243M/GE_D243X2 unset. */
{
extern int d243mProbeActive(void);
extern int d243mGetFrameCounter(void);
if (d243mProbeActive())
{
osSyncPrintf("D243M: onscreen frame=%d chr=%p vis=%d pos=%.1f,%.1f,%.1f\n",
/* M-166: aidx=/animframe= reuse the GE_D193A reverse-resolve
* technique (d193aAnimIndex, chr.c:67) + model->animframe1 (the
* actual current playback phase, bondtypes.h:1578) -- named per
* M-165/M-166's open question: is the visible chr's animation
* IDENTITY deterministic but its PHASE inherited from whatever
* gameplay preceded the cutscene (not guaranteed identical
* cross-platform)? A live capture with this field can now
* answer that directly instead of needing another round-trip. */
osSyncPrintf("D243M: onscreen frame=%d chr=%p vis=%d pos=%.1f,%.1f,%.1f "
"actiontype=%d anim=%p aidx=%d animframe=%.2f x2active=%d x2raw=%.1f,%.1f,%.1f\n",
d243mGetFrameCounter(), (void *) chr, (int) headSwitchVisible,
(double) prop->pos.f[0], (double) prop->pos.f[1], (double) prop->pos.f[2]);
(double) prop->pos.f[0], (double) prop->pos.f[1], (double) prop->pos.f[2],
(int) chr->actiontype, (void *) model->anim,
d193aAnimIndex((void *) model->anim), (double) model->animframe1,
(int) d243x2Active,
(double) d243x2CycledPos.f[0], (double) d243x2CycledPos.f[1], (double) d243x2CycledPos.f[2]);
}
}
#endif