mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-24 00:02:45 +02:00
User hit a "hang" (process alive, heartbeat dumps) at the end of the Facility outro cutscene. Symbolicated mainThread stack: parked in modelConstrainOrWrapAnimFrame <- modelTickAnim <- chrUpdateAnim <- chrTick <- playerTick <- propsTick <- lvlRender across every dump. Root cause: waitForNextFrame() (src/game/frametiming.c) passes nextFrameTime = (osGetCount()-prev+387937)/775875 to updateFrameCounters UNCLAMPED. osGetCount() is wall-clock on the port (D117), not VI-locked, so a real-time stall (asset load at the cutscene->debrief boundary, made worse by a local LLM hammering the box) makes nextFrameTime balloon to hundreds/thousands. That becomes speedgraphframes -> g_ClockTimer, which drives modelTickAnim's `while (numticks-- > 0)` per character per render plus dozens of `for (i=0;i<g_ClockTimer;i++)` sim loops -> one frame does thousands of anim ticks x N chars -> multi-second frame -> heartbeat trips, and the slow frame feeds an even bigger delta -> unrecoverable spiral. The N64 was VI-bound and never produced deltaFrames > ~2. Fix: #ifdef PORT clamp nextFrameTime to FRAMETIMING_PORT_MAX_CATCHUP (6) in waitForNextFrame(). N64 path verbatim. Timing-compensation class, cf. D117/D134. PORT-LEARNINGS §E. Verified: build green (ntsc-final); -level_09 unregressed (frame 200 nonclear delta 0.04pp, full-window crash-free). The clamp only engages when a frame took >~100ms, so normal play is byte-identical.