CoCo fun

Hi All,

This post was spurred on because I was replying to a comment today where someone was asking for my z80 to 6809 program and the link was dead.  I updated the link to the latest version I could find on my computer.  After replying to him I thought I might as well make this little post.

It’s been almost 1.5 years since I’ve posted anything here but life has been treating me like a baby treats diapers and I lost interest in using my CoCo.  But lately I’ve been playing a little with some of my old 6809 code and enjoying it.  I hope it continues to be fun and I have something useful to post here for the CoCo community in the future.  I guess we’ll see.

For those that are wondering about my Defender conversion, it was at a point that it would play weirdly and crash randomly.  I remember fighting with the code for hours and hours but couldn’t figure out why it was doing the things it was.  I think I needed to improve the emulation of the scanline location code too, at least I remember doing a lot of thinking about that code back then.  Anyways it will be a long time until I’m back into the CoCo enough to look at that code again.  But maybe one day…

I hope all my CoCo friends are well,

Glen

 

Posted in Uncategorized | 6 Comments

Defender Conversion for the CoCo 3 – Part 6 – Three out of Three attract Screens are converted

Today I completed converting the Defender Arcade code to play through all three attract modes.  The last one was definitely the hardest as it contains the sprites moving around the screen.  I also had to convert how Defender draws the planet surface and get the scanner working.  Unfortunately the CoCo 3 doesn’t have enough rows on the screen to match the height of Defender.  So I decided to leave the playfield area exactly the same as the arcade version so the play and feel will be the exact same on the CoCo 3.  To make room for the scanner at the top of the screen I had to reduce the height of it by half.  This should still give me enough room for the player’s reserve ships, smart bombs and score to fit.  Click here to see the video of the conversion so far.

Screen Shot 2018-02-07 at 7.34.53 PM

Now I can start on the actual game play, hopefully it won’t be so bad since most of the graphics conversion is done and it’s a matter of adding the controls and all the game logic.

 

Posted in CoCo Programming | Tagged , , , , | 9 Comments

Defender Conversion for the CoCo 3 – Part 5 – Another cool 6809 coding trick they used

Hello, I just wanted to document this neat little trick here.  For changing the colour of one of the 16 stars on screen randomly in Defender they do the following:

* Table of stars @ $AF9D to $AFDC
* Format of each star is a 4 byte entry
* 00 & 01 - address on screen
* 02 - ## where both nibbles match and are a value from 00 to 77 the even or odd pixel will be used at the proper time
* 03 - starts with a value of 00, I think it is ignored so the stars can change their colours a little quicker see the ANDB #$3C @ $E0F6
* Change stars colours
        LDB    <MA0DF     ;E0F4: D6 DF   B=($A0DF) = Random value
        ANDB    #$3C    **;E0F6: C4 3C   B can't be more then $3C (# of stars table entries) and force it to be a multiple of 4 * Cool * $3C = 00111100
        LDX     #MAF9D    ;E0F8: 8E AF 9D point at the list of stars
        ABX               ;E0FB: 3A      move the pointer to certain entry in the table
        LDA     $02,X     ;E0FC: A6 02   A = stars pixels colour byte value
        ADDA    #$11      ;E0FE: 8B 11   increment each nibble
        ANDA    #$77      ;E100: 84 77   make sure it's between 00 and 77
        STA     $02,X     ;E102: A7 02   save the new colour value

What makes this code neat?

Well they get a random number to choose which star will change its colour (first line above).  Normally you would do an AND #$0F so you have a value between 0 and 15 (your 16 entries) then you shift the value to the left two times which multiplies your value by 4.

That would mean your code would look like this:

ANDB  #$0F
ASLB
ASLB

See the Defender code listing above to do the same thing faster they just used ANDB   #$3C which does both things at the same time.  It limits the random number to a value between 0 and $3C but also makes it a multiple of 4.  Sweet

The two ASLB instructions requires 2 CPU cycles each, 4 cycles total aren’t much but this is used 60 times a second and is another example of some cool programming used in the game.

See you next time…

 

Posted in CoCo Programming | Tagged , , , , | Leave a comment

Defender Conversion for the CoCo 3 – Part 4 – Two out of Three Attract Screens are converted

I’ve been working hard on the Defender conversion and am happy with the progress and how well things are going.  I uploaded a video on YouTube showing that I now have two out of three attract screens working.  The code for writing the Williams logo was pretty cool.  The particle routines that Defender has for the “Beam In” effect was a big pain to work out on the CoCo 3.  The Defender hardware is optimized for handling the particles but I have written some pretty optimized code to emulate it.  The CoCo 3 version is now a few more CPU cycles slower than the speed of Defender.  Since the CoCo 3 is running at 1.78 Mhz and Defender runs at 1 Mhz, I feel pretty confident that the speed of the CoCo 3 version should be the same as the real thing.

Screen Shot 2018-01-24 at 11.25.58 PM

 

Screen Shot 2018-01-24 at 11.27.31 PM

The next attract screen is going to be a killer, as it pretty much has most of the game on screen.

Defender has a unique IRQ that is triggered every 4 milliseconds that is tied to the VBLANC/VSYNC.  It has hardware that can be checked to see where the scanline is being drawn.  With a 4 millisecond IRQ that means the screen is split up into 4 sections.  This allows Defender to update parts of the screen without the need for double buffering.  For example if the scanline is checked and found that the scanline in drawing the bottom half of the screen then Defender will draw sprites on the upper half of the screen.

I have figured out a way to emulate this IRQ on the CoCo 3 and it is being used in my version right now.  It hasn’t been tested with moving sprites yet as I haven’t got that far in the conversion yet.  Once I have it tested with running sprites on screen and I know it’s working properly I’ll go into details of how it works.  If it works the way I think it should then it could be a really nice way for game developers to put sprites on the screen without the headaches of double buffering and the extra  memory needed for handling two screens worth of graphics.

At this point I have all the hardware emulated so I’m in pretty good shape to move on to the last attract screen.  Then it will be on to the game itself!  I still haven’t come across the code that draws the land on the bottom of the screen which I’m looking forward to seeing how they pulled that off.  The last attract screen shows the land so I’ll be coming across that code soon.

