Zilog z80 to Motorola 6809 Transcode – Part 017 – Ready Player 1

Just a little update on my progress.  Things are looking pretty good.  I now have all the main game routines coded and I’ve added the buttons to insert a coin, select 1 or 2 player game and control Pac Man using the arrow keys.

screen-shot-2017-02-19-at-11-49-27-pm

There are tons of things I still have to fix, but it is quite playable except it’s slow compared to the real Pac Man.  I’m still hopeful that optimizing it will get it running at the proper speed.

Screen Shot 2017-02-19 at 11.50.15 PM.png

I still have to code in the cutscenes, but you can play it until the 2nd level is done and the first cutscene starts.

This is what I have to do at this point:

  • If you get to 10,000 points you should get a free man, currently it resets the score to 0 and no free man
  • Two player game high score didn’t get set properly, player 1 had high score but when player 2 was playing with a lower score it was still being copied to the high score
  • Fix Pac man death animation (need to copy from original sprite data)
  • Fix autoscrolling, currently broken if the ghosts are Dark Blue, it seems to follow the red ghost
  • Add the rest of the game code
  • fix sprites are wrecking the 1 player 2 player start message screen
  • Text in the middle of the screen is not erased when game starts
  • Maze gets erased beside where “game over” is written (sprites, problem)
  • When you eat the fruit the score shows up but part of the fruit is still shown until the score disappears
  • Credits jumps to 99 after starting a game
  • Credits not going down after playing a game
  • Test if keyboard scanning routine could be improved by swapping the STA and LDA bytes this would allows for only one STA for all the buttons along the same line

Of course I have to speed it up and sound would be cool too…

 

Posted in Uncategorized | Leave a comment

Zilog z80 to Motorola 6809 Transcode – Part 016 – Attract modes are done

Just a little update to say that I’ve made some great progress on the Pac Man code, it runs through both game attract modes properly and loops endlessly, looking for someone to put a quarter in the machine.

I found the random logic Pac Man uses actually points to the ROM hardware for part of the routine so I had to do the same in order to make the ghost movement match the original 100%.  The attract mode now matches real Pac Man and if someone know some patterns for Pac Man they should work on the CoCo 3 version exactly the same.

Getting the Maze demo working meant adding a lot of the ghost logic and once I add the controls in it shouldn’t be too much to actually get it to the point where I can play a level on the CoCo 3.

screen-shot-2017-02-17-at-8-50-16-pm

See you in the next post…

Posted in CoCo Programming | Leave a comment

CoCo 3 Loader for big programs

While working on the Pac Man transcode I was feeling a little cramped for space since the CoCo 3 has 64k of addressable space for the 6809 but loading a program that wont fit in memory between $E00 to $7FFF is difficult because the CoCo 3 uses some calls from the Disk Basic and Extended Basic while loading and if your program is too big it will over write the Extended Basic and Disk Basic routines and will lock up the computer.

There is some great info on William Astle’s page specifically his pdf on different ways to load programs into the CoCo.  I used this info and most of his two stage loader programs to make a generic loader that you can simply add to the beginning of your program and no longer worry about loading a huge file onto the CoCo3.  It as simple as assemble your program as usual, use the cat command to join the bigloader and your program into a new program and use that new program on the CoCo3.  Easy…

The technique is a little hard to wrap your head around but here goes…  The first program is the main loader it is a small program loaded into RAM at $2000 and while it’s loaded it also overwrites the end of the close routine to make it run itself instead of writing OK on the screen.  So once the program is loaded it auto starts and it copies all the data within it’s own large file into memory pages 0 to 7 (or more if you use the tricks mentioned below).  The first bit of code that is loaded is actually a secondary program.  Since it was loaded in RAM page 0 we know exactly where it is and when we finish copying all of our big program to RAM pages 0 to 7 we then make Block 6 use page 0 and execute the code which is now in RAM at $C000.  This code then copies the rest of itself to address $FD00 and then executes it from there.  This second program goes uses block 6 which is $C000-$DFFF as the place to read your program in from.  While it loads the program it handles all the ORG statements from your assembly language program and all the loading locations and even handles code that would write to RAM $C000-$DFFF so that when the loading is done your code will be exactly where it should be.  Your program will be autoexecuted after it’s loaded.

