Files
AnyPS5/docs/dev/debt/libSceNgs2.native.md

53 KiB

libSceNgs2.native technical debt

Unknown function info

  • NGS2 PCM sampler playback is not console-verified. Types 0x11, 0x12, 0x14, 0x16, 0x18 and 0x1a follow prosper's waveform parser analysis and the WAVE representations it selects: unsigned 8-bit, signed little-endian 16/24/32-bit and little-endian IEEE float/double. Integer samples use the existing signed-16 normalization generalized to their width; double samples narrow to host float. Console rounding, float clipping, nonfinite and subnormal handling are unknown: floating input outside -1..1, nonfinite values and nonzero magnitudes below the smallest normal float throw. Other types and nonzero configuration words on the new formats throw. Incomplete streamed blocks and dataless silence blocks remain supported only for signed-16 PCM; the new formats require complete blocks.

  • NGS2 voice validation returns 0x804A8203 for an invalid voice in Control, RunCommands, GetState, GetStateFlags, GetPortInfo and QueryInfo, following the type-4 handle error in prosper's PS5 module analysis. Control checks a null parameter list first (0x804A8360); GetState resolves the voice before output validation, and GetState rejects sizes below 8 before a null output. Existing rack-specific exact state sizes, other argument precedence and command layouts are retained; arbitrary-sized state copies and full console behavior remain unverified. These values follow module analysis, not new console execution.

  • NGS2 system and rack handle errors use 0x804A8201 and 0x804A8202, following the native handle-type error helper recorded in prosper's PS5 module analysis. sceNgs2RackGetVoiceHandle resolves the rack before checking the output pointer, matching the export in firmware 1.00 through 12.70 reported in #5916. Other exports retain their existing validation order; complete invalid-input precedence and console execution remain unverified.

  • NGS2 system option flags (libSceNgs2.native) - sceNgs2SystemQueryBufferSize, sceNgs2SystemCreate and sceNgs2SystemCreateWithAllocator accept flags 2 (bit 1) and ignore it. PPSA04540 (Rise of the Ronin) passes it when creating its system. The firmware's shared option validator, as read in prosper, checks the size and the fields from +0x6c on but not flags at +0x68. What bit 1 selects is unknown. Every other bit still throws, including bit 31, which shadPS4 reads.

  • NGS2 render buffer capacity is treated as available storage for one configured grain. PPSA01880 passes 303104 bytes for 256 stereo float frames (2048 bytes); rendering writes or clears only those frames and preserves the remaining capacity. Non-null silent outputs now undergo the same supported-format and minimum-size checks as audible outputs, with channel counts limited to 1 through 8. A zero buffer count throws: the module accepts it, but whether it renders voices is unknown. Before rendering, over 31 buffers return 0x804A830B, a type other than 0x12, 0x13, 0x18 or 0x19 0x804A8050 and a NULL buffer 0x804A8251, per prosper's reading; 0x13 and 0x19 then throw. Surplus capacity is unmeasured; channel and size refusals throw.

  • NGS2 ATRAC9 waveform loops (libSceNgs2.native) - unmeasured on a console. A loop starting inside the decoder delay or ending past the last sample, a loop block past the data chunk, a smpl chunk too short for its first loop and a looped file at a rate with no module frame size throw: the module wraps or does not bound these, and what it then decodes is unknown. As prosper reads the module, only the first loop's start and inclusive end are used, less the one-frame decoder delay, and type, fraction, play count and other loops are ignored; an end not after the start keeps one block, else an intro, the loop repeating forever and a tail. PPSA03747 (start 256, inclusive end 299224, 298969 samples) gets one block repeating forever

  • NGS2 ATRAC9 parsed delay (libSceNgs2.native) - sceNgs2ParseWaveformData reports one codec frame as num_delay_samples whatever the fact chunk's delay word holds, as prosper's reading of libSceNgs2.native.sprx sets it for ATRAC9 (its test expects 256 for a fact of 900 and 0). Not measured on a console. The block skip still comes from the fact chunk's third word, where prosper uses the same one-frame delay

  • NGS2 submixer UserFx (control 0x20000004) invokes the title's callback after input mixing on every playing grain, including silence. The 40-byte control and 48-byte process context follow shadPS4. PPSA03747 installs a peak-meter callback; its code confirms the channel pointers, user data 0, channel count, grain size and sample-rate offsets and returns 0. Other user data words are preserved. Flags are assumed to be 1 after registration/restart and 0 thereafter, following UserFx2's first-process convention; this callback does not inspect them. Null handlers disable the effect, setup clears it, and nonzero callback results throw. These lifecycle and error semantics are unverified on console hardware.

  • NGS2 voice callback after setup (libSceNgs2.native) - a sampler or mixer setup clears the voice callback with the rest of the voice state. PPSA18216 registers a block-end callback for a streamed music voice, later sets the same voice up again for one-shot ATRAC9 blocks with user data 0, and registers the callback again before it streams again; its callback dereferences the block's user data, so it must not run for the one-shot blocks. A setup made from inside the voice's own callback clears that callback as well, so a callback that sets its voice up again and queues the next block runs once instead of for every block; PPSA18216 never sets a voice up from inside its callback, so that ordering is unverified. Unverified on console hardware.

  • NGS2 ATRAC9 streaming keeps waveform duration and skip counts across compressed input blocks. The shared APPEND flag (2), called ONLY_DATA in the compressed-data reference, ignores an ATRAC9 continuation block's sample, skip and repeat counts, following KytyPS5; PPSA03747 confirms a 262044-byte initial buffer declaring 11310532 samples, followed by 16384-byte buffers with flags 3. Incomplete superframes are retained until more input arrives. Input-block completion callbacks allow refills; the final callback of a logical waveform waits for its buffered PCM to drain, preserving the existing complete-block repeat behaviour. This buffering, callback timing, decoded-byte accounting and starvation silence are unverified on hardware. A closed ATRAC9 stream ending before its declared samples throws; fragmented ATRAC9 waveforms with repeats are unsupported. PCM streaming retains its existing append validation and early-close behaviour.

  • NGS2 mastering voice gain (libSceNgs2.native) - a NaN sample in a PCM_I16L render buffer throws, because PS5 firmware 3.20 and 4.03 were measured only into float buffers, where a NaN gain gives NaN samples. Measured there: param 0x30000004 (id seen in PPSA22520) sets linear full-band and LFE factors on the mastering output, applied from the next render, flat for the first gain a voice receives and ramped over the next grain in eight lanes after that, which this change does not implement; each is clamped to [-32, 32] with NaN kept, and every value returns 0. The LFE level acts on channel 3 of 6- and 8-channel voices and the full-band level on every other channel, 1- and 2-channel voices included; a mastering setup resets both to 1, and STOP_IMM plus PLAY keeps them

  • NGS2 stereo mastering voice into a surround buffer (libSceNgs2.native) - PPSA21402 renders a 2-channel mastering voice into a 6- or 8-channel render buffer, which the mixing stage rejected. The console's conversion is unknown: the left and right channels are assumed to go to the first two buffer channels (front left and right) and the remaining channels stay silent, with no centre, LFE or surround content. Any other channel count mismatch still throws

  • NGS2 voices without a format (libSceNgs2.native) - a sampler voice whose setup has no format (all zero) accepts an add of no waveform blocks without APPEND, which only applies RESET and the CONTINUE state, and matrix levels with no levels, which clear that matrix. PPSA36591 sets such a voice up, adds no blocks and sets no levels when a button is pressed at its title screen. Whether the console returns success or an error there is not measured; blocks with data, APPEND and an empty matrix on a voice with a format are still refused

  • NGS2 play without setup (libSceNgs2.native) - differs from PS5 firmware 3.20 and 4.03 libSceNgs2.native.sprx in two cases: a set-up voice given an add of no waveform blocks and played keeps state flags 1 there for as long as it was watched and only until the next render here; an add of no blocks to a voice that already played and ended returns 0x804A8054 there and succeeds here. A PLAY on a voice with no channels (never set up; an all-zero setup leaves an earlier setup untouched) returns 0x804A8351 (SCE_NGS2_ERROR_INVALID_VOICE_ACCESS) from Control and RunCommands, leaves it idle and skips the rest of the list, as that module does for every rack; PPSA03061 (Void Terrarium) frees its sound slots that way

  • NGS2 silent waveform blocks (libSceNgs2.native): flag 0x10 (named SILENCE here; no public reference names it) lets a waveform block declare samples without data. PPSA04867 adds one block with flags 0x11, data_size 0 and num_samples 16385, then another with flags 0x11 and a fully specified 0x800-byte, 1024-sample mono block, which takes the ordinary path. A dataless block under the flag outputs num_samples frames of silence, reports them through decoded_data_size, and finishes like a complete block; a dataless block without the flag still throws as not fitting its data. The flag's real name, its interaction with ATRAC9 and repeats, and the console's waveform_data for silent blocks are unverified on hardware

  • NGS2 streaming PCM waveforms (libSceNgs2.native) - PPSA21402 streams its music by adding one block whose num_samples is the whole track and whose data_size is a 16 KiB first piece, with CONTINUE, and then adds each following piece with flag 0x2 (called APPEND here) and the same num_samples. No reference describes flag 0x2. A 16-bit PCM block without skipped samples or repeats whose num_samples exceed its data is assumed to start such a stream; flag 0x2 is assumed to append the block's data to the last streaming block, ignoring its num_samples; the voice is assumed to output silence without advancing while it has played all appended data and CONTINUE is set; and the waveform is assumed to end at num_samples or, once CONTINUE is cleared, at the end of the appended data. sceNgs2VoiceGetState reports the bytes played as decoded_data_size, which the title uses to release its queued data, and the read position as waveform_data. Appending to a block that is not a stream, or other formats, skipped samples, repeats and partial frames, throw

  • NGS2 matrix levels (libSceNgs2.native) - levels are clamped to -4..4 and NaN is kept, as the PS4 firmware 11.00 libSceNgs2.sprx stores them; not yet confirmed on the PS5 library. That library rejects a level count of 0 and keeps the matrix; the PS5 error code is unknown, so a count of 0 throws, except on a sampler voice without a format, where it clears the matrix (see NGS2 voices without a format). sceNgs2VoiceRunCommands is not in that library, so its matrix levels command is assumed to clamp the same way

  • NGS2 sampler voice state flag EMPTY (libSceNgs2.native) - a playing sampler voice that still accepts blocks (CONTINUE) and has played all queued blocks reports INUSE|PLAYING|EMPTY (0x20) and keeps playing, so blocks added later play on. PPSA18391 (engine: Clickteam Fusion) reads state_flags & 0x22 != 2 from sceNgs2VoiceGetState as the end of a sound and only then reuses the voice. When the console sets and clears EMPTY, and whether it also reports it for other voice types, is unverified on hardware.

  • NGS2 waveform block playback has reference checks for finite PCM repeat counts 0 through 3, skip/sample windows, callbacks and six input formats using host kernel adapters, not console execution. Finite repeat counts specify total passes, with 0 and 1 both playing once. PCM reads the combined skip/sample window from the data start; ATRAC9 retains codec skip handling. The public callback repeat field stays zero in those checks. Extreme window overflow, fragmented compressed repeats and callback positions outside the tested schedules remain unverified.

  • NGS2 custom parameter positions - other custom module families have not received the PitchShift validation audit. PitchShift decodes the low five position bits within its parameter family: 0x20 aliases position zero, matching 13.60 dispatch and host-adapted reference execution. An absent or mismatched module returns 0x804A835A before later linked parameters execute. Checks cover two module positions, invalid positions, list termination and active processing through an aliased parameter. These are host-adapted library checks, not console execution.

  • NGS2 reverb channel conversion (libSceNgs2.native) - a reverb voice whose num_input_channels differs from num_output_channels (PPSA03747 sets up 2 inputs and 8 outputs) mixes its ports in the input layout and folds that to mono with the input count's gains, as an equal-count voice does, and runs the comb and allpass stages per output channel. The PS4 library's handling of the dry signal in this case is not checked: here it reaches the output layout through the default channel map, so a stereo input keeps its dry signal on the front left and right and the other outputs carry only the reverb

  • NGS2 port matrix (libSceNgs2.native) - a port without a matrix, or with a selected matrix whose levels were never set, mixes through a default channel map: mono reaches both stereo channels at -3 dB and the 5.1 and 7.1 centre, stereo folds to mono at -3 dB per side, and wider sources fold down with 0.5 and -3 dB gains. The map and the equivalence of an unset matrix with no matrix were measured from the PS4 firmware 11.00 libSceNgs2.sprx, not yet from the PS5 library. That library only accepts submixer and mastering voices with 1, 2, 6 or 8 channels, so the map into 3, 4, 5 or 7 channels throws. A matrix set with fewer levels than the destination needs still mixes only the rows it has

  • NGS2 custom submixer rack (libSceNgs2.native, rack 0x4002) - UserFx2 process flags and setup/process/cleanup order follow only KytyPS5, not a console measurement; layouts follow shadPS4's ngs2_custom.h. A module control handler, unequal input and output channels, setup flags and default rack options throw. Module state is a separate buffer, not the state_offset slice of voice state; sceNgs2VoiceGetState throws for this rack. UserFx2 runs only on grains with input samples, so an effect tail stops with the input. Setup changes from custom process callbacks throw before later modules can use the changed layout; inconsistent input-mixing layouts after callbacks also throw. Console reentry behavior is unknown

  • NGS2 custom UserFx (libSceNgs2.native) - the 48-byte process context, process flags, callback error handling and null-handler behavior retain the existing submixer callback model and are not console-verified. Non-null module options throw because their console error is unknown. UserFx on custom sampler rack 0x4001 throws: its parameter indexing and routing are not implemented. Module id 0x19, the 40-byte voice parameter (handler and three user-data words), parameter id 0x40001900 | index, and lack of option and module state follow fma-rc's PS5 12.70 module reading, including parameter dispatch at 0x25ec4.

  • NGS2 custom Delay (libSceNgs2.native, 0x1d) - processing and defaults remain unverified on PS5. The agreed compatibility path preserves main's PCM pass-through for Void Terrarium (PPSA03061) until any Delay parameter is set; every 0x40001dxx parameter throws. Only one-buffer custom submixers with no module state and a 20-byte option are accepted. Option type 0/1, taps 1..8, length 1..20000 and reserved 0 follow fma-rc's 12.70 module reading. Other shapes and values throw because their console errors are unknown. This preserves host behavior, not console-equivalent Delay processing

  • NGS2 custom module ids (libSceNgs2.native) - Reverb (0x1b) and Convolution (0x23) are not processed: a rack that passes their creation checks throws. Gain (0x15) on custom sampler racks also throws. Per fma-rc's 12.70 module reading, creation returns 0x804A8302 for a wrong non-zero state size, and 0x804A8013, 0x804A8099 and 0x804A8098 for a bad Reverb option size or word and PitchShift word. Unknown: check order, errors for a Gain option, missing Reverb options, Convolution option sizes, and Convolution's state (64 bytes from SDK 3.0). PPSA04540 uses 0x15, 0x19, 0x1b and 0x23 (#8039), PPSA35169 0x20 (#4246) and PPSA33655 0x15, 0x19 and 0x1b

  • NGS2 custom PitchShift (module 0x20) - active processing requires grains divisible by 64. Pitch-down inputs with no selectable overlap throw instead of stalling. A channel bypassed at initialization cannot be enabled until playback restart: this throws instead of reproducing a non-terminating filter loop. Custom sampler and submixer paths support cents -1200..1200, bypass, filtering, waveform alignment and resampling; setup defaults to bypass. Pause/resume/stop fade over 64 samples and restart clears history. Sampled PCM comparisons stayed below 1e-6 and ATRAC9 below 5e-6. The shared sampler uses Q14 phase, four history samples and a 512-phase kernel, producing three initial zero samples at unity rate. No title run has verified progress past the PPSA35169 stop.

  • NGS2 sampler streaming - transitions on grains below 64 throw. Setup flags (currently named channel_mask) are accepted and ignored, as before this change, because PPSA36591 sets 0x10 on a VAG voice and plays on main. In 13.60, bit 0x10 selects an alternate AJM decoder slot (a missing slot reports 0x804A8352 during render); that selection and its error and accounting are not implemented. It is not a speaker mask. PCM/ATRAC9 reference checks cover block capacity, append coalescing, starvation, caches, replacement, callbacks and descriptor replay. Default scheduling processes UserFx before block callbacks, then publishes sampler racks in creation order and voices in rack order. Checks cover callback replacement/disable and peer stopping. External scheduling uses dependency batches; limits are listed below. The custom sampler state layout and size validation remain incomplete.

  • NGS2 custom Gain - PS5 rounding and first-parameter processor state are unverified. The initial previous gain retains main's zero convention; the schema default does not verify processor initialization. Processing before a parameter, after re-setup or after stopping a configured voice throws. The unclamped levels, i/N ramp and equal-gain paths follow the PS5 12.70 reading (0x33ce0, 0x5310); invalid parameter positions return 0x804A835A (0x250b0). Custom sampler Gain and module options throw: their initialization, lifecycle and option errors remain unknown. Integer rendering of nonfinite samples throws because the console conversion is unknown.

  • NGS2 peak meter - 13.42 confirms peak_height at offset 12 in Ngs2SamplerVoiceState and Ngs2SubmixerVoiceState (peak 0.5 and RMS 0.353553 for alternating 16384/0 PCM, no other word in the first 28 bytes changes), and that a sampler SETUP reset clears the detect type until it is enabled again; the submixer reset was not measured. The controls 0x10000009 (sampler) and 0x20000005 (submixer) carry the detect type at offset 8 (0 off, 1 peak, 2 RMS, else 0x804A8093). Each grain stores one value per channel in a ring of num_peak_meter_blocks slots (1 to 256, else 0x804A8092): the largest absolute sample for peak or the sum of squares for RMS; peak_height is the largest channel value, or sqrt(sum / (blocks * grain)) for RMS, over the filled slots. A detect-type change empties the ring, and measurement is after the voice modules.

  • NGS2 custom mastering rack (libSceNgs2.native, rack 0x4003) - follows fma-rc's reading of the 12.70 module: option size is 0x508, matching the custom submixer rack layout. Creation returns 0x804A8052 above 37 channels; channels 9 to 37 throw because voices hold at most 8 channels. Mastering racks with modules throw: attached modules and non-default option fields are unverified on PS5. Voice control parameters 0x40030000 (setup), 0x40030004 (gain) and 0x40030005 (output) configure channels, levels and destination buffer. sceNgs2VoiceGetState fills common voice state flags. PPSA10278 and PPSA04540 create rack 0x4003 without modules (#8039)

  • NGS2 custom buffers - multiple buffers on samplers, submixer channels above 8, inputs beyond 0/1 and multi-buffer chains beyond zero modules or one Gain throw. Default custom module order, UserFx extra-buffer selection and invalid port-buffer errors remain unknown. Input-to-buffer routing and grain clearing follow the PS5 12.70 reading (0x181a0); output-port selection follows KytyPS5. These paths have not been compared with console output. Creation validation order and QueryBufferSize validation remain unverified; the query throws for options whose creation returns an error.

  • NGS2 reverb rack (libSceNgs2.native, rack 0x2001) - follows the PS4 firmware 11.00 libSceNgs2.sprx, read and checked against its output at 11.025 to 48 kHz, including parameter changes during playback (differences at float rounding level); not yet compared with the PS5 library. Structure layouts come from shadPS4's ngs2_reverb.h and the param ids 0x20010000 (setup) and 0x20010001 (I3DL2) from PPSA22520. Only the default reverb_size of 1 is handled, with its 14400-sample reflection buffer; other sizes and the library's half-rate mode throw. System sample rates below about 7.5 kHz, where an allpass delay would have no samples, throw. Setup only accepts equal input and output channel counts

  • sceNgs2ReportRegisterHandler, sceNgs2ReportUnregisterHandler (libSceNgs2.native, NIDs uBIN24Tv2MI, nPzb7Ly-VjE) keep a registry of report handlers. Register rejects a null handler with an invalid argument and returns INVALID_OUT_ADDRESS for a null out handle, then stores the report type, handler and user data under a freshly allocated opaque handle; unregister removes and frees the matching record and throws for a handle that is not registered. The signatures (report type, handler, user data, out handle) and (report handle) follow SharpProspero and shadPS4's ngs2_report.h, and the 24-byte Ngs2ReportDataHeader passed to a handler is its OrbisNgs2ReportDataHeader. No report is produced yet, so no registered handler is ever invoked and PPSA04540, which imports both and registers a CPU load handler (type 5), still receives none.

  • sceNgs2SystemSetUserData, sceNgs2SystemGetUserData, sceNgs2SystemLock, sceNgs2SystemUnlock (libSceNgs2.native) - shadPS4 only checks the system handle (INVALID_SYSTEM_HANDLE) and SharpProspero names what each call does; neither gives the other limits. A null user data pointer throws. sceNgs2SystemLock and sceNgs2SystemUnlock follow prosper's notes on the PS5 module: Lock takes a per-system lock and counts nested holds, Unlock releases one hold from any thread and returns 0 without a hold, and sceNgs2SystemRender only tries the lock: while another thread holds it, Render clears one grain of each output, leaves the render count and voices unchanged and returns 0. The other calls do not wait for the system lock. Peace Walker (PPSA18216) holds it while it spins on a flag that its audio thread clears only after sceNgs2SystemRender and eight sceNgs2VoiceGetStateFlags calls, so on the console neither can wait for it. Whether the console's voice and rack calls take the lock at all is not known. sceNgs2RackLock still holds the library's lock until sceNgs2RackUnlock, as before

  • sceNgs2GetWaveformFrameInfo (libSceNgs2.native) - not measured on a console; shadPS4 only stubs it, and prosper does not cover the call. The outputs are taken to be the frame fields of the parsed waveform info, which prosper's reading of libSceNgs2.native.sprx fills for ATRAC9 with the superframe bytes and samples, the frames per superframe and a one-frame delay, whatever the fact chunk says. PCM_I16L answers channels * 2 bytes, 1 sample, 1 unit and no delay, as for parsed 16-bit PCM, itself assumed. Other types throw. Null outputs return INVALID_OUT_ADDRESS and an ATRAC9 format the codec does not accept INVALID_WAVEFORM_FORMAT; the codes are unverified

  • sceNgs2RackSetUserData, sceNgs2RackGetUserData (libSceNgs2.native) - the signatures follow SharpProspero and shadPS4, which only logs them; neither gives an error. A handle that is not a live rack answers INVALID_RACK_HANDLE before a null user data pointer is checked, and the null pointer throws, as in sceNgs2SystemGetUserData. A new rack starts with 0. Not measured on a console

  • sceNgs2RackGetInfo (libSceNgs2.native) - detached queries are deliberately rejected: the reference faults while reading the absent owning system, even with a valid 232-byte output. Custom extended queries that would write past the supplied size also throw instead of reproducing the reference overflow. The 232-byte base, family extensions, untouched bytes, owned custom-module options, per-system rack UIDs, rack-local render counts and default-configuration active counters are checked against the reference. Profiling-enabled configurations remain unverified; observed default configurations publish zero process ratio and tick. PPSA13356 passes 232 bytes and reads the count at offset 164, as recorded in #10037; that field is preserved by the corrected layout.

  • NGS2 system option checks (libSceNgs2.native) - not verified on a console. sceNgs2SystemQueryBufferSize, sceNgs2SystemCreate and sceNgs2SystemCreateWithAllocator return 0x804A8013 (size), 0x804A8311 (max grain, a multiple of 64 up to 2048), 0x804A8310 (grain, a multiple of 64 up to the max), 0x804A8051 (one of ten sample rates) and 0x804A8052 (1 to 37 channels) in that order, following prosper's PS5 module analysis.

  • NGS2 external job managers - supports all four manager lifecycles and slot 0 rendering, with the 112-byte scheduler option, capacity checks, query/init error propagation, reverse cleanup after failed initialization and slot-order destruction. Custom and default-pool comparisons cover synchronous and deferred submissions, dependency barriers, concurrent workers, completion before callbacks and sampler state publication. Native tests use host kernel adapters, not console execution. The host retains job contexts until join. Very small native batch-storage reuse is not an equivalence oracle.

  • NGS2 worker control updates - Setup/block/filter/patch updates, raw module commands, rack creation, system grain/rate changes, exclusive locks and recursive rendering from active jobs still throw. Slots 1 to 3 have manager lifecycle support but no sceNgs2Stream* routing. Supported events and render parameters retain the current grain snapshot; port volume/matrix products ramp over the next grain. Queries expose pending port/matrix values and PLAY. Paused samplers finish decode-ahead before stopping. Matrix-info requires 5,480 bytes. Host-adapted native checks cover worker order, event reduction, copied matrices and PitchShift updates at 256 samples. Active 64-sample PitchShift reports reference buffer-integrity errors and is not an equivalence oracle. KILL/restart is checked before downstream mixing; other callback dependency positions remain unverified.

  • NGS2 mixer and custom UserFx worker controls - Other custom-module parameters, including Gain, and raw worker command encodings still throw. Custom mastering modules and additional callback dependency positions remain unverified. Oversized inactive-master output buffers differ: the reference clears the full capacity; the host clears one grain. Supported mixer events, handler replacement and UserFx2 parameters preserve the current render snapshot. Submixer STOP fades its final grain; KILL suppresses current output and sends a final callback next grain. Paused callbacks continue. Mastering keeps its distinct envelope behavior. Failed UserFx2 edits remain in control storage without publishing to rendering; later controls see them. Native comparisons use host kernel adapters, not console execution. This does not establish full custom-FX or stream support.

  • NGS2 UserFx2 activation and control reentry - Additional callback dependency positions, UserFx2 work/state layouts and custom mastering modules remain unverified. Same-voice control/query reentry waits in the reference; the host throws, as it does for A-to-B-to-A cycles and destruction/rendering of a live control owner. These guards are host behavior, not native error codes. Modules activate only after control. Setup restores the initial parameter image without rerunning setup callbacks. Failed edits remain in control storage and activate on a later PLAY, including failures before first PLAY. Process callbacks buffer self-controls until the next grain; control callbacks can query/control independent voices. Native comparisons use host kernel adapters; guard tests are host-only, with reference waits independently observed.

  • NGS2 cross-thread control/process callbacks - Same-voice callback joins and cross-thread dependency cycles still wait in the reference and require caller coordination. Host-adapted native checks cover independent-voice handoffs, process self-handoffs, successful/failed controls under contention, query serialization, cleanup, system destruction and render/control overlap. Control callbacks retain per-voice ownership while releasing the global mutex; unrelated voices progress. API calls pin rack/system storage while waiting. Rendering waits before snapshot publication, without blocking peer controls. Handles become unavailable before rack cleanup. System destruction detaches live racks; explicit rack destruction later invalidates their handles. These checks use host kernel/TLS adapters, not console execution.

  • NGS2 UserFx2 lifecycle callbacks - Additional option layouts and retained callback context pointers remain unverified. C++ exceptions use host cleanup semantics: unpublished construction is discarded and detached cleanup storage is freed before rethrowing. Setup/cleanup callbacks release the global mutex for independent controls, renders and rack operations. Racks publish after setup and attachment; destroying the target system during setup returns INVALID_SYSTEM_HANDLE. Cleanup follows handle invalidation, disconnection and detachment. Setup uses a shared module template copied to voices afterward; cleanup receives that template in module/voice order. Negative setup skips cleanup; negative cleanup skips that module's remaining voices without failing destruction. Native comparisons use host kernel/TLS adapters, not a console.

  • NGS2 detached racks - Detached RackGetInfo deliberately rejects a verified reference fault. Additional option layouts and callback dependency positions remain outside the checks. No public reattachment path was found; attachment is called only by rack construction. System destruction retains rack storage, handles, parameters, work and state, clears active routes and preserves configured destinations. Explicit rack destruction releases storage through its original allocator. Detached filter controls own their parameter copy and defer coefficients until attachment. New detached controls apply earlier queued worker updates before reset/setup. Native comparisons cover sampler/custom-FX state, released-system buffer overwrite, matrices, ports, filters and delayed cleanup under default/external schedulers using host adapters, not console execution.

  • sceNgs2SystemSetGrainSamples, sceNgs2SystemSetSampleRate (libSceNgs2.native) - a grain that is not a multiple of 64 is accepted, where the module returns 0x804A8310, because the NGS2 tests render 8-sample grains. Changing the rate while a sampler filter is enabled throws, as the filter coefficients were computed for the old rate. After the handle check, a grain of 0 or above the system's maximum returns 0x804A8310, and a rate other than 11025, 12000, 22050, 24000, 44100, 48000, 88200, 96000, 176400 or 192000 returns 0x804A8051, per prosper's reading of the module's command validators; not measured on a console

  • sceNgs2VoiceQueryInfo (libSceNgs2.native) - only info id 0x4001 is known: PPSA22520 passes an 8-byte buffer and branches on the first word being 1 or 2, so it is assumed to be the voice channel count (0 before the voice is set up); the second word is zeroed and other ids throw

  • sceNgs2SystemCreateWithAllocator free handler (libSceNgs2.native) - an allocator with an alloc_handler but no free_handler throws after the option checks: the module only checks the alloc_handler, and what it does without a free handler is unknown. Otherwise sceNgs2SystemCreate returns 0x804A8020 for a null buffer info or host buffer, and sceNgs2SystemCreateWithAllocator 0x804A8023 for a null allocator or alloc_handler, before the null-handle 0x804A8010 and the option checks, per prosper's reading of the module; not measured on a console

  • sceNgs2VoiceGetOwner (libSceNgs2.native) - the signature (voiceHandle, outOwnerRack, outVoiceIndex) follows SharpProspero and shadPS4, which only logs it; neither gives an error. The errors are unmeasured: a handle that is not a live voice answers INVALID_VOICE_HANDLE before the outputs are checked, as in sceNgs2RackGetVoiceHandle, and either output pointer null answers INVALID_OUT_ADDRESS without writing the other

  • sceNgs2VoiceGetMatrixInfo (libSceNgs2.native) - a matrix id past the rack's max_matrices throws, as the PS5 code for shadPS4's PS4 INVALID_MATRIX_INDEX is unknown. A matrix without levels reports 0 levels, though it mixes through the default channel map. Signature from SharpProspero, layout (a count and 64 levels) from shadPS4; levels are the stored, clamped ones. Unmeasured: a null info answers INVALID_OUT_ADDRESS and a size other than 260 INVALID_OUT_SIZE before the voice is checked, as in sceNgs2VoiceGetPortInfo

  • sceNgs2CustomRackGetModuleInfo (libSceNgs2.native) - a size over 32 bytes throws, as the longer per-module info in shadPS4 is not kept. A size under 32 and an index past the rack's modules (any on a non-custom rack) also throw: the PS5 codes for shadPS4's PS4 INVALID_MODULE_INDEX and INVALID_MODULE_INFO_SIZE are unknown. It repeats the ids, state offset and size from rack creation, reserved words 0, as SharpProspero lays it out. Unmeasured: a null info gives INVALID_OUT_ADDRESS, then a bad handle INVALID_RACK_HANDLE

  • NGS2 patch destinations - a rack handle with input 0 resolves to its first voice, matching the Dead Cells call in #4334; selection on multi-voice racks remains unverified. Input 1 is supported only for a voice handle in a two-input custom submixer. Nonzero rack-handle inputs, other unsupported inputs and nonzero inputs on disconnected ports throw because their contracts are unknown. GetPortInfo reports the resolved voice handle and selected input, with zero delay. Changes to a port destination or input while its source is rendered throw before mixing: callback routing order is unverified, and combining the old destination with the new input is invalid.

  • NGS2 PCM waveform parsing (libSceNgs2.native) - sceNgs2ParseWaveformData reads integer PCM (tag 1, or WAVE_FORMAT_EXTENSIBLE with the PCM GUID) of 8, 16, 24 and 32 bits as types 0x11, 0x12, 0x14 and 0x16, and float (tag 3) of 32 and 64 bits as 0x18 and 0x1a, and returns 0x804A8432 for other depths, after prosper's reading of libSceNgs2.native.sprx; not measured on a console. Every depth keeps the checks of the 16-bit path (channels, rate, block align, whole frames, a looped smpl chunk throws), which that reading does not apply

  • sceNgs2ParseWaveformFile (libSceNgs2.native) - the signature (path, offset, info) is taken from the call site of PPSA21402, which sets only three argument registers; the file is read from offset to its end, the data and block offsets are taken to be relative to the start of the file, not of offset, and an unreadable file throws. The audio unit fields of a 16-bit PCM waveform are assumed to be one sample frame per unit and per frame; INVALID_WAVEFORM_DATA for a data chunk that runs past the buffer or ends inside a frame is assumed, and looped PCM and other PCM formats throw

  • NGS2 waveform format routing (libSceNgs2.native) - an extensible fmt chunk of 0x34 bytes whose GUID is neither PCM nor ATRAC9, which the module parses as ATRAC9 without checking its config, and the GUID of waveform type 0x43 throw. Otherwise a tag other than 1, 3 or 0xFFFE, an extensible fmt chunk under 0x28 bytes and an unknown GUID return 0x804A8432, per prosper's reading of the module; not measured on a console

  • sceNgs2VoiceControl sampler filter (libSceNgs2.native) - param 0x1000000a, its layout and meaning follow KytyPS5 only: location 1 type 1 is an RBJ low-pass biquad at the system sample rate after resampling, scaled by level, a set channel_mask bit bypasses that channel, type 0 turns the filter off. Other locations and types throw. The voice keeps playing a filter tail after its last block until the history is zero, with outputs below 1e-20 flushed to zero (a KytyPS5 choice); the console's tail length is unknown

  • sceNgs2PanInit / sceNgs2PanGetVolumeMatrix (libSceNgs2.native) - inputs on which the PS5 libSceNgs2.native.sprx of firmware 3.20 and 4.03 did not return within 60 s throw; whether it returns at all for them is unknown. They are an infinite speaker or param angle, an angle too large for a turn to change it, a speaker angle that wraps to exactly the unit angle, and a param angle that wraps onto the first speaker plus one turn, such as one float below the first speaker in radians

  • sceNgs2GeomResetListenerParam, sceNgs2GeomResetSourceParam (libSceNgs2.native) - the structures (12, 16, 16, 60, 96, 108, 32 and 308 bytes) come from KytyPS5's ngs2.cpp and match shadPS4's ngs2_geom.h field for field, but only KytyPS5 gives the behaviour - shadPS4 logs and returns success without writing the output. The defaults (orient front +Z, orient up +Y, sound speed 343, cone 1/360/1/360, rolloff 0/1000000/1/1, doppler factor, full-band, LFE and maximum level 1, two speakers and matrix format 2) are unverified on a PS5 title; KytyPS5 and iStark/PS5PCEM agree on them. PPSA15552 (Dead Cells) calls sceNgs2GeomResetSourceParam after creating its racks. A null output address returns INVALID_OUT_ADDRESS as elsewhere in the library rather than throwing as KytyPS5 does. sceNgs2GeomApply is now a minimal pass-through that follows KytyPS5's Ngs2GeomApply (shadPS4 only stubs it): pitch 1, source position, volume the larger of the source minimum and maximum level, and a diagonal of the source maximum level (1 when it is not positive) over matrix_format channels (0 is two, at most 8). The listener and flags are ignored, so source attenuation, distance rolloff, panning and Doppler stay unimplemented; neither KytyPS5 nor this has been measured on a PS5, and a null output address returns INVALID_OUT_ADDRESS where KytyPS5 exits

  • sceNgs2GeomCalcListener builds an orthonormal world-to-listener transform. The row-major matrix, front-axis priority and flag 1 for right-handed input follow PS5PCEM; they have not been measured on PS5 hardware. Velocity stays in world coordinates and positive finite sound speed is preserved. Orientation vectors are normalised and up is made perpendicular to front, so non-unit and slightly tilted vectors are accepted. When front and up are parallel, up is replaced by (0,1,0) or (1,0,0) so the basis stays defined: PPSA15552 (Dead Cells) passes orient_front={0,0,1} with orient_up={0,0,1} after moving the listener, which PS5PCEM rejects; the console error code is unknown. Zero orientation vectors, nonfinite input and an unrepresentable translation still throw without changing the output; console error codes are unknown, and a nonpositive sound speed throws where PS5PCEM and KytyPS5 default it to 343. KytyPS5 always writes the identity matrix, so the transform rests on PS5PCEM plus that Dead Cells case. Dead Cells (PPSA15552) reaches this call after the custom sampler rack in #4334. This does not implement source attenuation, panning or Doppler in sceNgs2GeomApply.

  • NGS2 custom sampler rack (libSceNgs2.native, rack 0x4001) - implements bounded support for the custom sampler rack and its built-in module 0x13 (Custom Voice Filter), unblocking PPSA15552 (Dead Cells) startup. Structure layouts come from shadPS4's ngs2_custom.h (OrbisNgs2CustomVoiceFilterParam, 40 bytes) and live trace correlation from prosper's hle_audio.cpp (0x40001300 command and parameters like 10000.0f and 0.707f). Routes parameter updates via the 0x40001300 command family into the Biquad filter engine. Filter type 0 clears the destination filter; type 1 configures the RBJ low-pass biquad frequency, Q and level. Other filter types and unmodeled configurations throw.

  • sceNgs2VoiceGetState custom sampler (libSceNgs2.native, rack 0x4001) - only the size and one field come from a title. PPSA15552 (Dead Cells) calls it on custom sampler voices with a 48-byte buffer at two sites (eboot 0x1740f90, 0x1741009) and reads only the 64-bit value at offset 16: the first site keeps it and the second subtracts the kept value, so it is filled with the voice's decoded sample count. Other sizes return INVALID_OUT_SIZE as for the other racks. The state flags fill the common voice state; the remaining fields stay zero. shadPS4's OrbisNgs2CustomSamplerVoiceState is about 80 bytes and does not match the size this title passes, so the field names and the console's value are unverified

  • sceNgs2CalcWaveformBlock (libSceNgs2.native) - an ATRAC9 config whose sampling-rate index (bits 20 to 23) is not 1, 4 or 7 throws, where the module reads 0 frame samples from its table and divides by zero. Every type follows prosper's reading of the PS5 module and its entry point: linear PCM and float (0x10 to 0x1b), VAG (0x1c) and ATRAC9 (whole superframes from the config alone, a skip of one frame of decoder delay plus the position in the superframe, modulo 2^32), the null checks and the 0x804A8432 of other types. Closes when: the other sampling rates are known

Functional

  • NGS2 rack lock and voice callbacks - Other threads' voice/rack API behavior during a rack lock and the console unlock error remain unmeasured. Rack locks nest per calling thread and exclude renders and destruction across threads/systems. A callback waiting for another thread's rack lock or render cannot progress. Other NGS2 calls may continue; block callbacks release the internal mutex. PPSA36591 previously froze when its main thread held a rack lock while waiting on a lock owned by sceNgs2VoiceGetStateFlags. Unlock without ownership returns 0x804A8202, whose console code is unknown. UserFx callbacks release the global mutex while retaining render or per-voice ownership.

  • NGS2 destroy from its own render (libSceNgs2.native) - sceNgs2RackDestroy of a rack of the system being rendered, or sceNgs2SystemDestroy of that system, called from one of that render's voice callbacks throws, also when the callback renders another system whose own callback makes the call, because the render would go on using the destroyed rack. The console's behaviour is not measured.

  • sceNgs2RackGetVoiceHandle voice index (libSceNgs2.native) - an index at or beyond the rack's voice count returns 0x804A8305 and leaves the output handle untouched, after the null-output and rack-handle checks that keep their order and codes. The value is read from the PS5 libSceNgs2.native.sprx export MwmHz8pAdAo (firmware 10.01 at 0x11f10, 12.70 at 0x12130, and every module from 1.00 to 12.70 checked in #5916): an index at or past the rack's voice count returns it through the same error helper that answers 0x804A8010 for a null output, and the output handle is written only on success. The rack is checked before the output pointer, and an invalid rack returns 0x804A8202. Heretic + Hexen (PPSA26525), DOOM + DOOM II (PPSA21444) and STAR WARS: Dark Forces Remaster (PPSA19728) create a one-voice reverb rack, take voice 0 and ask for voices 1 to 3 at start-up, log the failures and go on

  • PitchShift channel-mask width - processing 32 or more active voice channels throws before any 32-bit shift. The bypass and initialization masks remain 32-bit; broader channel semantics are unverified. Rack capacity alone does not establish an active voice channel count.