See you in the next post… Glen

Posted in CoCo Programming, Emulation | Tagged , , , , , , , | 3 Comments

Arcade Machine Conversion to the CoCo Overview

Hello, in a recent post I got a comment from username Perezernestoj who asked if I could convert Super Pac Man as my next game for the CoCo after I complete Defender.  I explained how much work this is and that you would only do it if that particular game meant enough to you to go through all the effort.  Well Perezernestoj said he might give doing the conversion himself a try.  It just occurred to me that I should put together some notes to aid not only myself but others that are thinking or might want to convert an old favourite Arcade game to the CoCo themselves.

In this short post I’m going over at a very high level what is involved in converting an old classic Arcade game to the CoCo and my approach to it.  These are some things I’ve learned so far…

  • Gather all info you can about the game from the internet, including technical/repair/owner manuals and read/watch interviews with the original game authors and make notes if they talk about your hardware.
  • If you are super lucky you can find a commented disassembly of the game online.  Some games use the same hardware as other games.  If you can find a commented disassembly of a game that uses the same hardware keep that info close it will help decoding a lot of your game, especially the sound and controller routines.  If you aren’t lucky enough to find a disassembly you will need to create your own disassembly of the game.  Maybe the hardware info you found will help you to figure out what ROMS hold data such as text messages and sprite info.  The more info you have about the layout of code and data sections the better your disassembly will be.  Looking through manuals and MAME source code for your game may help figure out what is machine code and what is other data.
  • It is also useful to break up your big disassembly into small parts to refer to.  For example if you find the data sections have a bunch of text messages you might want them in their own .asm file so you can refer to it quickly as you go through the code.  If you only have one big disassembly file to scan through it will mean a lot of jumping around from one section to the other and it can really slow you down.

My method of decoding a game:

  • As you decode and convert routines from the disassembled source code, from the original to CoCo format always keep the original code with the address in RAM info to the right so you can refer to it later (this comes in handy so much!)

Here is an example of what I mean from my Pac Man transcode.  The left is the 6809 (CoCo) assembly version and on the right is the Z80 (Pac Man)  disassmelby with the original address of the code and to the right of that I put in my own comments as  I go:

; Routine to determine number of pellets to eat
PelletCount:
        LDA     PelletsEaten                        ;08DE 3A0E4E      LD      A,(PelletsEaten)  ; number eaten
        CMPA    #$F4                                ;08E1 FEF4        CP      0F4h ; '('        ; compare to 244
        BNE     loc_8EB                             ;08E3 2006        JR      NZ,loc_8EB        ; jump if not done
        LDX     #CurrentTaskNumber                  ;08E5 21044E      LD      HL,4E04h          ; set level complete
        LDA     #$0C
        STA     ,X                                  ;08E8 360C        LD      (HL),0Ch
  •  From the hardware info you should be able to find out the address that the game starts at.  Sometimes called the RESET vector.  Start decoding where the game normally enters it’s startup routine.  Not at the first line of code (unless it is the startup routine) the startup routine is most likely going to be code that tests the ROM/RAM and other hardware.  This will usually show some messages on the screen this will force you to figure out how the game writes text to the screen.
  • Once you know how text on the screen is written you can go through the entire code and find where it jumps to the “SHOW TEXT” routine and markdown what text is shown on screen at that point in the code.  This gives you a good idea what the code in that section is actually doing before you even decode it.
  • If you can figure out how sounds are created in the game then you can do similar things to the above.  Find the routines that jump to “Play Sound” and mark that section as playing a specific sound like firing or starting a level.
  • Buttons are good info too, if you can find the code where the buttons are read then you can figure out what sections of code are used for firing and moving the player and handle coin insert and player start.  When you find where the player controls are you can figure out how it draws sprites on the screen and also where in the code it draws the enemy ships.
  • The ROM/RAM tests will fail, because our bytes won’t match the original processors code, so I just fake that the tests passed in the code and move along.  Once you have the main initializing code converted to a CoCo version where it shows something on the screen you should test your version on a CoCo or MAME this will make sure you understand how the graphics hardware works for the original game and it is very motivating to see your conversion is actually looking like the original game.  If you can get any initializing sounds working that the original game makes when starting up then that will also help to keep you motivated…  You can also work out audio later once the game is converted to a CoCo version.
  • Games will initialize themselves to a specific way from SRAM settings or hardware DIP switches before the game starts and the IRQ is turned on.  These are things like what score does the player get a free man and how many men does the player get per coin, how difficult the game mode will be, etc.  Then it will start up the IRQ.
  • Figure out how the IRQ works for the game, once this is figured out you have the heart of the game.  Everything is usually triggered based on the IRQ so you can decode different sections of code in the IRQ.  At the IRQ starting point, your game is about to start, probably in the attract mode until it detects a coin insert or player start button being pressed.
  • If you have converted the code to the CoCo version upto the IRQ then you will need to setup an IRQ on the CoCo to be triggered the same way the arcade machine does.  So far I’ve found most are triggered by the VSYNC IRQ.  So setup a Vsync IRQ on the CoCo and in your conversion emulate the routines in the IRQ one at a time.  Start by removing the jumps to routines you haven’t decoded and get a version of your code that can be assembled so you can test your progress on a CoCo or MAME as you progress through the different routines in the IRQ.

To help decoding have the original arcade game running in MAME in debug mode where you can setup breakpoints and watchpoints and step through the original game code and see exactly what it is doing at any point in the program.  It also shows the memory and registers…  I have a previous blog that explains how to program for the CoCo and use MAME in debug mode that will probably be helpful at this point.  That blog post is here.

One other thing I should mention is that a lot of old games use other processors then the 6809.  Many use the Zilog Z80 CPU and I have written a converter when I worked on Space Invaders and Pac Man to help get started that converts Z80/8080 assembly code to 6809 assembly code.  I talk about this in my older blog posts here and here.

Good luck with your own Arcade conversions…

Glen

Posted in CoCo Programming | 1 Comment

Defender Conversion for the CoCo 3 – Part 3 – Two more 6809 coding tricks they used