The loader allows you to use memory from $0000 to $FCFF for your program, that’s 64768 bytes!  Since it handles ORG statements you could actually use other pages in the CoCo3’s RAM to load even more data from your program.  For example if you wanted to load some picture data into RAM pages $23-$25:

    ORG  $FFA0
    FCB  $23
    ORG  $FFA1
    FCB  $24
    ORG  $FFA2
    FCB  $25
     ORG $0000
 Your data for graphics or whatever from $0000 to $5FFF go here

Just remember to put the pages back to normal before your code is written to those memory Blocks, unless you are doing something fancy…

    ORG  $FFA0
    FCB  $38
    ORG  $FFA1
    FCB  $39
    ORG  $FFA2
    FCB  $3A

Also keep in mind that the loader uses blocks 5 & 6 so don’t use them if you are doing special loads like the above example.

Other things to keep in mind:

-This over writes Extended Basic, Color Basic, Disk Basic and Super Extended Basic so your program will not be able to use these ROMS once it’s loaded.

-The loader uses high speed mode after loading from disk/tape (yeah it should work with a 64k tape based program too) so your program will be executed in high speed mode.

-The Stack is set to $FE00 which is probably the best place for it, since you can’t use $FD00 to $FDFF for your code because the actual loader uses this space.  The  RAM at $FD00 to FDFF is usable after your program is loaded if you want or it can become a nice space for the stack if left alone.

-RAM used for your code must be between $0000 and $FCFF, if it is bigger the $FCFF it will overwrite the loader code, there is no checking for this in the loader program.

To use the loader you simply copy the BigLoader to the start of your program using a binary copy tool.  First assemble your huge program for example we call it myprogram.bin.  With OSX and Linux use (cygwin under windows or a similar program) the cat command as follows:

cat bigloader.bin myprogram.bin > bigprogram.bin

This simply adds the loader to the start of your program.  Under RSDOS all you need is load the new bigprogram.bin since it now contains the loader and your program code.

Below is the source code for the loader programs if you modify the code for Part 2 it will change the position of where it thinks your program is and you will need to adjust it accordingly also it must be created as a RAW file not a regular CoCo binary.

You can download the program ready to use from here

Now I have some more room I can get back to Pac Man…

Part1:

        ORG     $2000
LOADER  LDD     #$176   ; restore close routine to be polite
        STD     $A42E
        CLRB            ; initialize block counter
LOADER1 STB     $FFA2   ; set MMU
        LDX     #$4000  ; init load pointer
LOADER2 JSR     $A176   ; get byte from file
        TST     <$70    ; EOF?
        BNE     LOADER3 ; branch if so
        STA     ,X+     ; save byte in memory
        CMPX    #$6000  ; end of MMU block?
        BLO     LOADER2 ; continue if not
        INCB            ; next MMU block
        BRA     LOADER1 ; set MMU and continue loading
LOADER3 JSR     $A42D   ; close file to be polite
        LDA     #$3A    ; Put BLK 2 back to default
        STA     $FFA2   ; page of $3A
        ORCC    #$50    ; disable interrupts to prevent crash
        CLR     $FFA6   ; stage two which decodes the loaded program will run from $C000
                        ; set CPU memory block 5 to physical memory 0
        STA     $FFD9   ; go to turbo mode
        JMP     $C000   ; transfer control to payload (stage two)
; this installs the close trap
        ORG     $A42E
        FDB     LOADER
; "LOADER" not really required
        END     LOADER

Part 2:

        ORG     $C000
        LDX     #Pointer
        LDY     #$FD00
!       LDD     ,X++
        STD     ,Y++
        CMPY    #$FE00
        BNE     <
        JMP     $FD00
Pointer:
        ORG     $FD00
LOADER  LDX     #$C0EB ; point to start of payload in logical block 6
        CLRA                    ; initialize block counter
        STA     $FFA6           ; initialize MMU point to $C000 where we will decode from
        LDS     #$FE00          ; Stack location
