Skip to content

fix(libSceNgs2): return the custom rack creation errors - #8609

Merged
1 commit merged into
boykopovar:mainfrom
KernelPanicNT:fix/ngs2-custom-rack-errors
Oct 23, 2026
Merged

1 commit merged into
boykopovar:mainfrom
KernelPanicNT:fix/ngs2-custom-rack-errors

Conversation

@KernelPanicNT

@KernelPanicNT KernelPanicNT commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What

sceNgs2RackCreate and sceNgs2RackCreateWithAllocator now return the errors that the PS5 libSceNgs2.native.sprx returns for invalid custom sampler (0x4001) and custom submixer (0x4002) rack options. Until now, Ngs2CheckCustomRack threw for these options.

Valid options whose behaviour is still unknown keep throwing, with a message that names what is missing. That covers the four built-in modules, multi-buffer racks and wide custom submixers, so this PR does not unblock a title by itself (see Unblocks).

Source of the behaviour.

  • fma-rc's reading of the PS5 12.70 module in #8039. The id map is the same in 4.00, 7.01, 9.00 and 10.01. It covers:
    • the built-in module table: 0x15 Gain, 0x19 UserFx, 0x1b Reverb, 0x20 PitchShift, 0x23 Convolution;
    • rack create rejects a module state size that is non-zero and differs from the module's own: 0x804a8302;
    • Reverb: a 12-byte option (other sizes 0x804a8013), the word after the size 0 or 1 (else 0x804a8099), no state;
    • PitchShift: an 8-byte option whose word after the size must be 0 (0x804a8098), 8 bytes of state;
    • Gain and UserFx take no option and no state. Convolution takes a 64-byte option and, from SDK 3.0, 64 bytes of state;
    • custom racks take 1 to 4 buffers (0x804a830b otherwise). Submixer and mastering racks also need num_buffers >= max_inputs, with max_inputs 1 or 2;
    • a module whose source, extra or dest buffer id is not below num_buffers fails with 0x804a8306;
    • custom submixer and mastering racks accept 1 to 37 channels (0x804a8052 above).
  • prosper's table of the same module's error codes (hle_audio.cpp#L3777-L3797) independently places 0x804a8013 at an option size check, 0x804a8052 at a channel count check and 0x804a830b at a buffer count check. Its notes on sceNgs2RackCreate and sceNgs2RackCreateWithAllocator check the buffer info or allocator before the rack core, so those checks now run before the option checks.

What is kept as a throw, and why.

  • The Query export: sceNgs2RackQueryBufferSize still throws for these options. Neither source says whether it runs the same checks.
  • The four built-in modules: Gain, Reverb, PitchShift and Convolution pass the checks and then throw, because their processing is unknown.
  • Multi-buffer racks: racks with 2 to 4 buffers throw, because how modules and ports route several buffers is unknown.
  • Wide custom submixers: 9 to 37 channels throw, because voices hold at most 8 channels.
  • max_inputs: a custom submixer value other than 1 or 2 throws, because the source does not say what happens then. This replaces the old acceptance, which had no source.
  • Module 0x19: it still throws as an unknown id. fma-rc and KytyPS5 both call it UserFx, but this library already serves a module it calls UserFx as 0x1d. That id comes from Void Terrarium (PPSA03061) creating a rack with it (feat(ngs2): support custom submixer rack UserFx module 0x1d #5139), with a 20-byte option (#5055) that fma-rc's UserFx does not take, so what 0x1d is remains open. The debt entries now say so; an earlier revision of this PR wrongly attributed 0x1d to KytyPS5.
  • Convolution sizes: its option and state sizes are not checked. The error for other option sizes is not given, and the state size depends on the SDK version.
  • Order and other errors: the order of the checks, and the errors for a Gain option or a missing Reverb or PitchShift option, are unknown. The tests only use inputs with a single fault.

Changes:

  • Ngs2Types.hpp: the seven error codes, the limits (4 buffers, 37 submixer channels, 2 inputs) and the module ids 0x15, 0x1b, 0x20, 0x23. The constant names are ours; the sources give only the values.
  • Custom.cpp: Ngs2CheckCustomRack returns a code.
    • It first checks the buffer count.
    • Then, for every module, it checks the buffer ids, replacing the per-module != 0 throws, and the built-in module sizes.
    • Only after that does it throw for multi-buffer racks and built-in modules.
  • Rack.cpp: CheckedRackOption returns that code, plus 0x804a8052 for more than 37 submixer channels. The create exports return it. The query export throws on it.
  • ngs2_custom, new TestCustomRackChecks:
    • every code through sceNgs2RackCreate (one through sceNgs2RackCreateWithAllocator, without calling the allocator), on both rack types;
    • the throwing cases for valid but unimplemented options;
    • a module after a valid built-in one that still returns its buffer id error;
    • the query throw.
    • The existing out-of-range dest_buffer_id assertion keeps expecting the query to throw.
  • docs/dev/debt/libSceNgs2.native.md: the custom module id entry is rewritten, and a new entry covers buffers and channels. Both cite the comment and list what is still unknown.

Tested

Linux (GitHub Codespace, 4 cores, native build of this branch rebased on ce7d54717, after #8238 and #8513 changed the rack lock next to the moved checks; the later amend only rewords the debt):

  • All 12 ngs2_* test executables (ngs2_custom, ngs2_render, ngs2_userfx, ngs2_filter, ngs2_handleerrors, ngs2_atrac9, ngs2_parse, ngs2_stream, ngs2_report, ngs2_geom, ngs2_voiceindex, ngs2_voicehandles): 5/5 runs each pass.
  • Negative control: with Custom.cpp, Rack.cpp and Ngs2Internal.hpp from main, ngs2_custom_tests aborts with NGS2: custom racks with 0 buffers are not implemented, and the other 11 still pass. 5/5 pass again after restoring them.

Windows (fork CI, run 39467813569, the first revision of this branch merged into the fork's main at 892a4f132, before the rebase): build and the full test suite pass, 1764/1764.

Title: @EdouardSence ran Rise of the Ronin (PPSA04540 01.009.000) on Linux with main c70524a3d, #8341 and the first revision of this PR (comment). The title's custom racks pass the new creation checks, and it stops about 30 s in on NGS2: the custom Gain module is not implemented, the same point as the earlier custom module id 0x15 stop, now named.

Checks:

  • python3 tools/check_conventions.py --base origin/main passes.
  • tools/progress.py: unchanged (4570/10772 on base and head).

Duplicate and overlap check

Searches of open and closed pull requests for Ngs2CheckCustomRack, "custom rack" and "custom module" find no other change to these checks. The closest are the merged #781, #4417 and #5139, which this builds on, and the merged debt entry #6673, which this rewrites.

python3 tools/pr_overlap.py --branch fix/ngs2-custom-rack-errors reports text conflicts on neighbouring lines, none on the same behaviour:

Whichever lands second keeps both changes. It could not compare #1384 and #5797, which conflict with main. Checked by hand:

Checklist

@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

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.

Pull request Shared files not compared
PR 1384 core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp
core/libs/prx/libSceNgs2.native/src/Ngs2Internal.hpp
core/libs/prx/libSceNgs2.native/src/Rack.cpp
PR 5548 core/libs/prx/libSceNgs2.native/src/Ngs2Internal.hpp
docs/dev/debt/libSceNgs2.native.md
PR 5797 core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp
core/libs/prx/libSceNgs2.native/src/Ngs2Internal.hpp
docs/dev/debt/libSceNgs2.native.md
PR 8851 docs/dev/debt/libSceNgs2.native.md
PR 9143 docs/dev/debt/libSceNgs2.native.md
PR 9148 docs/dev/debt/libSceNgs2.native.md
PR 9149 docs/dev/debt/libSceNgs2.native.md
PR 9155 docs/dev/debt/libSceNgs2.native.md
PR 9312 core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp
docs/dev/debt/libSceNgs2.native.md
PR 9315 core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp
docs/dev/debt/libSceNgs2.native.md
PR 9316 core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp
docs/dev/debt/libSceNgs2.native.md
PR 9320 core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp
docs/dev/debt/libSceNgs2.native.md
PR 9324 docs/dev/debt/libSceNgs2.native.md
PR 9327 docs/dev/debt/libSceNgs2.native.md
PR 9362 docs/dev/debt/libSceNgs2.native.md
PR 9926 core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp
docs/dev/debt/libSceNgs2.native.md

@EdouardSence

Copy link
Copy Markdown
Contributor

Checked on Rise of the Ronin (PPSA04540 01.009.000), Linux, RX 9070 XT / RADV Mesa 26.2.4.

Build: main c70524a + #8341 (6539598d5) + this PR (eec3f106e). #8341 is needed to get past the system option flags stop first.

Result: the title's custom racks pass the new creation checks, and it now stops about 30 s in on

what():  NGS2: the custom Gain module is not implemented

This is the same point as the previous NGS2: custom module id 0x15 is not implemented stop, now named as described in the PR. One 120 s run.

Tested and written by Claude (AI assistant) on a contributor's machine.
AI-assisted: yes

sceNgs2RackCreate and sceNgs2RackCreateWithAllocator now return the firmware's errors for a custom rack whose buffer count is outside 1 to 4 or below the submixer's max_inputs, whose module buffer id is at or above the count, or whose submixer has more than 37 channels, and for the state sizes of the Gain, Reverb and PitchShift modules, the Reverb option size and word, and the PitchShift option word. Racks that pass these checks with one of these modules or Convolution, with more than one buffer, more than 8 channels or a submixer max_inputs other than 1 or 2 still throw, and so does sceNgs2RackQueryBufferSize for the rejected options.
@EdouardSence

Copy link
Copy Markdown
Contributor

Follow-up on top of this PR: #9233 processes the custom Gain module on the custom submixer rack, from fma-rc's reading in #8039 (37 per-channel linear levels, default 0, linear ramp over the grain).

Rise of the Ronin with main + #8341 + this PR (9f5640af6) + #9233: its Gain racks now pass creation, and the next stop is the second module of the same rack:

what():  NGS2: the custom Reverb module is not implemented

Tested and written by Claude (AI assistant) on a contributor's machine.
AI-assisted: yes

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 22, 2026
@oneandonlydean oneandonlydean closed this pull request by merging all changes into boykopovar:main in a1d4803 Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs needs rebase Conflicts with main, rebase needed prx

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants