forked from Ports/goldeneye-pc-port
Root cause: src/game/mp_music.c's sub_GAME_7F0C0BF0() is a one-line wrapper around get_mTrack2Vol() with no return statement. On N64/IDO the value happened to already sit in $v0; at the PC release build's -O2 the return register is genuinely undefined (docs/porting-notes.md D6 class, same as D187). Every in-level music trigger goes through set_missionstate()'s MISSION_STATE_1/4 cases (the only path that starts a level's background track), which feeds this garbage/zero value straight into musicTrack1ApplySeqpVol()/musicTrack3ApplySeqpVol() right before musicTrack1Play()/musicTrack3Play() — silencing the whole track for its entire duration while note-on processing continues normally. Front-end/menu music bypasses set_missionstate() entirely (front.c calls musicTrack1Play() directly), which is why it was never affected. Fix: return the tail call under #ifdef AVOID_UB, #else keeps the N64 body verbatim. One line, no game-logic change. Diagnostic: added a temporary, cheap (~1/s, gated on GE_AUDIOTRACE) [AUDIOLVL] peak/RMS probe of the exact buffer audioSetNextBuffer() hands to SDL (port/src/audio.c), interleaved into the same audiotrace.log as the existing csplayer.c [MUSICNOTE] probe via the shared geTracePrintf lock. Before the fix: 173 [MUSICNOTE] events over a 28s BUNKER1 capture, but every single [AUDIOLVL] reading (29 samples spanning the full run) read peak=0 rms=0.0. After the fix: same note count, every [AUDIOLVL] reading sustained non-zero (peak ~2700-10300, rms ~800-2900). tools_pc/verify.sh bunker1: PASS, no visual regression. Docs: docs/dev/findings.md D77 updated from stale "nothing reaches PC speakers" framing to the actual root cause + verification; new D6 instance logged in docs/porting-notes.md. Claude-Session: https://claude.ai/code/session_016TaKy6AAsVUTfjkhrX6CjG