mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-24 00:02:45 +02:00
D150 (src/str.c) — NULL-tolerant strcpy/strncpy/strcat under #ifdef PORT. The watch BRIEF/OBJECTIVES pages build text with strcat(buf, langGet(id)); langGet() returns NULL on PC for a string bank the in-level flow never loaded, and str.c's primitives are __nonnull__ builtins so a plain param NULL check is optimised away — the guard launders the ptr through an empty asm (GE_IS_NULL). NULL src -> empty string instead of an AV crash. D151 (src/bondtypes.h) — watch data (objectives / mission background / M / Q / Moneypenny) all rendered blank. propDef types 35 (WatchMenuObjectiveText) and 23 (ObjectiveStart) store a plain s32 lang slot id in their 3rd word; the decomp structs decode it as [u16 reserved][u16 text] reading text at offset 0xA, which only works because the id is in the low 16 bits of a big-endian word. d88_propdefs.py bswap32's the whole word -> text @0xA reads 0 -> langGet(0) -> NULL. Fix: text is a full u32 at the word offset under #ifdef PORT (N64 layout kept under #else). No converter change, no sidecar regen. This is the D143/D150 "briefing text renders blank" root cause. D152 (port/src/libultra.c) — mission-failed / objective-failed permanent black screen. The D147 recursive-mutex behind osSetIntMask can be leaked (libaudio has unbalanced / early-return mask calls; a transient thread can acquire OS_IM_NONE and exit) -> mainThread + amMain both block forever in alEvtq* -> gfx pipeline stalls. Live gdb.txt from the user's session confirmed the deadlock (mainThread in the mission-fail audio fade-out sndSetScalerApplyVolumeAllSfxSlot -> alEvtqPostEvent). Mitigation: model the mask as a self-healing logical lock (owner/depth under s_imMx + condvar) — normal microsecond critical sections behave as before, but a waiter blocked > 2s concludes the holder leaked it, logs the stale owner + the stealing caller's return address, and steals the section. Worst case is a ~2s audio hiccup + a log line naming the leak, instead of a hung game. Proper narrow fix (dedicated ALEventQueue lock) still owed. D153 investigated and dismissed — the "-level_09 crashes at frame ~900" seen while regression-testing was D117/D134 host-scheduling flakiness under heavy concurrent build+run load; on a quiet machine -level_09 runs past frame 2400 clean with all three changes applied. Build: green (ntsc-final). Golden framediff not run clean (same machine-load flakiness); one quiet -level_09 run = 2400+ frames, 0 heartbeats.