Screen full of garbage: random screen location in assembler

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.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.