Below are a couple of coding tricks I’ve learned from Defender this week.  I thought I’d pass along the tricks for others to use, if they aren’t already.

For simple loop counting, a nice fast way is to load an accumulator with the count and do a DEC instruction such as this:

        LDB    #7    * number of times to loop
Loop:   STA    ,X+
        DECB         * Decrement the loop counter
        BNE    Loop  * loop until we reach zero

If you need to do a loop but you know your accumulators value will get changed because of some JSR or BSRs you can use the technique in Defender below and push the counter on the stack and use DEC   ,S  to count down your loop counter.

As per Defender, do an LDA   # of times to do the following.
The loop is at $D6B1 to $D6B8

        PSHS    A                        ;D69F: 34 02
        LDD     #M030B                   ;D6A1: CC 03 0B    3 sets, 11 bytes each
        JSR     ScrnBlkClr               ;D6A4: BD F5 C7    Go clear the area out
        LDA     ,S                       ;D6A7: A6 E4       Get number of smart bombs left
        BEQ     ZD6BA                    ;D6A9: 27 0F       if zero don't draw - exit
        LDY     #MF9D9                   ;D6AB: 10 8E F9 D9   Data for Reserve smart bombs
        TFR     X,D                      ;D6AF: 1F 10
ZD6B1:
        JSR     DrawChar                 ;D6B1: BD F5 22        Draw smart bomb as a character
        ADDB    #$04                     ;D6B4: CB 04           Move Down 4 bytes
        DEC     ,S                       ;D6B6: 6A E4           count down # of bombs
        BNE     ZD6B1                    ;D6B8: 26 F7           if not done go draw another
ZD6BA:
        PULS    PC,A                     ;D6BA: 35 82

Another tip to save a byte of RAM, if you have a value and you want to know if it is one and don’t need to use the value itself, then change this:

        LDA    <MA08C
        CMPA   #01
        BEQ     ZD697

Use this instead:

        LDA    <MA08C                    ;D68A: 96 8C
        DECA                             ;D68C: 4A
        BEQ     ZD697                    ;D68D: 27 08

This could also be used if you wanted to test a few different values of A.  For example if you needed to check if A is a 0,1 or 2 you could do this:

        LDA   <MA08C
        BEQ   JumpAisZero
        DECA
        BEQ   JumpAisOne
        DECA
        BEQ   JumpAisTwo

Anything bigger than this and you might want to use a jump table…

Nothing mind blowing but neat little tricks to keep in mind…

See you in the next post,

Glen

Posted in CoCo Programming | Leave a comment

Defender Conversion for the CoCo 3 – Part 2 – Short and Sweet

Just a little blog entry to share a neat little bit of 6809 code.
I’m really impressed with how well the 6809 is programmed in Defender.  I was decoding some of the Defender source code today and I came across some neat code to handle the button presses.  Someone other then myself might like to use this code in their own projects.
Defender get’s many of the buttons into the A accumulator bits 7 to 0 (7=Down,6=Reverse,5=1 Player Start,4=2 Player Start,3=Hyperspace,2=Smart Bomb,1=Thrust,0=Fire)
Then it uses this cool bit of code to handle the bits that are set (active).
       LDU   #MF882 ;D5E2: CE F8 82 Load U with table start position (add 4 to get real start address)
ZD5E5: CLRB         ;D5E5: 5F       B=0 & Clears the Carry flag on the CC register
ZD5E6: ADDB  #$04   ;D5E6: CB 04    B=B+4
       LSRA         ;D5E8: 44       Shift A which has the button values into the Carry bit
       BCC   ZD5E6  ;D5E9: 24 FB    If the bit position was a zero (button not pressed) then go check the next
       LEAU  B,U    ;D5EB: 33 C5    U=U+B U now points to the location in RAM to get the four bytes associated with the button press
       PULU  X,D    ;D5ED: 37 16    LOAD D & X with the button value
       ...

I like the use of the carry bit to find the active bit and then using U as the pointer and instead of loading X & D it pulls the data into the registers.  This saves cycles and space!  If you had to access the data from a table that had 6 entries you can do the same thing except you would use ADDB   #$06 and PULU  Y,X,D.  This becomes even better since a load to the Y instruction is slower and takes more space.  Neat stuff!

I’ve already used this technique to speed up my audio playback code since each sample needs it’s own Bank # in CoCo 3 memory, the # of banks the sample uses, start address and what MMU bank location to use.

Here is my setup code used whenever a sample is changed in Defender for the CoCo 3.  This uses the same PULU technique I just learned from the Defender code and even pulls the value of the Y register and uses it as the pointer to update the MMU page selections.

See you in the next post…

* Playback sound sample # in B
* Input = B
*****************************
PlaySoundB:
        PSHS    A,X,Y,U
        LDU     #SoundBankLocation
        LSLB                        * B=B*2
        STB     PlySndAddB+1        * Save the value for the add, self modify
        LSLB                        * B=B*4
PlySndAddB:
        ADDB    #$00                * B=B+(old B*2 value)
                                    * So B=B*6 - This value gets self modified, for the amount to add to B from above
        LEAU    B,U                 * Move U pointer to the correct position
        PULU    A,B,X,Y             * Load A,B,X & Y from the table below
                                    * A = Bank in RAM where the sample data is located
                                    * B = # of Banks this sample uses
                                    * X = Address where the sample data starts
                                    * Y = MMU Register Page Location the sample data will use to start playback from
        TSTB
        BMI     PlayRepeatSound     * If B - bit 7 is high then it indicates this loop is one the repeats go setup and play this sample looping
        TSTA
        BEQ     PlayNoSound         * If A = 0 then this turns off the audio output
!       STA     ,Y+                 * setup the correct MMU page selection to match where the samples are in RAM
        INCA
        DECB
        BNE     <
        STX     LoadAudio1+1        * Save the Audio playback start point in the playback routine memory directly
        LDX     #FIRQ_PlaySoundOnce * Playback sample once (no loop)
        STX     FIRQ_Jump_position+1    * Update the FIRQ Jump address
        PULS    A,X,Y,U,PC          * Done
