SID File Structure

A project log for SIDman player

A project about playing C64-era "SIDtunes" with a Teensy4, a 6502 processor and a SID (clone) chip

foxhoodFoxHood 05/13/2023 at 17:510 Comments

YES. I know its been two years since my last blog, but this project ain't dead. I was just busy dealing with College and bagging myself a Bachelor in Electrical Engineering. Which i now hold!! So hopefully i can revive and work on this project proper from now on!!

The High Voltage SID collection stores the SID code in specialized .sid files. These files consist of a Header, followed by the actual 6502 Machine code. For proper playback a player needs to read the header in order to figure out what kind of SID music is being played and how it has to be prepared. Luckily the archive comes with a file format text file that goes through all the data that can be found in the header. For convenience i compressed it into a table with the relevant fields and their offset from the start.

four character String containing either "PSID" or "RSID".
Informs the player what kind of file is being dealt with.
+0416-bit field containing Version of 1 to 4.
Depending on the version, there may be more data in the header.
+0616-bit field containing the DataOffset.
Points the where the machine code portion begins. Should be static depending on the version
+0816-bit field containing the LoadAddress.
This is the location in the RAM from which the machine code has to be loaded into.
If the LoadAddress is 0. The first two bytes of the machine code are expected to indicate  LoadAddress.
16-bit field containing the initAddress.
This is the address of the data subroutine that must be run by the processor to start playback. Special note is that when the initAddress is called the file will switch song based on the number stored in the accumulator register.
If the initAddress is 0. The LoadAddress is expected to double as init.
+0C16-bit field containing the playAddress.
The address that is to be called repeatedly for music to play. Normally the address called by the IRQ handler.
If 0. The code is expected to set up the interrupt service handler itself during init.
+0E16-bit field containing the number of songs.
Specifies the number of songs available in the file. Used to know what kind of accumulator values would be accepted when calling the initAddress
Is always at least 1 (never 0)
+1016-bit field containing the default Starting Song.
Specifies the default song to be played one load
+1232-bit field containing the Speed setting. Each bit corresponding with a song number and indicating whether the playback is based on the vertical blank interrupt (50hz/60hz based on PAL or NTSC) if bit=0 and based on the CIA1 timer interrupt (60hz) if bit=1
+76Starting point of Data for Version 1 SID files.

This is the extent of data found in V1 headers and for basic operation of old PSIDs it is enough, but it does lack a bit in regards of specifics. For example it doesn't tell you whether the file is meant for a PAL or an NTSC device, which has dramatic effects on how it sounds. Other versions (2,3 and 4) include an expansion on the header which provides more data:

A 32-bit "Flags" value. Stores bitwise data:
b0 :  Indicates built-in player [0] or Compute! player [1]
b1 : Specifies C64 compatible PSID [0] or PlaySID specific/C64 Basic [1]
b2-3:  Specifies Video standard:  01=PAL, 10=NTSC, 11=Both, 00=Unknown
b4-5:  Specifies SID chip used: 00=unknown, 01=6581, 10=8580, 11=both
b6-7:  Specifies second chip. same as above. Only used in Version 3 and 4
b8-9:  Specifies third chip. Same as above. Only used in Version 4
Rest is reserved and should be set to 0
+788-bit field containing startPage
Indicates if there is free space for a music driver. If 0. Anywhere outside of the data block is accessible. If 0xff: No space exists. Anything else indicates the high-bytes of  a memory page that has space.
+798-bit field containing pageLength
This informs how many pages of memory are available from the address indicated by the startPage. Every page is a byte of addresses.
+7A8-bit field containing secondSIDAddress
Indicates the address used by a secondary SID chip. This chip can occupy a part of the memory starting $Dxx0. The value of the field containing the two characters that go in the middle (e.g. 0x42 = $D420)
Only used in Version 3 and 4
+7B8-bit field containing thirdSIDAddress
Works the exact same as secondSIDaddress. Except indicating the third chip.
Only used in Version 4
+7CData start address

The V2/3/4 expansion provides a lot more specifics in regards of what the system may exactly entail. Including NTSC/PAL operation, which model SID chip the music was created for, needs special data from a player, if RAM is available and what addresses any other SID chips may have been assigned. All valuable data for a player that seeks to adapt to the file being loaded.

Noted is that the Version number doesn't so much indicate a header version, but actually how many SID chips are present. With version 2 only one, Version 3 having two and Version 4 having three separate SID chips. This can make it a lot easier to determine if a music file is compatible with one's player AND whether to switch the output is to either be stereo or mono.

Note on clock sources:

Judging by the information. It seems that a SID file may either use a raster interrupt from the VIC chip, or a interrupt from the CIA chip, configured by the speed field. It may be prudent to check SID files and ascertain whether they often are using a VIC or the more precise CIA and if special care is needed to ensure proper run-time with either. In RSIDs the VIC is expected to not be used.

This means going back to the Debug simulator soon and observe if players are actually using VIC registers, As during the RSID Investigation this wasn't observed as happening.

The Text file actually has some info for a default environment and how a player could read if its on a PAL or NTSC device ($02A6 holds a switch for that). what values to set in the CIA. It also suggests that a player using CIA timing for playroutine can ignore clocks altogether and alter the set time.

SONG Length:

The duration of a song is not found within the SID file itself, but is instead stored externally in a file called "Songlength.md5".

This file contains a a massive list of MD5 keys followed by time. These keys match the checksum generated of SID files. The idea being that you can generate the checksum of a SID file and then look for a match within the list.

The file is built in a INI like format:

So for a player to be able to know how long any song takes, it needs to be able to generate a MD5 checksum on the spot of the SID file to be played (incl header) and then compare it to the many keys within the songlengths.md5 file till it finds a match. Multiplying the timestamp untilll it has the right time in milliseconds.