Repository navigation
fix(libSceNgs2): clear the voice callback on sampler and mixer setup - #7428
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BywPXoZACVi8ALV4JKvuPZ
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
Reproduced on Windows 11, WinLibs GCC 15.2.0 (MinGW), Release, this PR applied onto One side effect isn't covered by a test or by the debt line: a block-end callback that sets its own voice up again and queues the next block now unregisters itself. That is what AI-assisted: yes (Claude Code); results above were run on this machine. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BywPXoZACVi8ALV4JKvuPZ
|
@wachi35676 thanks for reproducing it on Windows and for the probe. You're right about that side effect. I checked whether Peace Walker relies on that ordering. I added a temporary probe that logs every setup made while a voice callback is running, then played from the launcher to the beach tutorial on Linux. The block-end callback ran 3 times, and the game never set a voice up from inside a callback. Every setup that cleared a callback came from outside one, which is the case this PR is about. So I updated the debt entry in 5e0deae. It now says that a setup made from inside the voice's own callback clears that callback too, so such a callback runs once instead of for every block, and that this ordering is unverified, since PPSA18216 never does it. AI-assisted; the runs are from my machine(s). |
Checked the diff, the callers and the test; merged. |
What
A sampler or mixer setup (
SCE_NGS2_SAMPLER_VOICE_PARAM_SETUP, mixer setup) now clears the voice callback thatSCE_NGS2_VOICE_PARAM_CALLBACKregistered.Ngs2Voice::ResetSetup()already resets the rest of the voice: waveform, blocks, ports, matrices, filters and the UserFx handler. Only the voice callback survived the setup, so a callback registered for one use of a voice ran for blocks queued after a later setup.Metal Gear Solid: Peace Walker (PPSA18216) reuses one sampler voice for two jobs:
user_data.user_data0.main, the music callback still runs when the one-shot block ends. The game readsuser_data+ 0x20 (cmpb $1,0x20(%r15)withr150) and faults.That's the crash at New Game in #5268.
The game never clears the callback itself, and after each setup it registers the callback again before it streams music. That only works if a setup clears it. The debt entry records this as unverified on console hardware.
TestSetupClearsCallbackinngs2_render/ngs2_core_renderfollows the same sequence with PCM blocks:user_data0. The test expects no callback.user_data0x55. The test expects exactly one block-end callback.The existing
OnBlockcallback checksuser_data == 0x55, so onmainthe test fails the same way the game does.Tested
Release builds of this branch (
mainccb0c09 plus this commit):ctest -R ngs2)ngs2_render,ngs2_core_renderrepeated (--repeat until-fail:20)main'sVoice.cppNGS2 check failed at line 25(OnBlockgotuser_data0)tools/check_conventions.py,git diff --checkPPSA18216, with this change on top of
mainc9e6c45 plus #6014, #6196, #6237, #6842, #7072 and #7200, and two local graphics workarounds (branchtest/ppsa18216-ingame, described in #5268):main)user_data0mgspw.elf+ 0x4e8c, fromNgs2FinishBlock/AdvanceAtrac9The title also reached the tutorial on Windows 11 (laptop RTX A2000) with the same branch.
tools/pr_overlap.pycould not compare #1384, #5797, #6447, #6594 and #6680 because they conflict withmain. I checked their diffs by hand, and none of them changes the voice callback orResetSetup.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)AI-assisted; the runs are from my machines.