PlayNoSound:
        LDX     #FIRQ_NoSound       *  Audio off
        STX     FIRQ_Jump_position+1    * Update the FIRQ Jump address
        PULS    A,X,Y,U,PC          * Done
PlayRepeatSound:
        STA     MMU_Reg_Bank1_3 * Block $6000-$7FFF  Block #3
        STX     LoadAudio2+1        * Save the Audio playback start point in the playback routine memory directly
        STX     SampleStart         * Save it so when the sample player gets to the end of the sample it will load this value and start again
        LDX     #FIRQ_PlaySoundLoop     * Playback sample looping
        STX     FIRQ_Jump_position+1    * Update the FIRQ Jump address
        PULS    A,X,Y,U,PC          * Done
* Table will need these values
* Sample start address and the Bank or Page the sample starts from
*                        Start  MMU Reg
*       Bank,# of Banks,Address,Bank Location
SoundBankLocation:
        FCB     $0F,$02,$42,$17,$FF,$AA        ;00 Startup Sound
        FCB     $11,$04,$03,$55,$FF,$A8        ;01 Free Man
        FCB     $00,$00,$00,$00,$FF,$AC        ;02 ?? Sounds like Robotron Tank ??
        FCB     $00,$00,$00,$00,$FF,$AC        ;03 No Sound
        FCB     $00,$00,$00,$00,$FF,$AC        ;04 No Sound
        FCB     $15,$04,$04,$E9,$FF,$A8        ;05 Human falling
        FCB     $19,$02,$4A,$DB,$FF,$AA        ;06 Coin Inserted
        FCB     $00,$00,$00,$00,$FF,$AC        ;07 No Sound
        FCB     $1b,$02,$43,$10,$FF,$AA        ;08 Player or Enemy Death part2 Explosion
        FCB     $1D,$81,$60,$02,$FF,$AB        ;09 Player thrust
        FCB     $1E,$01,$66,$D3,$FF,$AB        ;10 Enemy/player teleports on screen
        FCB     $1F,$04,$00,$05,$FF,$A8        ;11 Player Fire
        FCB     $00,$00,$00,$00,$FF,$AC        ;12 No Sound - After death
        FCB     $00,$00,$00,$00,$FF,$AC        ;13 No Sound
        FCB     $23,$01,$6F,$AC,$FF,$AB        ;14 Player or Enemy Death/Smart Bomb
        FCB     $00,$00,$00,$00,$FF,$AC        ;15 No Sound
        FCB     $24,$81,$60,$0E,$FF,$AB        ;16 Play Thrust slow down sound
        FCB     $25,$01,$61,$5E,$FF,$AB        ;17 Lander & Humanoid turn into Mutant
        FCB     $00,$00,$00,$00,$FF,$AC        ;18 ??? Sounds like Joust ???
        FCB     $26,$01,$71,$FA,$FF,$AB        ;19 Swarmer shooting
        FCB     $27,$01,$6C,$95,$FF,$AB        ;20 Human picked up
        FCB     $28,$03,$36,$A3,$FF,$A9        ;21 Player 1 or 2 Button Pushed
        FCB     $2B,$04,$00,$01,$FF,$A8        ;22 Mutant attacking
        FCB     $2F,$01,$7A,$A7,$FF,$AB        ;23 Picked up human in the air/Got 500
        FCB     $30,$01,$66,$B9,$FF,$AB        ;24 Shot the Baiter or swarmer
        FCB     $31,$01,$72,$1D,$FF,$AB        ;25 Play hit Alien Ship
        FCB     $32,$04,$04,$C6,$FF,$A8        ;26 Shot the Pod
        FCB     $00,$00,$00,$00,$FF,$AC        ;27 No Sound
        FCB     $36,$01,$7C,$0B,$FF,$AB        ;28 Enemy fire
        FCB     $00,$00,$00,$00,$FF,$AC        ;29 No Sound
        FCB     $37,$01,$63,$85,$FF,$AB        ;30 shot the bomber
        FCB     $00,$00,$00,$00,$FF,$AC        ;31 No Sound
Posted in CoCo Programming | 7 Comments

Defender Conversion for the CoCo 3 – Part 1

Hello, I wasn’t going to blog about my conversion of the arcade version of the William’s classic game Defender for the Tandy Color Computer 3 but I decided it might be nice to share some of my progress.  Especially when there is something to see.  I made a video showing the loading of my Defender and the startup screens and sound.  It’s kind of a boring video but it does show what it will be like eventually once the game is finished (actually it might use 4 disks!).  You can view the video here

FYI – The rest of this blog is a little techie…

I’ve gathered up all the information on Defender I could find on the internet.  Two fantastic resources are The Computer Archeology’s Defender page and the other is Sean Riddle’s William’s Arcade Games Info page

Summary of what needs to be dealt with for this conversion:

Video display – Defender uses a display size of 304×256 pixels which can show 16 colours on screen at one time.  Each byte holds 2 pixels just like the CoCo 3 320×225, 16 colour screen.  Defender has a 256 colour palette where the CoCO 3 has 64, so Defender does have a little more fidelity in the colours to choose from but it probably wont be noticeable.  Defender’s screen RAM is not laid out like normal video RAM.  The top left corner in RAM is $0000 but the next byte $0001 is not the byte to the right of it but actually the byte below it.  To move to the right you must add 256 so $0100 is actually the byte to the right of $0000, that will have to be dealt with during the conversion.  The big problem is the height of the screen.  Out of the actual 304×256 pixel screen Defender only uses 290×241, I guess to make sure overscan on the monitors isn’t a problem.  Defender displays 241 rows, the CoCo 3 only has 225 rows.  So I either cut the screen off and not show the bottom 16 rows or I could maybe shrink the top of the display where the radar is displayed.  Or I could do what I did with Pac Man and scroll those bottom 16 rows if your ship gets below the middle of the screen.  I still don’t know what I’m going to end up doing here…  Too bad the CoCo 3 didn’t have a nice standard 320×240 pixel screen.

Defender_Screen