LOADER0 BSR     GETBYTE         ; fetch block flag
        TSTB
        BNE     LOADER2         ; branch if postamble
        BSR     GETBYTE         ; fetch block length
        STB     TWORD
        BSR     GETBYTE
        STB     TWORD+1
        LDY     TWORD           ; fetch block count
        BSR     GETBYTE         ; fetch load address
        STB     TWORD2
        BSR     GETBYTE
        STB     TWORD2+1
        LDU     TWORD2          ; fetch destination address
        CMPU    #$E000
        BHS     LOADER1         ; If new block is going to load at or above $E000 then load as normal it wont effect $C000-$DFFF 
        PSHS    D
        LDD     TWORD
        ADDD    TWORD2          ; end location in RAM
        CMPD    #$C000
        BHS     LoadHi          ; if writing to mem is going to hit our block then handle it
        PULS    D
LOADER1 BSR     GETBYTE         ; read a byte to its destination
Loader1b:
        STB     ,U+
        LEAY    -1,Y            ; finished block?
        BNE     LOADER1         ; continue if not
        BRA     LOADER0         ; handle next block
LOADER2 BSR     GETBYTE         ; ignore two bytes
        BSR     GETBYTE
        BSR     GETBYTE         ; fetch execute address
        STB     TWORD
        BSR     GETBYTE
        STB     TWORD+1
        LDB     #$3E
        STB     $FFA6           ; Put $C000 back to normal it could have code in it now
        JMP     [TWORD]         ; transfer control to main program
GETBYTE LDB     ,X+             ; fetch byte
        CMPX    #$E000          ; end of block?
        BEQ     >
        RTS
!                               ; return if not
        LDX     #$C000          ; reset pointer to start of block
        INCA                    ; bump block number
        STA     $FFA6           ; set MMU
        RTS                     ; return
LoadHi:
        CLR     FlagBigE
        CMPD    #$E000
        PULS    D
        BLO     >               ; If it is going to hit $E000 then we have to check when we hit it
        INC     FlagBigE
                                ; Other wise we will be good copying the rest of this block
!       BSR     GETBYTE         ; read a byte to its destination
        CMPU    #$C000
        BHS     LoadOther
        STB     ,U+
        LEAY    -1,Y            ; finished block?
        BNE     <               ; continue if not
        LBRA     LOADER0         ; handle next block
* Swap writing blocks and pointer from $C000 to $DFFF range to $A000 to $BFFF
* when done then swap them back
LoadOther:
!       PSHS    B
        LDB     #$3E
        STB     $FFA5 ; set block 5 to block 4 position
        PULS    B
        LEAU    -$2000,U
        TST     FlagBigE
        BNE     Continue1 ; Go handle blocks that end at or over $E000
        BRA     Continue0
!       BSR     GETBYTE         ; read a byte to its destination
Continue0:
        STB     ,U+
        LEAY    -1,Y            ; finished block?
        BNE     <               ; continue if not
        LDB     #$3D            ; Put block 5 back to normal
        STB     $FFA5           ; page $3D
        LBRA    LOADER0         ; handle next block
* Swap writing blocks and pointer from $C000 to $DFFF range to $A000 to $BFFF
* when we reach $C000 (really $E000) then swap them back and jump back to normal routine above
OverE000:
!       BSR     GETBYTE         ; read a byte to its destination
        CMPU    #$C000
        BEQ     >
Continue1:
        STB     ,U+
        LEAY    -1,Y            ; finished block?
        BNE     <               ; continue if not
!       PSHS    B
        LDB     #$3D            ; Put block 5 back to normal
        STB     $FFA5           ; page $3D
        PULS    B
        LDU     #$E000
        LBRA    Loader1b        ; continue as per normal now...
FlagBigE:
        FCB     0
TWORD: ; scratch locations
        FDB     0               
TWORD2:
        FDB     0
; read byte from A,X and bump pointer
PAYLOAD EQU     *               ; payload starts here
Posted in CoCo Programming, Uncategorized | Leave a comment

Zilog z80 to Motorola 6809 Transcode – Part 015 – Sprites on the Demo Maze

Not much to report, just adding more routines… I got as far in the attract mode as the first scene finished (where Pac man eats the power pill and the Dark Blue ghosts) then the maze is drawn and Pac man goes to the left, but Pac Man and the ghosts go through some of the walls…  I think the PaletteRAM is where the game checks for walls and they aren’t being setup properly  or detected properly.  But at least there is some progress to see on the screen…

