sceNgs2ParseWaveformFile read everything from the offset to the end of
the file into a zero-filled buffer and parsed that, although parsing
uses only the RIFF chunk headers and the fmt, fact and smpl payloads.
A waveform at an offset in a sound bank cost a read of the rest of the
bank on each call.
ReadChunks now takes the bytes through an accessor. Waveform data passes
its buffer; a waveform file seeks to and reads the headers and those
payloads alone, with the same checks against the length from the offset
to the end of the file. The format dispatch both use moves to
ParseWaveform.
ngs2_parse adds a bank of two waveforms in one file, the second with a
chunk after its samples, and parses each at its offset.
PPSA21402 (Balatro) parses its five 33 MB music tracks at start: one
call took 8.3 to 26.7 ms and allocated 33 MB, and now takes 0.01 to
0.04 ms with the same result.
Keep logical sample and skip counts across byte-only continuation buffers, assemble split superframes, and allow callbacks to refill, pause or reset the stream. Preserve decoded audio while waiting for input and reject truncated closed streams.
Validated with seven NGS2 tests, an ASan/UBSan streaming test build, and PPSA03747 repeatedly supplying continuation buffers during playback. Flag semantics follow the pinned KytyPS5 source documented in TechnicalDebt.md.
Written with AI assistance.
The call site of PPSA21402 sets only three argument registers, so the function has no size parameter. A data chunk that runs past the buffer or ends inside a frame returns INVALID_WAVEFORM_DATA instead of being shortened. The test no longer writes padding from a string literal.
LibAtrac9 read its bitstream without a length, so a corrupt ATRAC9 frame
made the decoder read past the end of the guest's buffer. Update the
submodule to 946e05a ("Prevent bitstream overruns"), whose decode
functions take the buffer size, and pass the bytes left in the
superframe from NGS2, AJM and Audiodec. The callers already reject a
frame that consumes more than the superframe holds.
ngs2_atrac9 places a synthetic corrupt superframe right before an
inaccessible page and expects the render to report the decode failure;
with the previous LibAtrac9 it crashes with a segmentation fault.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5WJS4ZdQynAJesCZKH5hb