Audio Output – Defender has a dedicated audio board that when sent a number would play a specific sound.  The hardware can only play one sound at a time.  As far as I can tell at this point Defender uses 21 different sounds even though the sound board has a few more sounds that it can create.  I’ve already converted these samples to a format that the CoCo 3 can playback using the FIRQ so this shouldn’t be too much of a problem or a hinderance to the speed on the game.  The audio is converted to 8 bit unsigned 6kHz samples.  Since I now have a CoCo flash I think I’ll output the audio to both the CoCo audio port and the CoCo Flash/Orchestra 90 audio outputs.  Audio in this format doesn’t compress well and they require 287,432 bytes!  That’s two disks just for the sounds used in Defender.  I could cut that down by 1/4 if I reduce the samples to 6 bit samples which is the maximum format the CoCo’s built in DAC can use.  But it’s still going to be huge so I figure I’ll leave it and try to get it to work with the CoCo Flash/Orchestra 90 cartridges.  It’s something new for me to learn, although I don’t think there’s much to it other then sending the data to a certain address in the CoCo 3.

Controls – Defender has a lot of buttons/controls.  I don’t think this will be a problem.  I will be coding it to use the keyboard only.

Program Code – Defender uses the awesome Motorola 6809 CPU running at 1.00 Mhz.  The CoCo 3 uses the same CPU but runs faster at 1.78 Mhz which leaves us with CPU cycles to spare!  Useful for audio playback and other things that will need to be dealt with like the screen layout conversion/scaling.  This is good news and hopefully I can just use a lot of the code as it is without having to tweak it too much!

RAM/ROM Layout – While reading through the above websites I learned that Defender and other William’s Arcade games use 4 Banked sections of code.  Which I figured I could duplicate since the CoCo 3 already has banked switching.  Defender swaps $1000 bytes of ROM in and out of location $C000 to $CFFF.  The CoCo 3 swaps out blocks of $2000 bytes and can only swap out the block at $C000-$DFFF.  Since the CoCo has a lot more RAM I decided I would just copy the code in $D000-$DFFF in each of the 4 Banks.  So now the swapping of the Banks will not change the code at $D000-$DFFF.  Another thing I realized that can save me a lot of headaches is to use the same Bank numbering scheme that Defender uses on the CoCo 3.  Namely  Bank 1, Bank 2, Bank 3 and Bank 7, so I’ll use the exact same Banks in the CoCo 3.  Anytime the Defender code changes the Bank by writing to address $D000 with the Bank #, I just have to change the $D000 to $FFA6 (Page $C000-$DFFF  Block #6) and it “should” just work.

This is what I have working so far

Audio – I have the audio samples all working and tested the playback of the single samples.  There are a couple of samples that repeat though like the player thrust sound and when the players ship slows down.  The code works, I just have to figure out where in the game the samples get used and tweak it to use my code instead.

Sprites – I’ve taken all the sprite data used in Defender and made compiled/blasted sprite versions of them.  I’ve also made compiled/blasted sprite versions of the text characters that are displayed on screen.  I’ve tweaked the draw character routine to use my compiled sprite versions of drawing text characters to the screen and  my compiled sprites render the text characters a lot faster then how the real Defender did it, which used simple Load and Store instructions to the screen memory.  My compiled sprites draws a 3×8 character takes on average 129 CPU cycles.  The real Defender code draws the same 3×8 characters but takes 291 cycles.

Defender has the benefit of drawing sprites to the screen memory as it’s video memory is laid out in a way that is useful for stack blasting.  Especially fast for erasing sprites on screen.  Which is the technique Defender uses for drawing it’s sprites on the screen.  It’s so amazing to me that the original programmers (Eugene Jarvis, Larry DeMar and Sam Dicker) back in 1980 & 1981 had already figured out that stack blasting is an amazingly fast way of moving data around using the 6809!  I should also mention that from what I’ve noticed so far of the Defender 6809 code is really top notch programming and highly optimized code.  They really did make excellent use out of the 6809.  My compiled/blasted sprites on the CoCo 3 are faster then stack blasting on the CoCo 3 but with the layout of the graphics RAM on the Defender hardware stack blasting the data is faster.  It’s not that bad though, my compiled/blasted sprites are only about %20 on average slower, some are actually faster.  The good news is our CPU is running 78% faster so it “should be” possible getting the game to run at 100% the same speed as the original.

Program Code:

  • I have the RUG pattern showing up during the RAM/ROM tests, which doesn’t really test the RAM or ROM in my version.  I want to save the space for code changes plus the code wont match the original and a true RAM/ROM test would fail.
  • Audio playback handling is good to go.
  • Bank switching locations match Defender’s Bank switching.
  • Character Text displaying routine working twice as fast as the original Defender, all code in place after the RAM/ROM test up to the point where it shows the message “INITIAL TESTS INDICATE UNIT OK”

What’s next?

Next I will add in more ROM data and go through the code and add or tweak it as I go.  I’ve really only started with the real game code so far.

Cheers, Glen

Posted in CoCo Programming | 2 Comments

MIDI 2 CoCo Converter

This is a program that converts MIDI files and outputs the converted music in one of three formats for the CoCo to playback.  It outputs the music data alone or along with the player for the given format.  The output formats that are supported are:

  • Simon Jonasson’s – DIPOLE.ASM software music player
  • John Linville’s – Game Master Cartridge support with my software player
  • Ed Snider’s – CoCo Programable Sound Generator with my software player

The program started out as a simple command line based tool that would take MIDI (.mid) files and output them in a format that would playback on Simon’s dipole.asm software music player.  I had the basic MIDI converter working where it would just describe the instrument and ask you what two instruments you wanted to convert.  This really meant that in order to use the tool you would have to prepare your own MIDI file removing tracks you don’t want, (which might still be necessary for complicated songs.)  This would be OK for a quick and dirty converter but I figured if I’m going to share this with others that I should make it a little more user friendly.

I then decided that I would show the user all the tracks and let them pick the instruments from a GUI.  This really works well since it shows you what instruments are used for the different parts of the song.  If any one instrument is used for only part of the song then you could see it and actually select a few instruments as long as they didn’t play notes at the same time.  You couldn’t figure this out without looking at the song with the separate track all laid out on the screen.

