05/16/2023 at 20:26 •
So based on the past two logs, i decided to revisit the Debugger and take a closer look at the C64 Schematics. To figure out the relationship of the CIA timers and the VIC-II
In the schematic i can indeed see that the IRQ input has three potential sources: The CIA1 chip, the VIC-II chip and the Expansion slot. So it would seem that the Vertical Blanking Interval is used at times as a Interrupt source.
I went into the debugger and started running a variety of SID files and note the interrupt configurations.
NAME TYPE NOTES 2400AD RealSID Raster Interrupt enabled Amazing Discoveries RealSID T1B and T2A active. Raster enabled A waste of space RealSID Same as Amazing Discovers Hi Fi Sky RealSID Same, My Life RealSID Same $11 Heaven PlaySID Raster Interrupt enabled Crystal Dawn PlaySID Raster Interrupt enabled Echofied 6581 RealSID Raster Interrupt enabled, 1A,1B and 2A active. Haven PlaySID 4x, 1A configured as IRQ source (4x as fast) Rotten Soul PlaySID 6x. 1A configured as IRQ source. (6x as fast) Age We Aceed PlaySID 4x. 1A configured as IRQ source (4x as fast).
So. Turns out that during my initial looking into behaviour, i did not pay attention to the VIC-II's behaviour and just assumed everything was done via the timers. It was not. Apparantly depending on the SID file used. One can expect either:
- Generic PSID only use the standard Raster Interrupt.
- PSIDs with anomalous speed, disable Raster and instead use the CIA timer at a custom interval.
- RSIDs may use either or even both at their own discretion.
This complicates things a little. As it means besides the CIA timers. The VIC's Raster interrupt needs to be handled as well.
Brief look at the VIC IRQ.
In practice. Without looking to actually output video. The Raster Interrupt can be seen as another timer. Though compared to others. This timer just runs non-stop up to 0x0137 (311) with the IRQ output turned on/off as needed.
Messing with the specific raster interrupt number while it is running in a debugger does not seem to cause any odd behaviour outside of graphics shifting and no active reading of the raster value has been noted for music itself. So it does not appear to require cycle exact behaviour, Functioning mostly as a periodic interval timer whose exact timing changes depending on the video format (NTSC/PAL).
In regards of knowing which one to activate. The SID format file specifies "Default" settings for both PSID and RSID, which combined with the header can allow for accurately configuring a player in advance. Any modifications are expected to be performed by the SID file itself during initialization.
Good thing this was figured out sooner, rather than later. Could have been a major headache later on!
05/13/2023 at 17:51 •
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.
+00 four character String containing either "PSID" or "RSID".
Informs the player what kind of file is being dealt with.
+04 16-bit field containing Version of 1 to 4.
Depending on the version, there may be more data in the header.
+06 16-bit field containing the DataOffset.
Points the where the machine code portion begins. Should be static depending on the version
+08 16-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.
+0A 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.
+0C 16-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.
+0E 16-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)
+10 16-bit field containing the default Starting Song.
Specifies the default song to be played one load
+12 32-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 +76 Starting 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:
+76 A 32-bit "Flags" value. Stores bitwise data:
b0 : Indicates built-in player  or Compute! player 
b1 : Specifies C64 compatible PSID  or PlaySID specific/C64 Basic 
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
+78 8-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.
+79 8-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.
+7A 8-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
+7B 8-bit field containing thirdSIDAddress
Works the exact same as secondSIDaddress. Except indicating the third chip.
Only used in Version 4
+7C Data 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.
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:
- The file starts with "[database]" as its first line
- A line starting with a semi-colon that contains a string of the expected file location. by starting with a ';' the line is expected to be skipped.
- next line starts with a MD5 Key, followed by a = and then a timestamp
- The time has the duration in minutes:seconds. Minutes may be one or two numbers. seconds is always two.
- Some also have milliseconds included as a dot '.' followed by always three numbers
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.
11/30/2021 at 13:47 •
Before i could get started it was imperative that i looked at the golden target. The playing of RSIDs and what makes them so special compared to the regular SID music referred to as PSIDs. Most projects around SID playback make assumption on how they could do it that as far as i know: never panned out only ever playing PSID. My hunch is that RSID playback has something to do with the "Complex Interface Adapter" (CIA) chips. These are massive chips in charge of general purpose I/O, but also Timing via a pair of Periodic Interval Timers (PIT1 and PIT2). These are also what control the processor's interrupts (CIA1->IRQ, CIA2->NMI)
To investigate this I used a "C64 Debugger". A Variant of the popular VICE emulator that shows information about the peripheral chips like the SID, CIA and VICs, a live memory map and can be run clock by clock if desired. I then proceeded to load up various SID files including a couple RSIDs and observe how they use the C64 hardware.
By default the C64 is configured with a regular IRQ signal coming from CIA1-PIT1. This IRQ goes of at a frequency of 50hz. Most PSID use this regular IRQ to call the "PlayRoutine" (an address that when jumped to starts the routine for the next step in playback) 50x per second. Some PSIDs deviate and reconfigure the CIA1-PIT1 to instead trigger IRQ more often. The other Timer and CIA2 are left alone.
RSIDs though start to use more elaborate tricks. With the SID chip they start to manipulate the volume register at times to pull off PCM sample playback. Occasionally using the NMI connected CIA2 or even forgoing the timers altogether and just running at full speed. Then I got to play "Hi-Fi Sky" by LMAN which showed the most devious exploit I had seen thus far.
This one did this weird thing where CIA1 was not creating any IRQ, but had its second timer running at an incredibly small interval while the first was standing still at a specific value. The processor kept passing by it. On closer inspection it turned out that the first timer's value matched a JMP opcode. The processor was reading the registers of the first timer which had part of a JMP command. The last byte it read for the target address being the low-byte of Timer2 that was constantly changing. The RSID was using the CIA1 Timers a a time-sensitive JMP Table!!
This is why most players failed and why you had to use a "Cycle Exact" emulator. Even when using a genuine SID chip, most players only assumed the IRQ would get used for a regular signal and any offset in timer value would break the playback if you didn't do it exactly.
So if i want a real chance at playing all the RSIDs. I need to figure out how the substitute the CIAs Timers. Which will be the subject of a future log.