From 9465073add017c3419cf1d7a90e981aa2edcce25 Mon Sep 17 00:00:00 2001 From: Rix Date: Thu, 29 Oct 2026 17:14:01 -0700 Subject: [PATCH] SPUDUMP: 64-byte sample data, the loop point's loop, reference player limits. Sample data payloads must be a multiple of 64 bytes: the SPU DMA moves whole 64-byte blocks, so a player reads past a shorter payload. The loop point text now says when a pattern is set to loop: the order table loops from its last entry back to that same entry. A note lists the fixed table sizes of nugget's spdplayer. --- SPUDUMP.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/SPUDUMP.md b/SPUDUMP.md index 1499d3f..5343893 100644 --- a/SPUDUMP.md +++ b/SPUDUMP.md @@ -87,7 +87,7 @@ Each packet consists of a header and a payload. The header is 4 bytes long: - **End of pattern (0x02)**: The payload size is 0. Signals that the current pattern is complete. The player advances to the next entry in the current order table and begins processing the corresponding pattern. If the current order is the last entry, behavior depends on the order table's loop setting. -- **Loop point (0x03)**: The payload size is 0. Marks the current stream position as the loop restart point within the current pattern. When the player reaches the end of pattern (0x02) and the pattern is set to loop, it returns to this position. Only one loop point per pattern is valid; a second loop point overrides the first. +- **Loop point (0x03)**: The payload size is 0. Marks the current stream position as the loop restart point within the current pattern. When the player reaches the end of pattern (0x02) and the pattern is set to loop, that is the order table loops from its last entry back to that same entry, it returns to this position instead of the start of the pattern. Only one loop point per pattern is valid; a second loop point overrides the first. - **Trace begin (0x04)**: The payload size is 0. Indicates that all preceding packets were synthetically generated to restore SPU state, and that subsequent packets represent actual captured data. This is analogous to the GPU dump format's trace begin packet. For composition-driven files, this packet is not required. @@ -134,7 +134,7 @@ Each packet consists of a header and a payload. The header is 4 bytes long: The payload consists of: - 1 word: SPU RAM base address in 8-byte units. - - Remaining words: raw ADPCM data, to be DMA'd contiguously starting at the base address. + - Remaining words: raw ADPCM data, to be DMA'd contiguously starting at the base address. Its length must be a multiple of 64 bytes, padded with zeroes if needed: the SPU DMA moves whole 64-byte blocks, so a player may read up to 60 bytes past a shorter payload. ### Timing Packets @@ -179,6 +179,15 @@ A minimal player performs the following steps: Seeking to an arbitrary order position is accomplished by setting the current order index and jumping to the corresponding pattern's stream offset. Because each pattern begins with a full SPU state snapshot, no history is required. +### Player limits + +The reference player, nugget's `spdplayer`, has fixed-size tables. A file meant for it should stay within them; the player ignores what does not fit: + +- 256 entries per order table, and 16 order tables. +- 256 pattern headers. +- 128 samples in the sample directory. +- 256 macros (indices 0-255), of up to 8 register writes each. + ## Usage Notes - For composition-driven files, the SPU state snapshot at the head of each pattern should write all registers for every voice used by the song, including volume, pitch, ADSR, and sample address registers. Voices not used by the song should not be touched, leaving them available for sound effects.