screen-shot-2017-02-05-at-2-54-27-pm

See you in the next post…

Posted in Uncategorized | 5 Comments

Zilog z80 to Motorola 6809 Transcode – Part 014 – MAME -debug and how fast is the code

Hi All, I thought I’d talk a little bit about one of the most powerful tools to use while transcoding, and that tool is MAME.  Specifically MAME using the -debug feature.  With the debug feature turned on you can do all kinds of great things with the emulated system.  It is a great tool to use to compare how the original system is running and compare your transcoded version is running down to the same location in code.  At the same time you can see the register values, the program counter, stack, accumulators.  You can also pull up memory view windows to see blocks of memory in real time or stop the process and step through the code one instruction at a time.  Another great feature is MAME will show you the beamx and beamy values and the frame # all having to do with the video rendering.  The beamx is the horizontal position and the beamy is the vertical line that is being drawn and the frame is the count of the number of frames that have been displayed since the emulation has started.  All this and you can set up break points for where in memory you would like the program to stop.  You can also setup watch points, that tell MAME to watch certain areas of RAM and when it is read or written or both to break and let you know where in the code execution it was when the read or write occurred.

I finally got my Pac Man code running to the point where the attract screen animation is happening and I thought it looked pretty good then I ran it beside the real Pac Man and noticed it looked the same but my code was running way slower then the original.  So I decided to investigate where the slowness of my code was coming from and this is where MAME -debug comes in handy big time!

You start MAME off in debug mode using the -debug option from the command line for example:

mame -window -natural -nojoy -debug coco3 -flop1 Disk1.dsk

Once MAME starts I’ll set a break point from it’s debugger’s command line with the command:

bp XXXX

Where XXXX is the hex address in RAM where I want the execution to stop.  So I looked through the output listing of lwasm which gives me all the code and the addresses, so I know exact where I need to stop the code to examine how long some code is taking to run.  For example I know my sprite routines currently start at 260A in memory and end at 27B5

So I would set two break points in MAMEs command line (use the help command to see all kinds of help with the other instructions MAME debug has):

bp 260A
bp 27B5

then press F5 to run the code and when it gets to address 260A MAME will stop and give you the command prompt again.  At this point you can record the beamy and frame #.  Then press F5 again and it will go through the sprite code and stop at address 27B5.  Now you can record the new beamy and frame #

What can you do with the beamy and frame #?  Well if you know how fast the CPU is you can use this information to see how many cycles have past between the first break point and the second break point.

It works like this for the CoCo3 in high speed mode.  The 6809 is running at 1.78 Mhz or 1,780,000 cycles per second.  So we take that number and divide it by 60 which is the number of screen updates per second or frames per second.  This gives us 29,666 cycles per frame.  MAME displays the coco 3 with 240 lines of resolution so we can divide 29,666 bye 240 to get the number of cycles the 6809 can do per line.  This turns out to be 124 cycles per line.

So now we take the end beamy value and divide it by 240 then multiply it by 29,666 and add it to the frame #.  We do the same with the start beamy and frame # and subtract the result from the end value and blamo we have the number of cycles that were used between the break points.  This will be very useful for testing the code to see which parts are taking the most CPU cycles and require the most optimization.  I’ve done a lot of this testing today with my current code and the numbers don’t look too good so far.  I’m running nearly 1/4 the speed of the original Pac Man 😦

I’ve reached out to the CoCo community on the CoCoList for Color Computer Enthusiasts and they have been super helpful and have already offered to help me optimize the 6809 code.  They are a great bunch of guys and I’m sure I’ll need their help in the future.  They have encouraged me to keep working on the code and they assured me that with lots more work I should be able to get the the 6809 version of Pac Man to run as fast as the real Pac Man!

I hope they’re right,  see you in the next post…

Posted in CoCo Programming | 2 Comments

Zilog z80 to Motorola 6809 Transcode – Part 013 – Sprites and more RAM!

First I have to give a big thanks to Mark McDougall who explained to me that I don’t have to have the video ram in the main 64k of addressable space the CoCo3 uses!  I should have realized this myself since working on the scrolling routines many times my code would scroll past the screen and view other RAM on the screen.  Also Super Disk Extended Basic uses a different memory block for it’s HIRES screens.  But it wouldn’t have come to me without someone like Mark telling me.  This frees up a good $5000 bytes of RAM which will hopefully allow me to add sound to the game which I really need to learn to do.  🙂

