OK. Time to move on. In previous post I introduced few issues that one has to take into account when programming in Commodore 64 assembler and introduced the assembler version of that lame “starfield” routine. Which can be found here. It has “.doc” suffix because of WordPress file filters, but it is actually a plain ASCII file. In this post I will introduce the main routine as well as the routine to get the random screen location where to put the character.
The main routine
MAIN
SEI
JSR RDINIT ;init rnd number
WAIT
LDA RASTER ;check for raster line
CMP #$80
BNE WAIT ;wait if not #$80
JSR RNDBYT ;get rnd number
AND #$03 ;scale it to range 0-3
JSR TRANSFER1
LDA $DC01 ;LOAD DATA PORT B / KEYBOARD
CMP #$EF ;SPACE
BNE WAIT
CLI
RTS
BRK
The main routine starts with SEI operation that will turn off the system interrupts (try to comment it out and see what happens) and then it will initialize the random number generator routine. Next we will check the raster line, that is, on which screen line the computer is drawing at the moment. We use this to slow down out routine to happen “only” 50 times a second.
Then we get a random number (0-255) and “AND” it with 3 that will zero all the other bits of the random number except the lowest two bits (giving us the range of 0-3). Finally we call the routine to select the random screen location.
Getting the random screen location
By now we have a routine for 8-bit random numbers (values 0-255), but the screen has 1024 locations starting with memory location 1024 ($0400) and ending in location 2047 ($07FF). So I split the screen into four 256 byte chunks and stored the start addresses to memory:
SCRMEM1 .byte $00, $04, $FF, $04, $FE, $05, $FF, $06
Note that the address bytes are wrapped around so $0400 becomes $00, $04. You can actually change the screen memory location, but we’ll look at that later on.
TRANSFER1
CLC
ROL ; get correct screen memory location
TAY
LDA SCRMEM1,Y ;first half of screen address
STA $BB
INY
LDA SCRMEM1,Y ; second half of screen address
STA $BC
JSR TAILPART
RTS
So the accumulator contains the previous random number (0-3) fetched in the WAIT routine. We clear the carry flag and rotate the number left one bit (I later realized that using the the normal shift operation, ASL). Now we have a even number between 0 and 6 inclusive. We use this value to select the proper chunk of 255 bits of screen memory.
First, we store that value to the Y register so that we can use it to access memory location and then we get the first (low!) byte of the screen address and place it in zero page to location $BB. Then we increase the Y value and get the next byte (the high byte of the memory location) and place it in $BC. Now we have the starting address of one of four screen location chunks in the $BB-$BC memory location. Next we call the “TAILPART” routine.
Select and print out a character in given location
TAILPART ; check and print the character
JSR RNDBYT
TAY
LDA ($BB),Y ; load curren character at $BB+1
CMP #$51 ; if it is ball
BEQ STEP2
CMP #$57 ; if it is donut
BEQ STEP0
CMP #$2A ; if it is asterisk
BEQ STEP1
LDA #$2A ; else
DRAW
STA ($BB),Y ; print character
RTS
STEP0
LDA #$20 ; space
JMP DRAW
STEP1
LDA #$51 ; ball
JMP DRAW
STEP2
LDA #$57 ; donut
JMP DRAW
First we get yet another random number. This one defines the actual screen location which we use to store our character, but before that we will read the contents (character) of the same memory location:
- If the character is ball we will replace it with donut.
- If it is donut we will replace it with a space
- If it is asterisk we will replace it with ball
- Otherwise we will insert asterisk in the screen location.
And then in the DRAW routine we will put the selected character to the selected screen location (we take the address stored in address $BB-$BC, add Y to it and store the accumulator in that memory location).
Finally we return (RTS) back to the TRANSFER1 routine and again return back to the WAIT routine where we will check if space key has been pressed. If not, we do the thing all over again. If space has been pressed we will enable interrupts and exit our program.
That’s about it. Next time we will add some colors to this routine.
Filed under: Commodore64