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 | 1 Comment

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 , , , , | 3 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