01/27/10: Can a Coco 3 sound like a C64? by remz, | Tags: , , , , , | Category: General | 54 comments - (Comments are closed)

Can a Coco 3 sound like a C64?

Oh yes it can.
I am currently working at a 3-voice synthesizer which should mimic and sound almost like a Commodore 64 SID chip, on a plain Coco 3. At the moment I haven’t finished coding the 3rd channel of a demo music, but it is going pretty well.
The final result will be a full 6-bit quality sound mixed in realtime, outputing at a high quality sample rate of 19456 Hz, featuring 3 completely independent channels that can play either a sine, sawtooth, triangle, pulse, or noise wave, at any frequency. It is not fully done yet but I am very confident it will sound like a C64.
(However the CPU is 100% used while playing so no chance of having stuff going on the screen simultaneously :))

This post was submitted by remz.

54 comments to Can a Coco 3 sound like a C64?

  • Maybe after it’s finished, you could do a cut down version, may be something like 2 voices at 11 Khz, that would leave some CPU available for other tasks? Or would that make very little difference in CPU usage?

  • remz,

    It might help you to do some research on the program Quaver, ftp://maltedmedia.com/coco/GreenMountainMicro/QUAVER/ ,
    by Dennis Kitz.

    This was a four voice music synthesizer which had the source code published in “The Color Cumputer” Nov.,Dec., 1983.


    I’ll be interested to see how you manage 19KHz sampling with three voices. It is not easy to get that kind of rate with a program designed to record microphone input and store it to disk with a Coco.

  • remz

    Diego: the problematic thing with sound mixing is that it needs to run ‘continuously’. You cannot set up a interrupt to occur, say 11000 times per second, this would cut down speed tremendously. The main program would slow down to a crawl. You can do just a little bit of work between “batch” of sound, maybe scrolling the screen or color cycling the palette, but if you do too much work, the music will kind of “hesitate”, like some CoCo games exhibit.

    Robert: My main mixing subroutine takes 92 clock cycle to mix the 3 voice, which at full speed of a Coco 3 means 1790000 Hz / 92 clock = 19456 Hz. However this number is slightly less in reality since the code must process song information, setup waveforms, calculate frequency, etc, all in realtime.
    Note that I am not recording sound, only output. And I don’t know if a disk can withstand that throughput (19 KB/sec), while the CPU keeps processing.

    Anyhow I’ll post up a demo as soon as I can!

  • If you would, please post source code along with the working demo.

  • remz

    If you want to take a look at the main mixer subroutine, here it goes:
    This section loops 389 times, thus outputing 389 samples thru the DAC.
    I have written clock cycle count beside each instruction.
    The 3 labels ‘selfmod_addd_freq1/2/3’ are used to put a self-modifying immediate value into ADDD #0, because immediate are a bit faster than direct memory access.

        ; loop for 389 iteration (to output 50Hz)
        lda #2
        sta loop_hi
        lda #133
        sta loop_lo ; loop '128' times
        ; First synth:
        ldd synth1.synth_freq ; 5
        addd #0 ; 4
        std synth1.synth_freq ; 5
        ldb a,y ; 5
        stb synth1.synth_out ; 4
        ; Total for synth 1: 23 clocks
        ; Second synth:
        ldd synth2.synth_freq ; 5
        addd #0 ; 4
        std synth2.synth_freq ; 5
        ldb a,u ; 5
        stb synth2.synth_out ; 4
        ; Total for synth 2: 23 clocks
        ; Third synth:
        ldd synth3.synth_freq ; 5
        addd #0 ; 4
        std synth3.synth_freq ; 5
        ldb a,s ; 5
        ; Total for synth 3: 19 clocks
        addb synth1.synth_out ; 4
        addb synth2.synth_out ; 4
        ldb b,x ; 5
        stb #$FF20 ; 5
        ; Total for mixing + inner loop: 27
        dec loop_lo ; 6
        bne synth_mixer ; 3
        dec loop_hi ; 6
        bne synth_mixer ; 3
        ; Total for 1 sample loop iteration for 3 channel: (we are not accounting for outer loop, insignificant)
        ; 92 clocks

  • remz

    Status report: the synthesizer is going well. I am converting a popular Commodore 64 music (Commando) which can be heard here: http://www.youtube.com/watch?v=qrQuR1LHAVI
    My Coco synth supports realtime enveloppe (Attack, Sustain, Release), Low-frequency Modulation on Pulse wave, and slurring notes for simulated portamento.
    The music sounds ‘harsher’ than the original C64 version, because the Coco having only a 6-bit DAC is the limiting factor on sound quality. But I think it still sound pretty impressive.
    I’m still working on additionnal functionality, such as ability to mute / unmute channels during playback, and maybe fast-forward / rewind control too even it is not an absolute necessity.
    The music itself is pretty long and difficult to convert “by hand”, I am coding it as fast as I can.
    I’ll keep you posted!

  • jdiffend

    How about a version for the stereo synth cart?
    Wouldn’t that require less mixing and offer more bits for improved sound quality?

  • remz

    Jdiffend: this is an excellent idea.
    Does anyone know if the Orchestra-90 cart can be used by the computer without actually “booting” into its own editor?
    Obviously the setup would require a Multipak adapter too, since you would need a disk drive cart, and an Orchestra cart.
    The sad thing is this wouldn’t be qualified as a ‘stock Coco’.
    That being said, having two 8-bit DAC would make a far higher quality sound.
    Do you have documentation on how to output sound thru this cartridge?

    Or did you mean the Tandy Sound & Speech cart?

  • remz,
    You most definitely want the Orc-90 not the Speech/Sound pak.

    The Orc-90 contains two passive resistive DACs. They can output sound in mono via the SND line for the Cart slot or via two RCA jacks on the pak for stereo.

    You don’t need to use the sound chip on the pak to output sound. My data indicates you can send sound to the right channel at $FF7B and the left at $FF7A.

    There is a problem with the audio circuitry of the pak. There are roll off filters on the output lines. Change C12 & C14 from .047uf to .002uf to reach a 10KHz output.

  • joel.ewy

    If you don’t want the Orchestra 90 program to run, you could simply tape over the CART line like you do when you want to copy the contents of a ROM PAK to disk. It also occurs to me that one might be able to replace or piggyback the ROM in the Orch 90 with an HDB-DOS/Drivewire EPROM, eliminating the need for a disk controller, and gaining faster “disk” I/O as a bonus — though I suppose the competing CPU needs of Drivewire and the audio program would clash. You’d just have to load your MOD data (or whatever) into RAM. It would probably require an antique 24-pin EPROM or a 24-28-pin adapter…


  • linville

    Just for the record, programming the Orch-90 hardware is dead simple — just replace (or replicate) every store to $ff20 with a store to $ff7a and/or $ff7b. Hth!

  • remz

    linville: great but does doing this implies ‘masking off’ the CART line as said by joel? I am not familiar with this technique but I don’t see how the program can access hardware registers inside the Orc-90 with it being inserted in a multipak adapter and accessed by BASIC or machine-language program.
    Are the $ff7a and $ff7b full 8-bit DAC? (compared to $ff20 which only uses the top 6-bit)

  • Robert Gault

    Addressing is automatic as it is with any other paks, including the disk controller.
    Since the DAC is an 8 resistor divider, the bytes at $FF7A and $FF7B take a full 8-bit word.

    Far as the CART line is concerned, either tape the lead or cut the trace on the pak, lands 7&8 or the connecting trace.
    You may not need to do this if an MPI is in use and the pak is not in the default slot, depending on how you access the pak. You will probably need to use software switching to select the correct MPI slot. During that process you can prevent the CART line from causing an interrupt.

  • DarrenA

    If you have an MPI then there is no need to tape over or cut the CART line. Just startup the system with the MPI switch set to something other than the Orch90 pak.

    The DAC addresses ($FF7A and $FF7B) do not rely on either of the “switched” signals (CTS or SCS), so there is no need to do any MPI software switching either.

  • remz

    The music is finished! I am very happy with the result, and I hope you will enjoy it.
    I am finishing up the ‘demo’ by putting a title screen and maybe a song progress indicator. As soon as it’s done, I’ll post the CoCo .DSK.
    I can also post an MP3 of the resulting music if anyone is interested.
    Or I’ll eventually prepare a YouTube video of it. And I’ll digitize the sound output of my real CoCo 3, not playing thru an emulator (even if the emulator is pretty accurate).

    I haven’t tried using the MPI + Orc-90 cartridge yet since testing and debugging would be a lot more painful, having to copy to 5 1/4 disk and try on the real CoCo every time. I don’t think MESS can emulate the Orc-90, can it? There was a thread about it somewhere on this forum but I haven’t seen its conclusion.
    Does anyone have the ROM for the Orc-90 cartridge, and does MESS know about the additional hardware (two 8-bit DACs)?

  • sixxie

    Based purely on the information in this thread I’ve bodged some Orc90 support into XRoar, so I imagine MESS either does it or can be made to quite easily!

    If you’re interested (and your code doesn’t need anything specifically CoCo3), I’ve left a snapshot in http://www.6809.org.uk/tmp/xroar/

  • remz

    Alright I managed to record my CoCo 3 playing the complete music and saved it as an MP3 here:
    The music is 3:56 minutes long.
    The result is pretty amazing, thanks to Rob Hubbard (original music composer for the Commodore 64 version).
    When you listen, the result seems much more than 3 voices playing at the same time.
    Amazingly, this demo might demonstrate that a CoCo 3 (or even a CoCo 1 or 2 since there is nothing related to the GIME chip or requiring much memory) can ’emulate’ the mighty C64 SID chip?
    Comments are welcome!

  • sixxie

    That’s absolutely fantastic! Impressively close to the original (which I’ve heard a lot :) ).

    Now the best music on a Dragon game was probably also attached to a Commando-like game. Unfortunately the game itself (Fire Force) was incredibly unfair. Perhaps a better clone of the game needs to be attached to your music 😉

  • remz

    Thanks Sixxie!
    I’ve uploaded an updated version of the MP3 (overwriting the same file so original link is still valid) because I realized that the original C64 music has notes much more ‘glued’ together, and my CoCo version sounded a lot harsher.
    This is now fixed and I think it sounds much better now.
    Same link: http://www.coco3.com/community/wp-content/uploads/2010/02/Commando_CocoSampled.mp3

  • briza

    Hi Remz.

    Just listened to the music score. It sounds amazing mate well done. Now if it was coded to send all data through the Orch-90 pack it would sound pretty darn close to the Sid chip in the C-64.
    But in it’s current form you have a done a remarkable job creating the music. It must be around 90-95% close to the sid version. I have not heard that music score in years but it does sound close to it.



  • jdiffend

    @Briza, the link to a youtube vid of the original game can be found earlier in the thread.

  • remz

    Thank you all,

    I have just put the DSK here on this site:
    To launch the program, type in:

    I can put the whole source code online too if anyone’s interested.
    Happy listening,

  • Robert Gault

    I for one, would love to see the full source code. I’d also like to know how the music was loaded and get the music as well.
    It would be very interesting, if possible, to compare the sound quality of CocoSid with one or two other Coco programs of similar type.

  • jdiffend

    I think it’s safe to say that a lot of people would like to see the source code.

  • Count me in on that.

    remz: Bad ass man. Just bad ass!

  • remz

    Here you go my friends:
    Source code for CoCoSID + background image.
    The source code named cocosid.asm is compiled using Rainbow IDE, CCASM_RogerTaylor, multi-origin.
    The background image is included, named cocosid_title_test2.bin

    The source is commented a bit, feel free to ask or comment any topic you want, I’ll do my best to answer.

  • Robert Gault


    I’m trying to understand what the song_voice# tables mean. It looks like these might be note values over about a 4 octave range. It that correct?
    On the other hand, your note_table seems to have 128 entries for a 10 octave range, considerably more than a piano can produce.

    • remz

      Hi Robert,
      song_voice1/2/3 tables are reference to pattern numbers.
      The pattern contains actual notes. For example, the pattern 02 here:
          ; Voice 3: 'A-1' measure
          fcb 06,01 ; activate wavetable
          fcb 03,33,5,1 ; play notes..
          fcb 03,45,1,1

      The command “06” is used to activate a wavetable (an instrument),
      then the commands “03” are used to play notes.
      fcb 03,33,5,1 -> play note 33, duration 5, pause 1
      The valid range for a note is 0..127 which is used in a lookup table named note_table. This translates the note number into a frequency.
      You are right, the range is pretty large. The numbers themselve come from standard MIDI note, as can be seen here: http://www.phys.unsw.edu.au/jw/notes.html
      The displayed range is 21 to 108, thus notes beyond are too low or too high to be useful.

  • sixxie

    You can save two more cycles in your inner loop by self modifying the adds of the two previous .synth_outs – 1 more per store (extended over direct), but 2 less per add (immediate over direct). Then regenerate the note_table based on 77.68Hz base frequency.

    Not that you need to – it already sounds great! I’ve applied this locally though, because I’ve also tweaked it to run in slow mode (so I can get a Dragon doing it!) by doubling up the frequencies and halving the loop counter. The extra few Hz probably help at the low end.

    Nice code by the way; I’ve found it very easy to follow.

  • sixxie

    And another 3 cycles by doing exactly the same thing with the .synth_freq values – which brings the rate up above the mystical 20kHz figure!

    • remz

      !! Amazing!
      You managed in minutes to optimize my code which I spent hours and days fiddling around.
      Also the ‘SSynth’ structure has ‘synth_freq’ and ‘synth_out’ can now be removed, they are no longer useful since the self-modifying immediate values replace them.

      Ah and I just optimized it further by moving the code in the same page as ‘DP’ is set, thus self-modify code can now be accessed with direct addressing instead of extended: 5 clocks saved.
      ..and this leads to another optimization: removing the ‘mixtable’: this is unneeded now since I am not using clipping anymore, so simply adding the 3 waveforms together always give a valid value. This saves another 5 clocks. We are now down to 77 clocks, reaching an amazing sampling rate of 23247 Hz!

      All of this implied a lot of modification for taking account this new sampling rate. The loop had to be adjusted (or else the song would play faster), and the note table has been regenerated based on a 90.8 Hz frequency. And since I removed the mixtable completely, the waveform data are now unsigned values (0..84) instead of signed (-42..42). So adding 3 voices together yield a maximum value of 84+84+84=252. However something that could be problematic now is that CoCoSID emits spurious bits in $FF20 into RS-232C DATA OUTPUT and CASSETTE DATA INPUT. Maybe Robert can explain if this is wrong or unharmful..
      Also one important thing I had forgotten are the ‘glide/portamento’ which are hard-coded values of frequency glide. These also needed to be recomputed by hand to take account of the new speed. Else the glide will sound slightly off key.
      I can provide an updated DSK and updated source code.

      I just discovered after posting this that since register X is now unused in the mixing subroutine, it could be used here:
      stb #$FF20 ; 5
      stb ,x ; 4

      ..saving 1 clock by using indexed addressing instead of extended.
      However maybe register X can be used more efficiently in some other way.. Let’s keep looking and be creative.

  • joel.ewy

    RE: my earlier comment about the ROM on the Orchestra 90CC:

    Mine has a 28-pin ROM, which means it shouldn’t be very hard to replace it with a 2764. The pinout checks out OK. In fact, you could put in a 27128 and a toggle switch for the high address line to switch between HDB-DOS Drivewire and a copy of the original Orchestra 90 ROM. I may very well try this…


  • Robert Gault

    “However something that could be problematic now is that CoCoSID emits spurious bits in $FF20 into RS-232C DATA OUTPUT and CASSETTE DATA INPUT.”
    There is no harm per se in this but it is definitely not advisable if there is a device attached to the bit-banger port such as a printer.

    Most code you will see, that send sound data to $FF20, masks out bits 0&1 which slows down the program. The best way to handle the problem is to convert the RS-232 line, bit-2, into an input for the duration of the music program.

  • sixxie

    “The best way to handle the problem is to convert the RS-232 line, bit-2, into an input for the duration of the music program.”


  • sixxie

    “Ah and I just optimized it further […]”

    Excellent, I’ll be tweaking this locally too. I’d suggest sticking it into a version control system somewhere, but I’ve already made extensive changes to work with my assembler (which really needs ‘struct’ support – that’s a good idea).

  • sixxie

    I see the glide commands, ($08xx, value) – locally I’ve just defined cycle_ratio as (76/92) and multiplied them all by that. Hopefully correct, though a bit of a bodge! Sounds ok to me, anyway.

    This sounds pretty decent even with CPU at 0.89MHz now!

    Though I must admit, I’ve listened to one tune a bit much now. Your note values are directly mapped to MIDI notes, I see (is that the same on SID?), so a MIDI to cocosid converter doesn’t seem beyond the realms of possibilty :)

  • remz

    Robert: Thanks, I’ll look up the docs to set the RS-232 line as input!

    Sixxie: Your patch for the glide frequency should be close enough. Some part of the song which uses extensive glide do actually sound a little bit off. I haven’t spent the time to hand-tweak those values, I think it is acceptable as it is.
    As for MIDI notes, yes, CocoSID actually uses MIDI note numbers so converting a MIDI would totally be possible. Although the way it works is by repeating patterns, whereas a MIDI file would have a continuous sheet of music with possible repeat as some places. Interestingly, there is no restriction on the length of a pattern in CocoSID, so it could totally be adapted to play a MIDI file. A script could convert a .MID to a Coco friendly format.
    The ‘complex’ part would be building instrument. That’s where the program sounds most like a Commodore 64 SID chip: by switching waveform at 50 Hz, it can produce fast ‘arpeggio’ that have a particular sound. To create cocoSID, I’ve work by analyzing the sound created by the original Commando on the C64, so the result is pretty much tied to its sound characteristic.

    I am at the moment working on COCOSID2 which would play a SID converted automatically by a script. It is not fully operational but I think it will work. The main problem being the music itself taking too much memory space.

    By the way, do you have a working Coco 2 version? That would be interesting to hear. I figure you got rid of the graphics too?

  • sixxie

    Yep, ripped out anything CoCo3 and it works just fine at the lower output rate on the 1/2 and Dragon.

    I’ve left my mangling of your source along with .cas and .bin files here: http://www.6809.org.uk/tmp/da/cocosid/.
    [rem Edit: I fixed your url bracket.. Scaringly, I can edit your post..]

    • remz

      Sixxie you have done an amazing job. I just tried your .BIN running on a MESS coco 2 emulator (with 64KB memory) and it works beautifully. The mixing rate is half the CoCo 3 but it does sound decent indeed.
      I see by looking at your source code that you worked hard, nice way to emulate the ‘SSynth’ struct too. You understand the program amazingly well.
      I was about to tell you have neglected to regenerate the waveforms into unsigned values.. when I found your ‘waveforms_start’ little loop that adds 42 to everything. Very nice.

      • sixxie

        That is pretty scary! Especially as I don’t see any way to edit anything myself…

        As for understanding: I understand enough to know which bits I don’t understand, and to leave those well enough alone! Heh, actually no, you’ve documented very well in most places, and the rest can be inferred quite easily from overall function :)

        An idea: Address-dependent mode might not add much with everything running from RAM, and calculating the rate would be a bit annoying, but if my understanding of it is right (that there are NVMA cycles that cause fast clock) there are gains to be had even on the older machines (while staying stable and with display).

        After the weekend I’ll give it a go and see what happens!

  • RetroRick1974

    If it’s of use to anyone, you can find more SID files here:


  • sixxie

    So, here’s a curiosity that’s probably been covered before, but it’s new to me. The SAM data sheet, under “Changing the MPU Rate” (p11), discusses address-dependent mode, and specifically states that as the CPU ouputs FFFF on the address bus during some “dead” cycles, speed gains can be had as that address is one that triggers /8 MPU rate instead of /16.

    After totting up the half cycles (using http://koti.mbnet.fi/~atjs/mc6809/Information/6809cyc.txt as a reference), I make the requisite recalculations of sample rate etc., and it’s lovely under XRoar because I’d implemented that behaviour. Then I uploaded it to a real Dragon and find it’s not quite right. In fact, it’s exactly as not quite right as if I remove the switch to address-dependent mode, meaning that no speedup is being had at all on real hardware.

    Has this been discussed before? I’m assuming the data sheet is just wrong in this respect. I’m in map type 0. Anybody got any insights?

  • jdiffend

    @sixxie, my understanding was that the high speed POKE with a SAM only works in the ROM bank area. RAM is always normal speed.

  • Robert Gault

    Why don’t you try the full fast mode. You will lose video but all addresses will run at 2MHz. Once the program is finished just go back to .98MHz and video will be recovered.

    I used to run some Coco1 programs that did math at full fast mode and never had a problem returning to slow speed. Of course if playing music with CocoSID, you would like to see the graphics. But it might work quite well for audio at full fast speed.

  • DarrenA


    I don’t know if you would see much benefit from the faster “dead cycles” if your code is running from RAM. A typical instruction like LDA $xxxx takes five cycles, with only one of those being a dead cycle. The dead cycle falls between two live cycles. The SAM has to switch rates at certain point within the cycle when it sees the address presented by the CPU. The address bus is unstable during a portion of each cycle, so I’m not sure if a single fast cycle in between two slow cycles would have much affect at all.

    It may be that you need to have a run of multiple fast cycles (where the SAM doesn’t have to switch rates on consecutive cycles) to see any real boost.

  • sixxie

    jdiffend: True, but also some other regions above the 32K line. SAM/CPU data sheets imply that during cycles lost to internal operation, CPU will output one of those addresses (and specifically claims it’ll speed things up!)

    Robert: Ah but then there’d be nothing for me to do! Also, nice to imagine using this to play some title music. And while I’m sure the requisite addresses will be accessed during playback, there’s still that possibility of failing to refresh everything.

    DarrenA: Sounds plausible, though in this case every last “half” cycle would help (and be noticeable). I always imagined that at the point the SAM latched the address, that determined the next whole cycle timing. Ah well, good to learn something new, even if it’s not what you hoped.

  • jdiffend

    So, when will an General Instruments AY-3-891X emulation be done?
    It should be easier. 😀

  • DarrenA

    I decided to test the VMA cycle usage under address-dependant mode to see if any gains could be had. It is possible, but does seem that you need to have a run of consecutive VMA cycles to see any difference. This implies that typical code sequences would likely not benefit much if at all.

    I used the following code to perform the test. I loaded it into RAM at $4000 on an NTSC CoCo 2.





    STY $600 ; STORE COUNTER AT $600

    Each iteration of the LOOP uses 8 cycles, with 3 of those being VMA cycles. The two VMA cycles in the LEAY instruction run consecutively. This loop runs 1866 times in both Normal and Address-Dependant mode, so there doesn’t appear to be any significant difference.

    If an LEAU *+100,PCR instruction is inserted into the loop, this adds 9 additional cycles, with five of those being consecutive VMA cycles. Now the loop runs 878 times in Normal mode and 995 times in Address-Dependant mode, saving about 2 cycles for each iteration.

  • sixxie

    That’s good research! Needs more determinism for my liking, but further tests can get that, I’m sure. Looks like you’re right about needing some time for the rate to “kick in”, though that makes absolutely no sense in my head :)

  • DarrenA

    The SAM datasheet you referenced shows a waveform diagram for the rate transitions. It lacks detail, but certainly gives the impression that a single fast cycle would have no benefit because it stretches the low portion of the Q clock during a transition from slow-to-fast.

  • briza

    G’Day Remz.

    A fellow coconut called Torsten in Germany says he knows a great website that contains C-64 Sid files. Here is the link to it: http://www.hardsid.com

    Here is 1 of the files you will find in the website.



  • sixxie

    DarrenA: I see what you mean. Looks like any transition basically leaves you with the first cycle still effectively “slow”. Boo!