An .spc is a Super Nintendo's sound chip, frozen. The SNES has a second computer for audio -- the SPC700, with 64 KB of its own RAM and a DSP that plays compressed samples out of it -- and this file is that computer mid-tune: the CPU registers, every byte of RAM, and the DSP's 128 registers. A player loads the image and lets the program run. There is no score to parse. What there is: a tag, a machine state, and a bank of samples the DSP knows how to find.
Every SPC is 66,048 bytes before its optional tail: a 256-byte header, 65,536
bytes of RAM, 128 bytes of DSP registers, 64 unused, 64 of the boot ROM area. Then, usually, an
xid6 chunk carrying the rest of the tag.
Thirty-three bytes of magic, then three bytes the specification describes as a signature and a tag flag, then the CPU state, then the tag. The bytes are from a real file.
The SPC specification has travelled with every player since 1999, and real files disagree with it in three places. Each is the kind of thing only a pile of files can show.
The tag flag. The spec says byte 0x23 is 0x26
when an ID666 tag follows and 0x27 when it does not. Real files carry
0x1A there -- bytes 0x21 to 0x23 are three DOS
end-of-file markers, so a tune printed to a console shows its magic and stops -- and they
carry a full tag regardless. A reader that obeys the flag reads every file as untagged.
Telling the two spellings apart. The tag's length and fade are text in one spelling and packed numbers in the other, and the spec suggests looking at the date to tell which. Real dumpers leave the date empty in both spellings. The seconds slot is the tell: digits means text, anything else means binary, and an empty slot is text with the length simply not written.
The emulator byte. In the text spelling it is written as the character
'0', not the number 0. The spec does not say so.
The title, game, dumper and comment slots are the same in both. From the date onward they differ, and the artist moves by one byte:
Read the binary artist at the text offset and its first letter vanishes: "Akihiko Mori" becomes "kihiko Mori". A reader that is one byte off is always one byte off in the layout, never in the font.
A third spelling, from one dumper. Files with the v0.20
magic and 0x1B at byte 0x23, dumped in the summer of 1999, leave the text slots
empty and put a 20-character title at 0x30 -- two bytes late -- and the date at
0xD0 as day, month and a little-endian year, exactly where the text spelling keeps
its disable and emulator bytes. Some v0.10 files use the same 0x30 title slot,
space-padded, with a binary length. A reader that takes the title from 0x2E sees an empty
slot and calls these untitled.
DSP register 0x5D, DIR, names a page of RAM holding the
sample directory: 256 entries of four bytes, a start address and a loop address each.
Every entry that points inside RAM looks like a sample.
Most of them are not. The directory is a table the hardware reads by index,
and a sound engine leaves it full of whatever was there: addresses from other tunes, from
the game's other banks, from nothing. Two thirds of real files have directory entries that
overlap each other and the program code. What the DSP actually dereferences is named by the
eight SRCN registers, one per voice at 0x04 + voice * 0x10: the entry
each voice is set to play. Those are the real samples, and those alone.
Samples are Bit Rate Reduction, the SNES's own ADPCM: nine-byte blocks, each a header byte and sixteen 4-bit samples. The header carries the shift, the filter, and two flags: END and LOOP. A sample runs from its start address until a block with END set. Whether it loops is the LOOP bit of that same last block -- the directory's loop address says where to, not whether.
The 256-byte header has room for a title, a game, an artist and a length.
Everything else -- publisher, year, disc and track, intro and loop lengths to the
1/64000th of a second -- lives in a chunk after the image: xid6, a size, then
sub-chunks of a one-byte ID, a one-byte type, and a two-byte length or value, each padded
to four bytes. The spec presents it as an optional extension. Nearly every real file has
one, and it is where the metadata is.
An .rsn is a RAR archive of SPC files, renamed so a player will
open it. It works because every tune from one game shares its engine and most of its
samples, and RAR's solid compression stores the shared bytes once.
The SPC700 is little-endian and so is everything here: the program counter, the directory entries, the packed tag numbers, the xid6 lengths.