forked from Ports/goldeneye-pc-port
D248: fix port-wide 30fps halving -- pointer-width scheduler ABI bug
osScAddClient() stashes a per-client "every retrace vs every other retrace" flag in the next array slot's .next field (c[1].next = next); __scHandleRetrace read it back via a hardcoded 8-byte offset that only lands on the right memory when OSScClient is 8 bytes (32-bit pointers). On this 64-bit port the struct is 16 bytes, so the read landed inside the gfx client's own msgQ pointer (always non-NULL) instead, silently collapsing the gfx client onto the audio client's 30Hz path even though the VI-retrace pacemaker itself was always correctly ticking at 60Hz. Fix indexes the struct (client[1].next) instead of hand-rolling the byte offset, so it scales with pointer width on either platform -- same class as D122/D126/D132/D209, just in the scheduler instead of a ROM-serialized struct. Verified via the Video.DisplayFPS overlay: 30 FPS pre-fix, 60 FPS post-fix, same build/scene (-level_09). -level_09/-level_20 both crash-free post-fix.
This commit is contained in:
1 parent
dac4ae7c0c
commit
52477b44af
4 files changed
+42
No files matched your search
+17
@@ -331,7 +331,24 @@ void __scHandleRetrace(OSSched *sc) {
|
||||
__scExec(sc, sp, dp);
|
||||
}
|
||||
for (client = sc->clientList; client != 0; client = client->next) {
|
||||
/* D2xx (PC-port pointer-width fix): osScAddClient() stashes a
|
||||
* per-client "every-other-frame" flag in the *next* array slot
|
||||
* (`c[1].next = next`, see osScAddClient above) -- gfxClient gets
|
||||
* NULL (send every retrace, 60Hz) and g_AudioClient gets a nonzero
|
||||
* sentinel (send every other retrace, 30Hz). This read has to land
|
||||
* on that same slot. The N64 line below finds it via a hardcoded
|
||||
* 2*sizeof(s32)=8-byte offset, which only equals sizeof(OSScClient)
|
||||
* (and thus &client[1]) when pointers are 32-bit; on this 64-bit
|
||||
* port sizeof(OSScClient)==16, so the hardcoded offset instead reads
|
||||
* the low 32 bits of client->msgQ itself (always non-NULL) and the
|
||||
* gfx client silently loses its 60Hz path, halving to 30fps. Fix:
|
||||
* index the real field instead of hardcoding the byte offset -- it
|
||||
* naturally scales with the pointer width on either platform. */
|
||||
#ifdef PORT
|
||||
if ((client[1].next == 0) || ((sc->frameCount & 1) == 0)) {
|
||||
#else
|
||||
if ((*((s32*)client + 2) == 0) || ((sc->frameCount & 1) == 0)) {
|
||||
#endif
|
||||
osSendMesg(client->msgQ, (OSMesg) &sc->retraceMsg, OS_MESG_NOBLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user