I now setup the videoRAM in the 512k CoCo3 memory banks 0-4 and a backup videoRAM area at $10-$14.  This allows me to stop (most) of the flickering when rendering Pac man and the ghosts.  For now it simply saves the background of the sprite from the backup videoRAM area, then draws the sprite on the real VideoRAM area.  After the next VBLANK it restores the sprite location with the saved background and starts again.  This will make the sprites flicker when they cross paths since it doesn’t handle the sprites on top of each other but it’s faster then double buffering and it will do for now.

I will move on from the sprite stuff and get back to transcoding.  There is still a little glitch in the speed of the ghosts in the attract animation which I still have to figure out.  Then I’ll move on to the demo screen showing the maze and the game in action.  But that requires a lot more transcoding…  I can work on fixing the video glitches as I go.

Here’s a picture of the first attract mode

screen-shot-2017-01-31-at-9-27-38-pm

I wanted to talk a little bit more about the sprite engine I wrote.  It is very optimized now…

This is used for copying the background before the sprite is drawn and also for restoring the background.

Instead of using LOAD and STORE instructions copying data from the background to a temporary buffer the stack is used to PULL the memory to the registers and PUSH them into a temporary location.  Since there is no LOAD instructions or STORE instructions this is done very fast.  All that is needed is to point the U stack to a storage buffer memory location and point the S stack register to the row in memory that needs to backed up and give it a PULS A,B,X,Y and PSHU A,B,X,Y then move the S pointer to the next line and so on.  When it’s done the data in the storage buffer can be used in reverse, it can be PULLED from the stack and stored back into video RAM as quickly as possible on the next restore routine.  See the sample code below, it includes the new memory swapping I had to add since I moved the videoRAM blocks around.  So it is basically BackupSprite, DrawSprite (not shown below) then next VBLANK RestoreSprite and repeat.

*************************************************************
* BackupSprite:
* Backup the data behind where the Sprite will be placed from the backup VideoRAM Map
* A = Horiztonal (X) pixel location (0 to 239 (255 - 16 "sprite size"))  0 is the left, 255 is the right
* B = Vertical (Y) pixel location (0 to 271 (287 - 16 "sprite size"))  0 is the top, 287 is the bottom
* U = Pointer to the Sprite Location & Stack storage location
*************************************************************
* -5,U = Destination in Video RAM
* -3,U = Even Flag
* -2,U = X & Y
***********************************
BackupSprite:
 * Should only be called during the IRQ so no need to do an ORCC #$50
        PSHS    U
        CLR     -3,U               * Clr Even Flag for this sprite
 STD -2,U * Store the X & Y values so it can be checked for collisions with other sprites
        BITA    #1
        BEQ     >
        INC     -3,U             * Even # so set Even flag to 1
!       RORA                            * A divided by 2 (screen X is 128 Bytes across from the X 256 pixel value)
        LDX     #Screen_Start
        LEAX    A,X
        LDA     #128                    * 128 bytes per row this moves us down in the Y direction
        MUL
        LEAX    D,X                     * X = Destination location in Video RAM, save and use again for drawing the sprite
        STX     -5,U                    * Save the Destination in Video RAM associated with this sprite so it can be automatically restored in the restore sprite routine
        STS     S_Temp                  * Save the stack so we can restore it once done
        LEAU     145,U                  * Backup to the temp stack storage then organize it to optimize restore time
                                        * Move U to point to the the end of the Sprite Stack space +1 (PSHS to stack skips the current byte and counts down)
        TFR     X,D                     * Calculate which two memory blocks to get for the backup data (from the backup VideoRAM)
        CLRB                            * Clear the Carry flag
        ANDA    #$E0
        RORA                            * Shift A to the right 5 times to get the block that will hold the backup background
        RORA
        RORA
        RORA
        RORA
        ADDA    #$10                    * Backup VideoRAM is between $10 to $14
        STA     MMU_Reg_5               * $10 to $14
        INCA
        STA     MMU_Reg_6               * $11 to $15
        TFR     X,D
        ANDA    #$1F
        ADDD    #$A000
        TFR     D,S
        PULS    A,B,X,Y     * Start copying the area behind where the sprite will be from the top left corner
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LEAS    119,S
        PULS    A,B,X,Y
        PSHU    A,B,X,Y
        PULS    A,X
        PSHU    A,X
        LDS     S_Temp
        PULS    U,PC
