NEW WAVEFORMS Some people claim that everything imaginable has been done on the C64. This is true to a certain extent. The typical scenario is indeed that you come up with something new just to find out that someone else has done it 10 years ago... But sometimes strange things happen and even lamers like myself stumble on new stuff. This happened when we were working on our 4k intro Pico! for Breakpoint this year. I was coding the music player and tried to create some drum sounds when I accidentally got some harsh, very distorted sounds. The funny thing was that I was using the noise waveform and got something that sounded like a synthesized electric guitar! This was not supposed to happen... Noise is not supposed to have a pitch... It took me some time to figure out how and why this works. In this article I will tell you what I found out. The trick requires custom code, and can't be done in existing players and editors. Hence this text is intended mostly to coders, but musicians might find it an interesting read, too. THE NOISE MECHANISM In order to understand how the new waveforms are generated we have to examine the internals of the SID chip. As already mentioned, the trick is based on the noise waveform. SID uses a pseudo random mechanism based on a 23 bit shift register to generate the noise waveform. When clocked, the register is shifted to the left and bits 22 and 17 are fed through an exclusive or gate back to the least significant bit. (This was proposed by Marko Makela and Asger Alstrup, and seems to be correct) This results in a new pseudo random value that is used as the output sample of the voice. (Bits 22, 20, 16, 13, 11, 7, 4 and 2 are used as the output bits.) In normal circumstances the register is clocked periodically and the generated sequence of random numbers is perceived as noise. Of course, this is no fun. What we really want is to abuse this mechanism to get some weird side-effects. In our case, we are going to fool it into repeating a short sequence of "random" numbers. This is achieved by resetting the value in the shift register when we want to restart the sequence. In order to do this we need a way to load a certain value to the register. There is no simple way to do this, but it is possible to alter the bits in the shift register either by using the testbit or by using combined waveforms. COMBINED WAVEFORMS When other waveforms are selected simultaneously with the noise waveform bits 22, 20, 16, 13, 11, 7, 4 and 2 of the shift register are cleared immediately. Notice that these are the same bits that are used as the output bits of the voice. THE TESTBIT I found out two interesting things about the testbit. 1) When the testbit is CLEARED the shift register is clocked once. 2) When the testbit is SET bit 19 is inverted and the result is written to bit 1. This happens immediately. (I can't really prove that bit 1 is updated when the testbit is set, but I will assume this is the case. It is also possible that bit 2 is updated when the testbit is cleared _after_ that the shift register is clocked. From a theoretical point of view, it doesn't really matter which one we choose to believe in, since there is no way we can measure the value of bit 1 when the testbit is set.) If the testbit is set for several seconds the value in the shift register will slowly change and $7ffff8 can eventually be read from it. This is NOT useful for creating new waveforms because the delay before something happens is too long. $7ffff8 is indeed the value that was proposed as the initial value of the shift register by Marko Makela and Asger Alstrup and is also used in ReSID. However, it's not really the initial value since the register is clocked once after the testbit is cleared. My theory is that the real initial value is $7ffffc. It seems as if all bits are set (except for bits 0 and 1 that are cleared) in a certain order with a certain delay. The delay seems to vary, and sometimes the bits are set in a slightly different order. The only explanation for this is that it is some kind of analog magic. I don't have an explanation for why bits 0 and 1 are cleared instead of being set but that might have something to do with that these are the only bits in the register that are written to. (bit 0 when the register is clocked and bit 1 when the tesbit is set) I wonder whether there was some purpose behind this weird behaviour. HOW IT IS DONE Now we know how the mechanism works and how to abuse it. So how do we actully produce these sounds? A very simple approach is to use a CIA irq to reset the noise mechanism. Experiment with different CIA and noise frequencies and put something as simple as the code below in your irq routine: lda #$f1 ; combined waveforms on, testbit clear ldx #$09 ; testbit set ldy #$81 ; only noise set, testbit off sta $d412 ; ($d412=osc3 control register) stx $d412 sty $d412 With the right frequencies you will get a pitched sound. This was the way I discovered the trick but I'm sure you could use more complicated routines to generate more interesting sounds. Go ahead and impress me! THE TEST PROGRAM I wrote a program for testing the mechanisms described here. It can be found on this disk with the filename WAVECOMPOSER. It is rather simple but allows you to experiment with some basic sounds. Keep in mind that the program won't work on the emulator. You can select a CIA frequency (timer lo/timer hi) and program a noise frequency sequence with the frequency table (labeled freq). Use "frq end" and "frq loop" to specify where the table ends and what position it should jump to after reaching the end. You can also specify how many frames each row in the frequency table lasts by using the "len"-table. The wave table (w1/w2/w3) is used to specify what three values are written to $d412. You can turn off the screen by changing the value in $d011 to $00 to ensure that bad lines won't interfere with the timing. You can also make the timer interrupts stable by setting "synch" to $01 but this seems to have little significance on the sound. There's also variables for changing adsr and controlling the filter. I added these just to spice up the example sounds a little bit but of course they are really not important for the new waveforms. Press F1 to read the value of the internal shift register while playing a sound. I recommend that you disable the screen (set $d011 to $00) before using this feature to avoid timing problems caused by bad lines. You can hit RESTORE to view the source code and make your own modifications to the program. You might want to add more than three writes to $d412 for each interrupt for greater control over the value in the shift register. A separate table for the CIA frequency could also be very useful. I wrote the program before discovering the details about the noise mechanism and hence it lacks these features... ABOUT EMULATORS AND DIFFERENT SID REVISIONS Luckily the trick seems to work in the same way on all revisions of the SID chip. This is natural since it depends only on digital logic. You might argue that combined waveforms are analog in nature, but in our case it seems that the bits affected are always cleared. However, I've been using waveform "$f1" (all waveforms are toggled on) most of the time, so other combined waveforms might result in unpredictable results on some SID chips. The mechanism described here is not emulated correctly on any current emulator, so what you will hear on emulators is just plain noise. This means you could use the trick for emulator detection but I'm not sure what happens if this kind of routine is run on a real c64 without a SID chip... Well, that's all, see you next time! SounDemoN/Dekadence