Once I got the GUI working and was able to convert the MIDI files to Simon’s Dipole.asm format I realized I could do a similar thing for John Linville’s Game Master Cartridge.  Since MAME supports the cartridge it allowed me to experiment and learn how to program the Texas Instruments SN76489 sound chip that is used inside John’s cartridges.  I was just about finished working on my own GMC format player when Ed Snider posted on Facebook that he was ready to send out some CoCo Programmable Sound Generator cartridges.  So I bought one off Ed and continued to finish up the GMC format and add in my MIDI to GMC format player code.  Since Ed’s cartridge is more of a dedicated sound card for the CoCo that would stay in your Mult-Pak Interface I figure it would be helpful to BASIC programmers if I made my MIDI 2 CoCo converter output the music and player in a way that anyone could easily use it to add background music in their programs.

Here is what the MIDI to CoCo converter can do, it converts MIDI files to:

  • Simon’s dipole player format along with the player all ready to have an assembly programmer add their code to the end of the program and it will automatically include the music in the background.
  • Simon’s dipole player format, just the music data in assembly FCB format which you can add to your own assembly program and add Simon’s dipole.asm music playing code in your own program.
  • John Linville’s GMC playable format along with my own player in a format that can be used in creating your own game cartridge to easily add music to your game.  ready to be tested using MAME
  • John Linville’s GMC compatible format assembly FCB format file to be used with my GMCPLAY.asm program to be used in your own game cartridge code
  • Ed Snider’s CoCo PSG playable format with my own player that can be easily added as background music to your BASIC program.  The sound data is stored on Ed’s CoCo PSG 512k RAM leaving lots of room for your BASIC program.
  • Ed Snider’s CoCo PSG playable format with my stand alone PSGPLAYER.asm that can be used as part of your own assembly program/game and easily allow you to add background music to your assembly program.

Where do I download the program?

You can get the program and the support files on the Tandy Forum in the Software Project section and soon the TRS-80 Color Computer Archive

Need to Install QB64 on your modern computer

The converter is written in QB64 which is BASIC for modern PC’s.  You can use it on Mac, Linux and Windows.  It takes your BASIC program and in the background turns it into C++ code which is then compiled on the host computer and outputs a completely independent program that is ready to be executed on that host computer.  It doesn’t need any other support files or libraries it is ready to be executed as it is and since it is run on a modern computer it runs super fast!  First thing you need to do is install QB64 on your modern computer.

Once installed you take my basic program (mid2coco.bas) and load it into QB64.  Then you  click on Run | Save EXE in the source folder.  Finally click on Run | Make Executable Only.  From that point on you have a stand alone program that can be moved and used just as any other program on your computer.

Make sure the mid2coco executable file is in the mid2coco folder.  If you want to use the mid2coco program in a new folder you need to have the mid2coco program along with the following files that are required for certain output modes.  You need to have GMC_Play.asm, Dipole_Part1.asm and Dipole_Part2.asm along with the MIDI files that you want to convert in that new folder.  You run the program from the command line.  Change your directory so you are in the directory with the new mid2coco executable that you just made and use this command:

mid2coco MIDIFILE.mid

For example to convert a MIDI file called Axelf.mid:

./mid2coco Axelf.mid

or

mid2coco.exe Axelf.mid

Then the program asks you what output format you would like.  Select the output based on the output format you require as per the picture below:

mid2cc_screen1

Select the output format you want (1 to 6).  Also you can add the letter p after the number to have the program output the music data for the proper playback speed for PAL computers (for example 5p) otherwise it will default to using NTSC timing.  Note the PAL timing hasn’t been tested.

Next you are asked if you want to transpose the MIDI file one octave higher, since some older MIDI files were created this way.  Most of the time you can just hit enter as the default is No.

Next it asks you what type of CoCo you will be using the program on.  This really doesn’t matter except if you are using Ed Snider’s CoCo PSG from BASIC where it will give you some instructions of using the loader and player in BASIC, and what the addresses are to start, stop and continue playback.

Next you are shown a list of the tracks and the instrument names for each track that is in the MIDI file.

If you selected Simon’s dipole.asm format then you can only choose two voices.  If you choose John Linville’s GMC format you can choose three voices for tones and the fourth only for the drum track.  If you selected Ed Snider’s CoCo PSG then you can choose from three voices for tones or use voice three as a drum track.  If you want to use voice 3 for drums then make sure click on the boxes with the number 4 and no boxes with the number 3.

Since we are limited to individual notes per voice there is one other thing to note about track selection.  During the MIDI conversion of chords the program always selects the highest note of the chord as the note to convert unless you select more then one voice for the same track.  The program works like this…  If you want to play notes of a chord from your MIDI file select voice 1 and 2 for the same track.  The program will then use voice 1 as the high note of the chord and voice 2 as the lowest note in the chord.  If you select voice 3 in the same track with voice 1 and voice 2 then voice 3 will play the 2nd highest note.

As for picking which tracks are played by which instrument you use the mouse and left click on the little box with the number of the voice you want to use for that track.  Use a right click to cancel the voice selection.  There are many songs that have many instruments but not all of the instruments are playing all the time.  For example the picture below is the GUI output for the file Axelf.mid using Simon’s dipole format which only allows you to choose two voices.

Screen Shot 2017-12-12 at 9.13.34 PM

You can see that only tracks 1 and tracks 2 are used throughout the entire song.  So you could select voice 1 for track 2 (slap Bass 2) and you can select voice 2 for track 3, track 4, track 5 and track 7 since none of these tracks play notes at the same time.  The instruments will all sound the same but at least you will get more of the original notes that are in the song and it’s usually good enough for background music for your game.

See the picture below with the little coloured boxes that indicated which voice I’ve selected for each track.  Sometimes the MIDI converter is unsure if a track is a drum track or not and will display “??? Instrument or Drums” it doesn’t display a box with the number 4 beside it but if you place your mouse pointer to where the box would be you can click on the imaginary box and it will turn white to indicate that the converter will use this voice as drums using the selected track.

Screen Shot 2017-12-12 at 9.20.04 PM

Once you’v selected your tracks, then press the Space Bar or Enter to start the conversion of the tracks and voices you’ve selected.

