Ripping music is the process of detaching the code and data of a music player from an enclosing program and getting the isolated music to play.
This section is not meant as a full guide on ripping C64 musics. Individual pieces of music may be very difficult and time consuming to rip for a beginner. And there must clearly be distinguished between just a rip and a so-called clean rip. In this and subsequent paragraphs the term ripper refers to a human person, unless specified in any other way.
Ripping can be as easy as having to determine two single program addresses only and saving a small region of enclosing memory.
Clean rips often are much harder to achieve, as their aim is to strip down the source program to nothing else than the music player and its belonging data, thereby making the ripped data as short as possible. Additionally, rippers often copy the remaining fragments of data into a more compact form. Sometimes they even relocate the player. This may be required if one wants to merge all subsongs (perhaps each with a separate player), keeping in mind the C64 memory limitation of 64 kB. Concerning SIDPLAY this is easier, as the entire data is reloaded upon starting each subsong, permitting the ripper to always use the full memory regardless of whether he likes to overwrite unused parts of the music data or not. The entire sidtune data will be recovered upon restarting a song or starting another song.
Cases where the player and its data (including all subsongs) are spread throughout the whole memory are crucial. It is then difficult to determine whether certain regions of memory actually belong to the music player. Proving the integrity of a fragmented song can only be done by listening to it and comparing it to its original program. This might be the most boring part upon performing a rip if you don't want to fully read and analyze the music player (which, by the way, would be the only true way to track down the location of all belonging data; except using a self-written utility). Consider a long song, where you would have to listen to it entirely to find its end to be broken. The effect of only a bit of data missing might not be as obvious as you would guess. A single instrument might be only slightly altered. You probably would not even notice a difference, a weaker vibrato effect for instance. Better save a wider region of the memory rather than cutting off any parts by accident.
Consider some of the required music data (such as vibrato tables, instrument definitions or track and pattern data) to be put into a memory region, which you would not even think of. For instance, sensitive data might have been put into the stack address space or into the zero-page. Zero-page pointers sometimes are only initialized once by some code at the early start of the program. It can be required to write an own music player initialization, most often based on available code fragments.
Usually only musics in demonstration programs are likely to be protected. Hard to rip musics in games generally are protected by accident, which either means the game programmer mixed parts of the music player code with his own code (or he did the music himself) or he had a very confusing coding style (socalled spaghetti-code), making the code unnecessarily difficult to understand and making it almost impossible to detach music player code from program code. More on this further below.
As long as a (partially) ripped music can be determined to be oviously damaged, you can still decide to leave it in its most basic form. For instance, if the code of the application and the music player code are nested, saving the entire memory might be a hint. Making the rip a clean rip is just an optimization and could be done later.
The availability of special software or external hardware tools is of much help. Try to get one of the following (sorted by recommended priority):
If you don't have access to any of the tools listed above, you are definitely
out of luck. At least I can't think of any other equivalent tools. Except
nowadays you do not need a real C64 for ripping music. Some of the existing
C64 emulators provide a built-in emulation of such monitoring and freezing
functions, e.g. the freely available C64 emulator VICE.
As a side note, it is also possible to rip directly from *.D64 emulator disk
images.
Of course you need to know of the capabilities of your tools and how to use them efficiently. Finally, you certainly need to know the C64's hardware and the 6502/6510 machine language. A bit of knowledge of hexadecimal machine codes would be appreciated, but is rarely necessary as you will almost never have to read plain hex machine code. You don't need to be a programmer either, though you should be able to read and understand (and thus be able to follow) disassemblings.
The method presented here is just one way to rip a sidtune. It may not be directly applicable to all sidtunes and their programs. It is more meant as an introduction. The overall ability to rip a specific sidtune mainly depends on experience and instinct, as well as a bit of machine code programming skills. You will certainly build your own individual ripping algorithm based upon the experiences you will make. Most of the examples and recommendations in this section are based upon questions I and others on Usenet were asked. For the weird case, that you want to test this guide on some program, please take into account that intro/demo tunes generally are much more easy to rip than game tunes. If you want to rip a very easy game tune, check out the game Commando. It is probably the most famous tune and very easy to rip due to the simplicity of Rob Hubbard's modularized music player.
Have you ever tried to rip a sidtune from a game or demo? Maybe you always wanted to be able to listen to your favourite one without having to load and run a larger program? If you ever tried to rip, did you succeed? If not, what was the main problem? Maybe you didn't know where to start? Maybe you erratically browsed through hundreds of lines of machine code and randomly displayed kilobytes of C64 memory without a clue? Or maybe you did not even come that far?
Depending on the tools which aid you on your ripping-task, make a hardware reset to stop the running program and start the monitor (here the term monitor always refers to the monitoring utility and not the screen :). Making a reset does not mean turning off the computer and then on again. By doing that you erase its memory! Inside a C64 emulator you often have the choice between soft and hard reset. Soft reset should be the recommended one unless the application is protected against resetting. Without an expansion module the easiest way to reset the C64 is to connect pins 1+3 (GND and RESET) of the user port (starting to count the pins from the left while looking at the back of the C64) for a short time. For the case that you don't have an external hardware module installed and need to load and start a software monitor, you will overwrite a part of the memory by loading the monitor. Some monitors are relocatable. Make and save a couple of versions for different memory regions, e.g. $1000, $6000 and $C000. Unless you find out a memory region that is definitely not used by the music player and data, you will likely have to repeat this procedure:
You already had come so far, but didn't know any further? Did you think about the simple fact that SID music can only be produced by machine code that accesses the SID chip? Hence that is the most trivial hint. The following steps in trying to rip the tune will be:
Unless the ROM and the I/O address space are turned off, the SID chip registers are found at a constant place in memory, i.e. address $D400 to (and including) $D41D. On the contrary, all subsequent chunks of 32-bytes from $D420 to $D800 are mapped to the SID chip, too. But only a very few tunes access the SID chip via these mirrored registers.
So, first we need to find the music player code. We assume the music player uses the absolute addressing mode to access at least one SID register. This is most common, but must not be true for a specific player. Basically, you could search for the appearance of any valid SID address. But starting with the Master Volume and Filter Type Register $D418 next to the Oscillator 1 Control Register $D404 is a good hint. In your monitor enter something like the following at the prompt to search the C64 memory for the appearance of each value:
> H 0800 D000 18,D4
This searches the memory from address $0800 to $d000 (where the VIC chip starts) for appearance of the consecutive bytes $18 and $D4. Notice the little-endian order of the low and high byte of the 16-bit address word. Please also take into account, that if you want to search other parts of the C64 memory, like the RAM under the ROM $d000 - $FFFF, you first have to enable/disable the desired memory bank. Further, superior monitoring tools are able to search for full valid machine code instructions instead of just hex values. Consider the following output:
> H 0800 D000 18,D4 087C 127A 15F4 CFEA > > H 0800 D000 04,D4 117A 1208 13F8 1410 15FE
Searching for alternate $D4?? values would probably also hit the area at $1???. Avoid searching for the SID registers of operator 2+3, as most players access these via indices and the SID base address $D400. Since repeatedly searching the C64 memory takes some time, you can narrow down the region once you had a couple of hits. In this example there is most likely some SID sound code between $1000 and $1800. Examining the code in that area might be enough. Keep in mind, that unless you are able to directly search for full valid machine instructions, these hits might only be binary data. Manually searching for possible instructions could be a hint. Consider the instruction STA $D418:
> H 1000 2000 8D,18,D4 1279 15F3
Further keep in mind, that there might be more than one player in memory as well as additional SID code outside a compact music player, so you might find your searches to hit two completely distinct memory regions.
Next the often more difficult task of finding the initialization and play addresses of the music player, although the overall procedure is similar:
Special problems need special treatment:
An universal C64 Timer Interrupt Handler at address $6000 is set up like this and can be used to verify the found play and init addresses of a rip:
$6000 SEI $6001 LDA #$60 $6003 STA $0315 $6006 LDA #$31 $6008 STA $0314 $600B LDA #$00 $600D STA $DC0E $6010 LDA #$4D $6012 STA $DC05 $6015 LDA #$00 $6017 STA $DC04 $601A LDA #$01 $601C STA $DC0E $601F LDA #$0F $6021 STA $D418 $6024 LDA #$35 $6026 STA $01 $6028 JSR <INIT> $602B LDA #$37 $602D STA $01 $602F CLI $6030 RTS $6031 LDA #$35 $6033 STA $01 $6035 JSR <PLAY> $6038 LDA #$37 $603A STA $01 $603C JMP $EA31
Finally, you just need to save the tune to disk. Worth knowing is, that the music data may either be stored in front of or behind the player. Or it is stored at a more distant location. The safest way to search for the true location of the data is to follow the initialization subroutine and try to determine where pointers, arrays, note tables and such are kept. But generally it is enough to do a quick memory dump of the full player environment, searching for boundaries, which often consist out of a larger number of zero padded bytes. With a bit of experience you will be able to hit the right region just by looking at a hex dump.
Without bank-switching it is nearly impossible for an emulator to determine which memory region should be accessed. There are some sidtunes that do not only use the memory under the address space of the Basic-ROM and Kernal-ROM, but also the memory under the I/O address space. To have all sidtunes in a unique format, it would be preferred to use valid machine code, which would also run on a real C64, except for the PlaySID-compatible sample-player modifications of course.
Please don't neglect bank-switching! It doesn't make the code of a ripped sidtune much longer. Where necessary, it generally takes only 2*12 bytes of additional code in front of the initialization and main player routines.
SIDPLAY's built-in machine code interpreter provides default bank settings for the C64 music player starting addresses:
The main aim of these default values is to provide a sane initial state prior to executing the music player machine code. Further, these defaults make it possible to jump directly from SIDPLAY to any RAM area without turning off too many components. The single value $05 is not used for all the memory banks because, for instance, it would be necessary to turn back on the Kernal area to use the end-of-irq functions.
The quickest way to add C64 bank-switching code to a sidtune is to append the following code and adjust the initialization and player address accordingly. This example switches off Basic-ROM and Kernal-ROM, but leaves on the I/O address space:
New <init>/<play> subroutine:
LDX #$35 STX $01 JSR <init>/<play> LDX #$37 STX $01 RTS
Note: Keep in mind, that some PlaySID-specific rips assume all registers to contain a zero prior to executing the player subroutine (and the X and Y-Register to contain a zero prior to executing the init subroutine). Thus, when modifying those rips to use bank-switching, the additional code does not satisfy the PlaySID-specific assumption. To satisfy such a rip, add LDX #$00, LDY #$00 in front of the music player call.
Variable replaying-speed for a song can be set up via CIA 1 Timer A:
985248 Hz ---------------- = timer_value song_speed in Hz Normal double-speed: 985248 Hz / 100 Hz = $267C
Some music composers demand subsequent player calls to be done after a specific number of scan-lines. This way effect updates are affected and, according to the composers, result in better sound.
Without the availability of emulation of scan-line interrupts you can nevertheless achieve such a timing by dynamically updating the timer speed for each player call. You can divide the normal speed timer value into small chunks that would equal the system time for one scan-line:
On a PAL system:
$4CF8 (50 Hz) / 312 scan-lines = 63 cycles per scan-line 63 * X scan-lines = timer value for one particular player call
New <init> subroutine:
LDX #$26 ; plain 100 Hz LDY #$7C STX $DC05 STY $DC04 JMP <init>
New <play> subroutine for double-speed and $48 scan-lines delay:
LDA <counter> ; decide which timer value to set AND #$01 ; 0=1st or 1=2nd player call ASL ; two bytes per timer value TAX LDA <timer_table>,X ; $11D4 (duration of $48 scan-lines) STA $DC05 ; $3B24 (the rest of the screen) LDA <timer_table+1>,X ; ($11D4 + $3B24 = $4CF8 full screen) STA $DC04 INC <counter> JMP <play>/<play2> ; maybe call different player entries
A lot of C64 music players contain a built-in instance of an interrupt handler and a corresponding interrupt set-up routine. It was probably used to provide a small test player, making it able to quickly start the music for demonstration purposes. And it often serves as an example of what is required to correctly initialize a song, its speed and where the music player has to be called to produce continous music. A certain simplicity of such a built-in handler provided, it is very easy to convert such a sidtune to SIDPLAY compatible form. Specifying the play address $0000 makes SIDPLAY search and use an installed interrupt vector in either $0314/$0315 or $FFFE/$FFFF.
Avoid any usage of Basic-ROM or Kernal-ROM routines. Not necessarily because SIDPLAY does not include the original ROM images and does not otherwise emulate any ROM routines, but because ROM functions generally imply any sort of I/O usage. A jump into the ROM memory is considered equal to an ``RTS'' instruction. Some specific versions may include faked emulation of a few often used and interrupt related ROM routines. If you don't want to break the compatibility to other SID emulators, don't use these routines either.
Some C64 musics replay 4-bit (or 3-bit) samples by rapidly changing the SID master volume value $D418. This method was called volume samples and fake samples. Usually, such a music player used a Non-Maskable-Interrupt (NMI, vectors $0318/19 or $FFFA/FB) next to the standard player subroutine to continually copy sample values to the master volume register.
PlaySID introduced a different method, which required a modification of the sample players to use a set of new SID registers, called the Extended Sound Interface Device. SIDPLAY provides compatibility to these registers. Basically, the main aim of these new registers was to aid PlaySID in directly replaying the C64 samples via one of the Amiga audio channels. The original description of the new registers can be found in the PlaySID package or in the chapter Technical Information. Using the extended registers is not as flexible as a full-featured interrupt emulation would be, but it allows a sample playblack at maximum quality (4-bit samples :). This section only deals with setting up an examplary sample player for SIDPLAY or PlaySID. If you want more examples, consult the already converted sidtunes.
Modify the sample player to do the following only once for each sampled waveform you want to start instead of continually piping sample values into the master volume register in a loop or via an interrupt handler: