*** SID/PSID (Various SIDPlay / PlaySID Formats) *** Document revision: 1.2 *** Last updated: March 15, 2004 *** Contributors/sources: LaLa, Peter Weighill The data files used by SIDPLAY contain binary C64 data and music player machine code. Both, the programmer on the C64 and this emulator need information on how to access the code inside the binary file. That means, information like the memory location to load the file to, the number of tunes, the starting address of the executable code and its subroutines. This specific information has to be delivered in either a separate file - which is often called info file - or in form of a header in the single binary data file. A standalone C64 data file without a header or without a corresponding info file is considered invalid. It is recommended that you get accustomed to one-file sidtunes with the *.sid extension. For raw C64 binary files the extension .c64 or .prg is preferred in order to be able to assign a .sid extension to the additional info file. Supported and merely used file formats are: PlaySID single-file-format (widely known as PSID) PlaySID info-file-format (Raw C64 binary file plus Amiga Workbench icon tooltype file .INFO) SIDPLAY info-file-format (Raw C64 binary file plus SIDPLAY ASCII text info file, previously .SID) C64 Sidplayer format (.MUS/.STR) Raw data or PSID files have appeared as *.data, *.psid or psid.*. DAT files The .DAT file name extension has been introduced by the early versions of SIDPLAY/DOS. It has never been used to specify a file format. Its main use has been in assigning a unique file name extension to any sidtune file, but especially raw C64 data files, and allowing to use .SID for additional info files. INFO files These are Amiga Workbench tooltype icons containing binary graphics data and ASCII text information strings. They have been used by PlaySID and are supported by SIDPLAY. Their file name extension normally is .info or .INF. This is a two-file format. A separate C64 binary data file is required. On Amiga the corresponding C64 data files usually haven't had filename extensions. However, they might have been renamed on other systems. SIDPLAY info files These are plain ASCII text files which have been introduced by the earlier versions of SIDPLAY/DOS. They are used to be able to alter the information inside with a normal ASCII text editor. They can be converted to a single file that contains a binary header. This is a two-file format. A separate C64 binary data file is required. Notice that each pair of files usually has the old DOS-naming of .SID for the info file and .DAT for the C64 data file. The SIDPLAY info file is derived from the information inside the PlaySID one-file format. It is structured like this: SIDPLAY INFOFILE ADDRESS=<loadAddress>,<initAddress>,<playAddress> SONGS=<total>[,<start>] SPEED=<hexValue> NAME=<name of music/tune> AUTHOR=<name of author/composer> COPYRIGHT=<year/name of copyright owner/company> RELEASED=<year/name of copyright owner/company> SIDSONG=<YES|NO> RELOC=<hexValue>,<hexValue> CLOCK=<PAL|NTSC> SIDMODEL=<6581|8580> COMPATIBILITY=<R64|BASIC> The first line of the text containing ``SIDPLAY INFOFILE'' is only used to identify the type of file. ADDRESS=<loadAddress>,<initAddress>,<playAddress> Each specified address is a 16-bit effective C64 memory location in case insensitive hexa-decimal notation without a prefix, e.g. C000 or E012, but neither $FCE2 nor 0xFCE2. Preceding zeroes are ignored. <loadAddress> is the C64 memory location where to put the C64 data. 0 means, the data is in original C64 format, i.e. the first two bytes contain the little-endian load address (low byte, high byte). Please don't explicitly specify the load address unless required for sure. If the load address is explicitly specified, some sidtune converters and utilities conjecture that the C64 data lacks its load address. Hence they move it in front of the C64 data. This would create two redundant bytes if the C64 data already had a load address in the first two bytes. Additionally, those extra bytes in the beginning can confuse disassemblers. <initAddress> is the start address of the machine code subroutine that initializes a song by accepting the contents of the 8-bit 6510 Accumulator as the song number parameter. 0 means, the address is equal to the effective load address. <playAddress> is the start address of the machine code subroutine that can be called frequently to produce a continuous sound. 0 means, the initialization subroutine is expected to install an interrupt handler, which then calls the music player. If so, the value in the bank-select register $01 determines whether the IRQ vector $0314/$0315 (Kernal-ROM on) or the IRQ vector $FFFE/$FFFF (Kernal-ROM off) is to be used. SONGS=<total>,[<start>] <total> is the decimal number of songs (or sound effects) that can be initialized by calling the init address. The minimum is 1. <start> is the decimal number of the song to be played by default. This value is meant as a proposal and is optional. It has a default of 1. It often specifies the first song you would hear upon starting the program is has been taken from. SPEED=<value> <value> is a value in case insensitive hexa-decimal notation without a prefix. Preceding zeroes are ignored. The value contains information about the speed of each song. For each song a bit is reserved, bit 0 for song 1, bit 1 for song 2, and so on. A bit set to 0 means, the music player subroutine is called at 50 Hz. A bit set to 1 means, the real speed is indicated by the CIA 1 Timer A $DC04/05, which defaults to 60 Hz. To not break compatibility to the PlaySID formats, use a maximum of 32 bits, which is equal to 32 songs. Due to a bug in PlaySID, the PSID format can only handle up to 8 songs correctly. On the contrary, the SIDPLAY info format is extended to 256 bits, which is equal to 256 songs. Examples: SPEED=0 replays every song at 50 Hz speed. SPEED=1F replays songs 1-5 at 60 Hz speed, all other songs at 50 Hz speed. NAME=<name of music/tune> AUTHOR=<name of author/composer> RELEASED=<year/name of copyright owner/company> or COPYRIGHT=<year/name of copyright owner/company> These three fields are all plain ASCII text strings. There are limited to a maximum of 80 characters each. To not break compatibility to the PlaySID formats, use a maximum of 31 characters. SIDSONG=<YES|NO> is used to indicate that the corresponding C64 data file is in (Enhanced) Sidplayer file format. This field is optional and defaults to NO. RELOC=<hexValue>,<hexValue> is used to indicate a free memory range not used by the sid tune. (e.g. RELOC=04,65) CLOCK=<PAL|NTSC> is used to indicate the type of C64 the tune was original written for. SIDMODEL=<6581|8580> is used to indicate the type of sid chip the tune was original written for. COMPATIBILITY=<R64|BASIC> is used to indicate the compatibility mode of the sid tune. Normally this would not be included but is set to R64 when the tune includes "sample" music and will only play correctly on a real c64 or a newer sidplayer. This is set to BASIC when the .dat file contains BASIC code. An example file ``EXAMPLE.SID'' may look like this: SIDPLAY INFOFILE ADDRESS=2AF0,3002,300C SONGS=3,2 SPEED=0 NAME=Example AUTHOR=Example RELEASED=199? (c) Example SIDSONG=NO PSID/RSID file header The detailed structure of the SID header looks like the following. Header offsets are in hexadecimal notation. Other integer values are decimal unless explicitly marked otherwise. Any stored integer values are in big-endian format: +00 magicID: ``PSID'' or ``RSID'' This is a four byte long ASCII character string containing the value 0x50534944 or 0x52534944. 'RSID' (Real SID) denotes that the file strictly requires a true Commodore-64 environment to run properly. 'PSID' files will generally run trouble-free on older PlaySID and libsidplay1 based emulators, too. Some words about the Real C64 SID file format (RSID): The RSID format was designed to contain tunes that are not PlaySID compatible, but strictly require a real C64 environment to run. Tunes that are multi-speed and/or contain samples and/or use additional interrupt sources or do busy looping will cause older SID emulators to lock up or play very wrongly (if at all). By using the name RSID for such rips all existing SID emulators will reject these tunes safely until they can be upgraded to cope with the additional requirements. Due to the nature of these tunes, every effort must be made to make sure they are directly runnable on an actual C64 computer. As such the tunes will only be presented with the default C64 power-on environment and expected to configure and use all hardware appropriately. RSID is based on PSIDv2NG with the following modifications: magicID = RSID version = only 2 loadAddress = 0 (reserved) playAddress = 0 (reserved) speed = 0 (reserved) psidSpecific flag is called C64BASIC flag The above fields MUST be checked and if any differ from the above then the tune MUST be rejected. The definitions above will force tunes to contain proper hardware configuration code and install valid interrupt handlers. The default C64 environment is as follows: VIC - IRQ set to raster 0, but not enabled. CIA 1 timer A - set to 60Hz with the counter running and IRQs active. Other timers - disabled and loaded with $FFFF. Bank register - $37 A side effect of the bank register is that init MUST NOT be located under a ROM/IO memory area (addesses $0000-$07E8, $A000-$BFFF and $D000-$FFFF). Since every effort needs to be made to run the tune on a real C64 the load address of the image MUST NOT be set lower than $07E8. +04 WORD version Available version number can either be 0001 or 0002. Headers of version 2 provide additional fields. RSID and PSID v2NG files must have 0002 here. +06 WORD dataOffset This is the offset from the start of the file to the C64 binary data area. Because of the fixed size of the header, this is either 0x0076 for version 1 and 0x007C for version 2. +08 WORD loadAddress The C64 memory location where to put the C64 data. 0 means the data are in original C64 binary file format, i.e. the first two bytes of the data contain the little-endian load address (low byte, high byte). This must always be true for RSID files. Furthermore, the actual load address must NOT be less than $07E8 in RSID files. You must be absolutely sure what to enter here. There is no way to detect automatically whether the first two bytes in a C64 data file are meant to be a load address or some arbitrary bytes of code or data. Unless your C64 file is not a normal binary file and thus has no load address in front, you need not enter anything else than 0 here. The SID tune will not play if you specify a load address which is present in the C64 file already. Normal C64 binary data files have a load address in their first two bytes, so they can be loaded to a pre-defined destination address by executing LOAD"FILE",8,1, for instance. If a load address is explicitly specified in the sidtune info file, some sidtune converters and utilities conjecture that the C64 data don't have a load address in their first two bytes. Hence, the explicit load address from the info file is moved in front of the C64 data to create a valid C64 binary file which can be easily loaded on a C64, too. If that C64 file were to be saved, it would contain two superfluous data bytes at offset 2 if an original load address had been in the first two bytes of the old file. This process of adding a duplicate load address can be repeated. The file loader strips off the first two bytes (the used load address) and puts the rest of the file contents (including the now obsolete load address at file offset 2) into memory. If the new load address is the same than the old one the two added bytes cause the whole data to be displaced by two bytes, which most likely results in malfunctioning code. Also, superfluous bytes in memory then can confuse disassemblers which start at the beginning of the file or memory buffer. +0A WORD initAddress The start address of the machine code subroutine that initializes a song, accepting the contents of the 8-bit 6510 Accumulator as the song number parameter. 0 means the address is equal to the effective load address. In RSID files initAddress must never point to a ROM area ($A000-$BFFF or $D000-$FFFF) or be lower than $07E8. Also, if the C64 BASIC flag is set, initAddress must be 0. +0C WORD playAddress The start address of the machine code subroutine that can be called frequently to produce a continuous sound. 0 means the initialization subroutine is expected to install an interrupt handler, which then calls the music player at some place. This must always be true for RSID files. +0E WORD songs The number of songs (or sound effects) that can be initialized by calling the init address. The minimum is 1. The maximum is 256. +10 WORD startSong The song number to be played by default. This value is optional. It often specifies the first song you would hear upon starting the program is has been taken from. It has a default of 1. +12 LONGWORD speed This is a 32 bit big endian number. Each bit in 'speed' specifies the speed for the corresponding tune number, i.e. bit 0 specifies the speed for tune 1. If there are more than 32 tunes, the speed specified for tune 32 is also used for all higher numbered tunes. A 0 bit specifies vertical blank interrupt (50Hz PAL, 60Hz NTSC), and a 1 bit specifies CIA 1 timer interrupt (default 60Hz). Surplus bits in 'speed' should be set to 0. For RSID files 'speed' must always be set to 0. Note that if 'play' = 0, the bits in 'speed' should still be set for backwards compatibility with older SID players. New SID players running in a C64 environment will ignore the speed bits in this case. WARNING: This field does not work in PlaySID for Amiga like it was intended, therefore the above is a redefinition of the original 'speed' field in SID v2NG! See also the 'clock' (video standard) field described below for 'flags'. +16 ``<name>'' +36 ``<author>'' +56 ``<released>'' (also known as ``<copyright>'') These are 32 byte long zero terminated ASCII character strings. Upon evaluating the header, a zero byte will always be put into the last byte of each string. So the maximum number of available free characters is 31. +76 <data> Version 1 of the SID header is complete at this point. The binary C64 data starts here. Version 2 of the header incorporates the v1 header fields and provides additional fields. Some of these are actually v2NG specific - those are noted below. +76 WORD flags This is a 16 bit big endian number containing the following bitfields: Bit 0 specifies format of the binary data (musPlayer): 0 = built-in music player, 1 = Compute!'s Sidplayer MUS data, music player must be merged. If this bit is set, the appended binary data are in Compute!'s Sidplayer MUS format, and does not contain a built-in music player. An external player machine code must be merged to replay such a sidtune. Bit 1 specifies whether the tune is PlaySID specific, e.g. uses PlaySID samples (psidSpecific): 0 = C64 compatible, 1 = PlaySID specific (PSID v2NG) 1 = C64 BASIC flag (RSID) This is a v2NG and RSID specific field. PlaySID samples were invented to facilitate playback of C64 volume register samples with the original Amiga PlaySID software. PlaySID samples made samples a reality on slow Amiga hardware with a player that was updated only once a frame. Unfortunately, converting C64 volume samples to PlaySID samples means that they can no longer be played on a C64, and furthermore the conversion might potentially break the non-sample part of a tune if the timing between writes to the SID registers is at all altered. This follows from the ADSR bugs in the SID chip. Today, the speed of common hardware and the sophistication of the SID players is such that there is little need for PlaySID samples. However, with all the PlaySID sample PSIDs in existence there's a need to differentiate between SID files containing only original C64 code and PSID files containing PlaySID samples or having other PlaySID specific issues. As stated above, bit 1 in 'flags' is reserved for this purpose. Since RSID files do not have the need for PlaySID samples, this flag is used for a different purpose: tunes that include a BASIC executable portion will be played (with the BASIC portion executed) if the C64 BASIC flag is set. At the same time, initAddress must be 0. Bits 2-3 specify the video standard (clock): 00 = Unknown, 01 = PAL, 10 = NTSC, 11 = PAL and NTSC. This is a v2NG specific field. As can be seen from the 'speed' field, it is not possible to specify NTSC C64 playback. This is unfortunate, since the different clock speeds means that a tune written for the NTSC C64 will be slightly detuned if played back on a PAL C64. Furthermore, NTSC C64 tunes driven by a vertical blank interrupt have to be converted to use the CIA 1 timer to fit into this scheme. This can cause severe problems, as the NTSC refresh rate is once every 17045 cycles, while the CIA 1 timer A is latched with 17095 cycles. Apart from the difference in timing itself, the SID ADSR bugs can actually break the tune. The 'clock' (video standard) field was introduced to circumvent this problem. Bits 4-5 specify the SID version (sidModel): 00 = Unknown, 01 = MOS6581, 10 = MOS8580, 11 = MOS6581 and MOS8580. This is a v2NG specific field. The MOS6581 and the MOS8580 have three notable differences. First, combined waveforms are generally louder on a MOS8580, to the extent that some combinations that are clearly audible on a MOS8580 are completely silent on a MOS6581. Second, the internal DC levels in the MOS8580 are so small that software or hardware tricks must be used to play volume samples. Third, the MOS8580 analog filter has totally different characteristics from the MOS6581 analog filter. To ensure that music specifically written for one of the two SID versions can be played back correctly, bits 4-5 in 'flags' are used as stated above. Bits 6-15 are reserved and should be set to 0. +78 BYTE startPage (relocStartPage) This is a v2NG specific field. This is an 8 bit number. If 'startPage' is 0, the SID file is clean, i.e. it does not write outside its data range within the driver ranges. In this case the largest free memory range can be determined from the start address and the data length of the SID binary data. If 'startPage' is 0xFF, there is not even a single free page, and driver relocation is impossible. Otherwise, 'startPage' specifies the start page of the single largest free memory range within the driver ranges. For example, if 'startPage' is 0x1E, this free memory range starts at $1E00. +79 BYTE pageLength (relocPages) This is a v2NG specific field. This is an 8 bit number indicating the number of free pages after 'startPage'. If 'startPage' is not 0 or 0xFF, 'pageLength' is set to the number of free pages starting at 'startPage'. If 'startPage' is 0 or 0xFF, 'pageLength' must be set to 0. The relocation range indicated by 'startPage' and 'pageLength' should never overlap or encompass the load range of the C64 data. For RSID files, the relocation range should also not overlap or encompass any of the ROM areas ($A000-$BFFF and $D000-$FFFF) or the reserved memory area ($0000-$03FF). +7A WORD reserved This is a 16 bit number and is reserved and should be set to 0. +7C <data> Version 2 of the SID header ends here. This offset is the start of the binary C64 data. See also 'loadAddress' for what the first 2 bytes of 'data' might indicate. MUS files The .MUS & .STR file name extensions are used for Compute's Sidplayer music files. The overall file layout is as follows: The first two bytes contain the load address. The next two bytes contain the length of the data for Voice 1 The next two bytes contain the length of the data for Voice 2 The next two bytes contain the length of the data for Voice 3 Then the data for Voice 1 follows immediately Then the data for Voice 2 follows immediately Then the data for Voice 3 follows immediately Then the text description of the music file (upto 5 lines) The data for each Voice consists of a stream of two byte commands and should be terminated with a HALT code which is 01 4F. The text description can be upto 5 lines long, each line upto 32 characters wide. It is made up of PETSCII characters and may contain colour codes. The text description should be terminated with a 00 byte (but might not be).