You will then be shown a little summary screen of what the program did during the conversion and will tell you a little bit more about the song.  It will tell you the length of the song and the size of the data that is needed to play the song.  It will also give you some information on how you can use the output format that you’ve selected.  Press any key at this point to close the mid2coco program.  Then you will either have to use the output in your own assembly program or if you are using Ed Snider’s CoCo PSG you can use it from BASIC, or in your own assembly language programs.  I’m not going to go into details here for using each format.  But if you play with the program and look at the output files it produces I’m sure you will understand how to use them for your own projects.

mid2cc_screenDone

CoCo PSG background music from BASIC

If you have Ed Snider’s CoCo PSG you can use option 5 to convert the MIDI file so it will play in the background of your BASIC program.  Then follow the instructions as described above to convert the MIDI file to a file called PSGLOADR.BIN.  All that is needed is to copy the file generated called “PSGLOADR.BIN” to the floppy disk or .dsk image if using CoCoSDC.  The PSGLOADR.BIN is a loader program that will copy the music data which is also in the PSGLOADR.BIN file and copy it to the RAM of the CoCo PSG.  So your music data won’t take any RAM from your CoCo.  The PSGPLY16.BIN or PSGPLY32.BIN programs which are the actual playback programs will require about 1150 bytes of RAM from BASIC and these programs need to be on your disk.  You actually need only the one program depending on the amount of RAM in your CoCo.  If you have 16k then you only need the PSGPLY16.BIN program on the floppy disk.  If you have 32k or more, even a CoCo 3 then you need to make sure the PSGPLY32.BIN program is on the floppy.  The last thing you need to do is add a few lines of BASIC code to your BASIC program.  The converter will let you know what these lines of BASIC code are depending on the amount of RAM the CoCo target system has.  The converter will also let you know the EXEC commands to start, stop and continue the music playback in your BASIC program.  The last thing it will let you know is the POKE address you use to set the number of times the music will repeat (default is continue looping forever).  All the programs required are included in the .dsk image and as stand alone files in the mid2coco.zip package.

Take a look at the program listing for the included programs PSGPLY16.BAS or PSGPLY32.BAS to see how to load and start the music.  It also shows the EXEC addresses to stop and continue playback.

Some other things to note about the conversion and using the music in your own programs.  The mid2coco converter takes velocity into account but Simon’s player always plays notes at the same volume level.  The other two formats support velocity and the program does output the notes and their volume level according to the info in the MIDI file.

Also note – Since the GMC and CoCo PSG are cartridges that produce sound the mixer inside the CoCo must be set to output sound from the cartridge port to the speaker on your TV.  Once the mixer is set as the cartridge as it’s input you can no longer use the CoCo DAC for sound effects.  You will have to use the sound chip on the cartridge for sound effects in your game.  Or temporarily turn off the cartridge mixer and select the CoCo DAC then switch back to the cartridge to play the music again.  If you are using the CoCo PSG from BASIC with my converted player and you get an error then the CoCo will set the audio mixer to the internal DAC even though the music will still be playing in the background and you wont hear it.  The easiest way to get the sound set back to the CoCo PSG is to EXECute the stop command then EXECute the Continue command (shown in the example PSGPLY16.BAS or PSGPLY32.BAS files).  Also note if you EXECute the start address twice it will crash the CoCo since the start EXEC actually sets up to intercept the BASIC IRQ routine and if you do it a second time it will intercept it’s own routine and that is bad.

Also a note about the GMC playback routine, the assembly code copies the playback routine from the cartridge to RAM at address $7000 as a default.  If you are going to use this code with a real game cartridge you should probably change this address to something that makes more sense for your program.

Have fun…

Glen

If you want to get a Game Master Cartridge reach out to John Linville here

If you want to get a CoCo PSG visit Ed Snider’s webpage here

CoCo PSG player format description

* 5 Byte header:
* Byte  Value
* 00-02 'PSG' - Header Identifier
* 03    $xx - File version # currently only supports a value of $01 for version 1.00
* 04    $xx - Number of times to loop this song where xx is:
*       $00 - Don't change the number of loops value
*       $01 to $FE - loop this number of times
*       $FF - loop forever
* All bytes at this point are data bytes that are encoded as per the info below.
*
* First the descriptor byte
*  Left nibble  = # of vsyncs/2 to count until next change in tone or velocity is done
*  $0x to $Fx   = 0 to 15 delay count before next note or velocity change, add one to get real value of 1 to 16
*
*  Right nibble = # of bytes to copy (1-11) count of bytes to copy max needed in current format is 3x3 = 9 bytes = (2 tone values, 1 velocity value for each of the 3 voices)
*  or if the value of the right nibble is higher then 11 or $0B then do the following
*  $x0          = 00 unused
*  $xC          = 12 signals the repeat count is larger then 16 so use the next byte as the repeat count (left nibble = bytes to copy)
*  $xD          = 13 signals the repeat count is larger then 256 so use the next 2 bytes as the repeat count (left nibble = bytes to copy)
*  $xE          = 14 Flip Channel C from tones to noise or drum track or back to tones
*  $xF          = 15 signals End of Music data
*
* Next process the data bytes
*
* My PSG playback format uses the following format for the data bytes
*
*          ,------------- 0=Note, 1=Volume or channel C Noise/Drum frequency
*          |      ,,----- Channel  00=chan A, 01=chan B, 10=chan C, 11=chan C - Drum/Noise info
*          |      ||
*          |Xxx xx||  x=volume or msb of 12 bit tone info or Xxxxx = 5 bit noise/drum frequency for channel C
*          1000 0001
* If it is a Note then it has the 4 msb of the 12 bit tone and the next byte has the 8 lsb's of the 12 bit tone value (so two bytes are always needed for tone data)
* Done, the next byte is the next encoded byte...

Game Master Cartridge Format Description

There is no header to the data stream since it will be played back from the cartridge directly.  The encoding for the music data is:

* Encoding byte
*                left nibble = # of times to repeat          0 to 15 repeat count
*
*                right nibble = # of bytes to copy (1-11)    count of bytes to copy
*                                                            12 signals the repeat count is larger then 15 so use the next byte as the repeat count     (left nibble = bytes to copy)
*                                                            13 signals the repeat count is larger then 255 so use the next 2 bytes as the repeat count (left nibble = bytes to copy)
*                                                            14 signals jump to the next Bank of the GMC (reached the 16k length of the current bank)   (ignore left nibble)
*                                                            15 signals End of File

 

