Fix Death Mountain Trail rockfall crash (gfx pool headMagic overflow, graph.c:356)#6744
Fix Death Mountain Trail rockfall crash (gfx pool headMagic overflow, graph.c:356)#6744halo9004 wants to merge 1 commit into
Conversation
The opaque gfx pool (polyOpaBuffer) is filled from both ends in a frame: display lists from the front, matrices/vertices from the back via THGA_AllocEnd, which has no lower-bound check. Very dense frames push the back allocations past the start of the buffer and overwrite headMagic, hard-crashing Graph_Update (graph.c:356). Enlarging polyOpaBuffer from 0x2FC0 to 0x6000 gives those frames enough headroom. Reproduced 100% at the Death Mountain Trail summit during the rockfall as adult Link; does not occur there as child Link. Independent of resolution, enhancements, mods, and the OTR. Tested from a source build: the crash no longer occurs.
| // SOH [Port] polyOpaBuffer enlarged from 0x2FC0. It's allocated from both | ||
| // ends (display lists grow up, matrices/vertices grow down via THGA_AllocEnd, | ||
| // which has no lower bound). Very dense frames like the Death Mountain Trail | ||
| // rockfall drive the tail below the buffer into headMagic and hard-crash | ||
| // Graph_Update (graph.c:356). More headroom keeps those frames in bounds. |
There was a problem hiding this comment.
| // SOH [Port] polyOpaBuffer enlarged from 0x2FC0. It's allocated from both | |
| // ends (display lists grow up, matrices/vertices grow down via THGA_AllocEnd, | |
| // which has no lower bound). Very dense frames like the Death Mountain Trail | |
| // rockfall drive the tail below the buffer into headMagic and hard-crash | |
| // Graph_Update (graph.c:356). More headroom keeps those frames in bounds. |
we'd already doubled the size before
guessing you're on high FPS
There was a problem hiding this comment.
yeah im running it on my 480hz monitor actually 😅 I play counter strike so im a sucker for high fps
There was a problem hiding this comment.
we need to cap fps until interpolation doesn't generate N steps per frame that all get buffered here
There was a problem hiding this comment.
ahh ok yeah agreed this is just a bandaid fix, I see the there is already a fps limit of 360FPS in the settings but toggling match refresh rate overrides that. Maybe capping it at 360FPS internally would be a better solution. Anyway hmu if you want me to test any fps cap or interpolation change or anything else that I can contribute too😄
|
Tick the box to add this pull request to the merge queue (same as
|
Ship of Harkinian [BUG].log
Summary
Hard crash when standing at the Death Mountain Trail summit during the rockfall,
as adult Link. The game faults in
Graph_UpdateviaFault_AddHungupAndCrashat
soh/src/code/graph.c:356. It does not happen as child Link in the samespot, and it is independent of resolution, enhancements, texture/model mods, and
the OTR (reproduced with all mods removed, enhancements off, N64 mode 4:3/240p,
and a freshly regenerated OTR from a clean, hash-verified ROM).
Version
Steps to reproduce
100% reproducible at that spot for me.
Crash signature
(Full crash log attached.)
Root cause analysis
graph.c:356is the gfx-pool head-guard check inGraph_Update:headMagicsits at offset 0 ofGfxPool, immediately beforepolyOpaBuffer[0](offset 0x08). The opaque arena is a two-headed arena:
polyOpaBuffer[0];Matrix_NewMtx->Graph_Alloc->THGA_AllocEnd) grow thetail downward from the end of
polyOpaBuffer.THA_AllocEnd(soh/src/code/TwoHeadArena.c) has no lower-bound check:In a single frame that draws a very large number of actors at once (the DMT
summit rockfall: many
En_Fire_Rock, boulders, plus adult Link's heaviermodel/equipment), the tail decrements past
polyOpaBuffer[0]and writes intoheadMagic. The next frame'sGraph_Updatesees the guard clobbered andhard-crashes. Because the write lands on
headMagicrather than trippingTHGA_IsCrash(which would just skip the frame), it's a hard crash rather than adropped frame. Adult vs. child Link is a threshold effect -- adult's extra
per-frame matrices push that frame over the edge.
Proposed fix
Give the opaque arena more headroom in
soh/include/z64.h--polyOpaBufferfrom0x2FC0to0x6000Gfx entries (~95 KB -> ~192 KB per pool, ~200 KB total extraacross the two pools). Nothing else hardcodes the old size.
typedef struct { /* 0x00000 */ u16 headMagic; // GFXPOOL_HEAD_MAGIC - /* 0x00008 */ Gfx polyOpaBuffer[0x2FC0]; + /* 0x00008 */ Gfx polyOpaBuffer[0x6000]; /* ... */ Gfx polyXluBuffer[0x1000]; /* ... */ Gfx overlayBuffer[0x800]; /* ... */ Gfx workBuffer[0x100]; /* ... */ Gfx unusedBuffer[0x40]; /* ... */ u16 tailMagic; // GFXPOOL_TAIL_MAGIC } GfxPool;I built this change from source (commit cb71e22) and confirmed the crash no
longer occurs at the DMT summit rockfall as adult Link.
Optional hardening (not required for the fix, but converts any future over-budget
frame from a hard crash into a harmless dropped frame): clamp
THA_AllocEndsothe tail can't underflow below
tha->bufp, letting the existingTHGA_IsCrashpath in
Graph_Updatehandle it gracefully.Build Artifacts