*************************************************************
* RestoreSprite
* Restore a 16 Bit sprite
* Not needed X - From stored location = Horiztonal pixel location (0 to 239 (255 - 16 "sprite size"))  0 is the left, 255 is the right
* Not Needed Y - From stored location = Vertical pixel location (0 to 271 (287 - 16 "sprite size"))  0 is the top, 287 is the bottom
* U = Pointer to the Sprite storage stack location with Data to be restored
*************************************************************
RestoreSprite:
        PSHS    U
        LDX     -5,U            * X Now points to the top left location where to restore Video RAM
        STS     S_Temp          * Save the Stack
        TFR     U,S
        TFR     X,D             * Calculate which two memory blocks to get to restore the backup data to the real VideoRAM
        CLRB                    * Clear the Carry flag
        ANDA    #$E0
        RORA                    * Shift A to the right 5 times to get the block that will hold our character
        RORA
        RORA
        RORA
        RORA
        STA     MMU_Reg_5       * 0 to 4
        INCA
        STA     MMU_Reg_6       * 1 to 5
        TFR     X,D
        ANDA    #$1F
        ADDD    #$A000
        TFR     D,X
        LEAU    2048-128+9,X    * Move U to the bottom right corner of our Sprite restore location
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LEAU    -119,U
        PULS    A,X
        PSHU    A,X
        PULS    A,B,X,Y         * PULS A,B,X,Y
        PSHU    A,B,X,Y         * PSHU A,B,X,Y
        LDS     S_Temp
        PULS    U,PC
Posted in CoCo Programming | Leave a comment

Zilog z80 to Motorola 6809 Transcode – Part 012 – Pacman is in the building and handling the z80 RLCA instruction

I’ve started implementing sprites and I’ve got the red ghost animating and Pac man moon walking a little across the screen.  You can’t see it from the picture below but you can see that I finally have Pac Man on screen!!!

screen-shot-2017-01-23-at-8-21-05-pm

Pac Man is a little lower then the Red Ghost which I’ll have to figure out.  I’m still missing tons of code to transcode but I think once I can get this little animated scene working then a lot of the game will actually be complete.

I’m running out of memory again!  The big scrolling screen really does take a lot of RAM away from the 64k available memory the CoCo3 can use at one time.  I thought I’d be able to keep the sprites in main memory at all times but that is not going to be an option.  The sprites take 8k of space that I can’t spare anymore.  I don’t know if I’m going to have room for adding audio!  Which is one thing I wanted to do since I haven’t worked on sound in assembly on the CoCo before and that would be a great thing to learn.  We’ll see…

 

Edit – (better way to do this is described at the bottom below this section) – Another bit on transcoding (pardon the pun)…  The z80 RLCA and RRCA are 7 bit rotate instructions that rotate the accumulator or memory location.  If you rotate left then bit 7 goes to bit 0 and if you rotate right then bit 0 goes to bit 7.  The 6809 doesn’t have this function so to get around this I use the following code:

        ANDCC   #$FE
        BITA    #$80
        BEQ     >
        ORCC    #$01   * Set Carry Bit
!       ROLA                           ;0231 07          RLCA

First it clears the C – Carry flag, then checks to see if bit 7 is clear, if it is then it does a normal ROL, but if bit 7 is set then it sets the C – Carry flag which will be copied into bit 0.

I figured out a faster way to do the 7 bit shift using the LSL and BCC instructions as shown below:

        LSLA
        BCC     >
        ORA     #$01                   ;0231 07          RLCA
!

Johann Klasek commented below with a way to save another byte in the code above by using INCA instead of ORA  #$01.  as per the code below,  Thanks Johann   🙂

        LSLA
        BCC     >
        INCA                           ;0231 07          RLCA
!

and for RRCA: 

        LSRA
        BCC     >
        ORA     #$80                   ;0307 0F          RRCA
!

See you in the next post…

Posted in CoCo Programming | 12 Comments