Posted in CoCo Programming | 1 Comment

How to setup and use IRQs on the TRS-80 Color Computer – Part 5 – Advanced interrupt settings and using CoCo 3 specific interrupts

Table of Contents (click on a link to jump to that web page)

In this section I will be going over some pretty advanced techniques to speed up your interrupt request routine so it has minimal effect on the rest of your program.

First trick is to setup an FIRQ that is in Direct Page space.  This will save a couple CPU Cycles every time the FIRQ is triggered.

Example:

The DP is set to $3E and the FIRQ routine starts in RAM at address $3ECA

 LDA    #$0E  * Write the direct page JMP instruction
 LDB    #$CA  * Will jump to address DP + $CA = $3ECA in our example
 STD    $010F * CoCo 1 & 2 FIRQ Jump pointer

Simon Jonassen told me about trick that you can use with the jump location in a CoCo 1 & 2.  You can use the  FIRQ jump Vector location as the actual interrupt routine so there is no jump required the code is executed at the FIRQ vector.  To use this you would just put your entire FIRQ routine starting at $010F.  That way you save the few extra cycles that would normally be used with the JMP $xxxx instruction.  If your program doesn’t use the FIRQ you can do the same thing with the IRQ but your interrupt routine would start at $010c.  – Thanks Simon


I’m going to show you some very optimized 6809 code that will be used for a CoCo 3 only audio sample player.  This code is not CoCo 1 or 2 compatible.

In this example the audio data has been loaded in RAM starting at address $3D59 and ending at address $7FFF and this code will playback the sample looping it over and over.

To minimize the CPU cycles this interrupt routine uses some self modifying code.

        ORG     $C000           * Address of the Direct Page and FIRQ
DirectPage:
        SETDP   DirectPage/256  * Setup the DP addressing for the assembler
*****************************************
* Play Sample in the background in mem $3D59-$7FFF, Loop it
Sample1Start:
        FDB     $3D59            * location where sample starts counting down from, used for looping
FIRQ_Interrupt1:
        STA     FIRQRestoreA+1   * Save A before we exit the routine (self modifying code)
        LDA     $FF93            * Re enable the FIRQ
LoadAudio1:
        LDA     $3D59            * This value gets changed with some self modifying code below
        STA     $FF20            * OUTPUT sound to DAC
        INC     LoadAudio1+2     * Increment the LSB of Sample pointer
        BNE     >                * check if we hit 00, if not exit
        INC     LoadAudio1+1     * Increment the MSB of Sample pointer
        BPL     >                * If positive then we are good still under $8000 otherwise (end of sample, reset pointer)
Hit8000:                         * Restore the pointer to the start location of the sample
        LDA     Sample1Start     * Point to the MSB of the sample Start location
        STA     LoadAudio1+1     * Store the MSB of Sample pointer
        LDA     Sample1Start+1   * Point to the LSB of the sample Start location
        STA     LoadAudio1+2     * Store the LSB of Sample pointer
        
FIRQRestoreA:
!       LDA     #$00             * STA at the start of the FIRQ stores A's value here and gets loaded before the RTI saves a cycle and a byte of RAM
        RTI                      * Return from the FIRQ

The program starts here and sets up the hardware on the CoCo 3 to use the GIME chip’s interrupts.  This is different from the previous methods shown in this series of posts.

START
***********************************************************
        ORCC    #$50            * Disable interrupts
        CLR     $FFD9           * High Speed mode enabled

        SETDP   DirectPage/256  * Set the direct Page so the assembler will use Direct Page addressing when assembling
        LDA     #DirectPage/256 * Set the Direct Page value
        TFR     A,DP            * to where our FIRQ is located

        LDA     #%00110100      * Setup the CoCo 3's hardware
        STA     $FF01           * HSYNC IRQ Disabled, IRQ Polarity Flag falling Edge, Data Direction Normal, Select Line LSB = 0, HSYNC Flag = 0
        STA     $FF03           * VSYNC IRQ Disabled, IRQ Polarity Flag falling Edge, Data Direction Normal, Select Line MSB = 0, VSYNC Flag = 0
        STA     $FF21           * CONTROL OF CD FIRQ* TO CPU DISABLED, IRQ Polarity Falling Edge of CD, CD Flag off
        STA     $FF23           * CONTROL OF Cart FIRQ* TO CPU DISABLED, IRQ Polarity Falling Edge of Cart, Cart Flag off
        LDA     #%01111100      *
        STA     $FF90           * CoCo 3 Mode, MMU Enabled, GIME IRQ Enabled, GIME FIRQ Enabled, Vector RAM at FEXX enabled, Standard SCS Normal, ROM Map 16k Int, 16k Ext
        LDA     #%00100000      *
        STA     $FF91           * Mem Type 64k chips, 279.365 nsec timer, MMU Task 0 - $FFA0-$FFA7
        LDA     #%10000000      *
        STA     $FF98           * Graphics mode, Colour output, 60 hz, max vertical res

* Setup the Timer FIRQ
        LDA     #$0E            * Write the JMP instruction to a direct page JMP location
        LDB     #FIRQ_Interrupt1-DirectPage  * B now is the address of the FIRQ routine
        STD     $FEF4           * Save it to the CoCo 3 FIRQ vector address 
        LDD     #$0280          *
        STD     $FF94           * Set countdown Timer to $0280 - This is the speed the samples will playback at
        LDA     #%00100000      * $20
        STA     $FF93           * Enable TIMER FIRQ Interrupt

        ANDCC   #$AF            * = %10101111 this will Enable the IRQ and the FIRQ to start

* Your program can go here, for now it just loops forever as the sample plays in the background
!
        BRA    <
        END    START            * Tell the assembler when creating an DECB ML program to set the 'EXEC' address to wherever the label START is in RAM (above)

I hope you are now an interrupt expert and use them in your next awesome game…  🙂

Posted in CoCo Programming | 2 Comments