(Article by Phaze101)
Clearing the Screen
Why clearing the screen, is important?
During a game clearing the screen can happen several times. Clearing the screen is time consuming. If this is happening several times during your game, it becomes an important factor which means you will need a fast routine.
There are different methods of doing this. Some I agree with and some I do not like at all. Also, there are times when a fast routine is not necessary. It always depends where the routine is in the game.
As I have stated this many times now, I would like to remind you all that I never wrote games as a professional, so the optimised, fast routines won’t be found here, although I try to cover some of this. Having said that this series of articles is aimed at beginners hence trying to understand concepts is more important in these cases.
Method One – Using the Kernal
In terms of code this is the easiest method of clearing the screen. It is also the slowest method of clearing the screen. Although it is the slowest method to clear the screen there is use for it more than one thinks. An example of this is when you are on the main screen of the game and select to go to the instructions screen. It doesn’t need to be a fast routine to clear the screen and display the instructions.
This method is using the Kernal. The Kernal is a block of code that has several routines in it to handle different things.
As defined on the C64 Wiki
“The Kernal was the set of low-level hardware interfaces repeated throughout Commodore’s 8-bit computer series, beginning with the Commodore PET
The Kernal consisted of thirty-nine (39) functions ranging from Input / Output control to file management, memory management, console management and time management. These functions formed the basis for higher level routines in the BASIC ROM like LOAD, SAVE, INPUT and PRINT.
Kernal functions are accessible via a jump-table at the end of addressable memory (\$FF81-\$FFF3). The Kernal ROM occupied the last 8KB of address space in Commodore 8-bit computers (\$E000-\$FFFF).”
Here is a link to the C64 Wiki Kernal Page
The routine I am going to use is not part of the Kernal standard routines that are listed in the table, but it is build inside this chunk of 8K Kernal code.
The routine to clear the screen is at \$E544. All one needs to do to clear the screen is to call it using the Jump to Subroutine instruction hence JSR \$E544.
Here is a listing of the code.
Remember to type SYS 49152 in the emulator and to press the spacebar to exit and get the Ready Prompt 😊
Here is a screen capture. As you can see not much on the screen or not much that you can really see.
Method Two – Our Own Version
So instead of using the system routines now it is time to write our own.
For those that do not know the Commodore 64 Screen memory location starts at address 1024 or \$0400. The screen is made up of 25 rows with 40 characters in each row. This means that if we do 25 x 40, we get 1000. That means the screen can hold 1000 characters. So, screen memory is from 1024 (\$0400) to 2023(\$07E7) . A space character is screen code 32 or \$20. So, if we had to poke in each of these 1000 memory locations the screen code 32, we would effectively be clearing the screen.
This is what we do in this method. Here is the main listing of the code.
Lines 43 to 45
These should be familiar. We are writing a 0 which is black to the background and border registers. These were included as revision of article 6 😊
Lines 47 and 48
We are initialising the accumulator with \$20 or 32 hence a space. Also, we are setting the X register to zero.
We are labelling the start of our loop. We could have written lines 49 and 50 as
Loop STA \$0400,X
I just prefer the label to be on its own.
Line 50 to 54
So, what we are doing in lines 50 to 54. We are basically storing the value of the accumulator which is 32 to the memory location using absolute index addressing.
So, if we take in context only line 50, we are storing the accumulator value into memory location \$0400 + X. Since X is zero (line 48) the first time through the loop it will be at \$0400. X will change later in the program. If say now it is 1, we will be storing the accumulator value of 32 which is a space to memory location \$0400 + X where X is a 1 so at memory location is \$0401.
The same happens in the following lines 51 to 54 at memory locations \$04c8, \$0590, \$0658, \$0720. Why at these memory locations, we are doing the same thing? Well the X register can only hold a value between 0 to 255 and we have a screen which is 1000 bytes long hence it will only be able to clear 256 characters of the screen.
We could have added 256 to \$0400 and that you mean that next memory location would be \$0500, $600 and $7000 however 256 multiplied by 4 gives us 1024 which is more than our 1000 characters. It happens that after memory location \$07E7 (2023) we have some sprite registers. We will be overwriting these if we had to clear 1024 bytes instead of 1000 bytes. In some cases, this doesn’t matter but for a game it does, most of the time you are using sprites, so I got into the habit of avoiding clearing memory locations beyond 2023.
To overcome the issue instead of adding 256 we could add 200. Now 200 x 5 gives us 1000 which is the screen memory size. Therefor the memory locations \$04c8, \$0590, \$0658, \$0720 are 200 bytes apart and if we add X with a value between 0 and 199 (200 characters) we will be clearing the whole screen and we will be covering 1000 characters.
We are incrementing X each time we go through the loop.
We are making sure we have not reached 200, so we compare the value of X with that of 200.
If the value of X is not equal to 200, we simply loopback to like 49. If it is equal to 200, we stop looping and continue with the next instruction which is the subroutine that will check for the space bar.
Running the program will produce a blank black screen and you will see the ready once you press the space bar.
Here is a link to the C64 screen codes.
This simple screen cleaning code could also be used to fill the screen. By passing a value different that $20 in line 47 you can fill the screen with whatever character you want.
What will happen if you had to change the value in the line 47 to another value say 0?
What screen code did I use to fill the screen and create the effect below?
Here is a full listing of the code used for method two.
Method Three – Using Page Zero
The method is same as method two however instead of using absolute indexing mode we use page zero to clear the memory screen.
This method goes beyond the 1000 characters on the screen and it changes sprite registers. It is not ideal for games, but I am covering it here to make you aware of how to use Page Zero.
In article 8 I will reveal my screen clearing technique using page zero and only clearing the 1000 characters of the screen. It will also be like a revision of this article.
Here is the main code
Most of Page zero memory locations are used by the system and basic. However, there are 4 memory locations that are left free for the programmer to use. These are \$FB, \$FC, \$FD and \$FE.
If you want to see what each memory location at Page zero is used for, check the link below.
As stated, note the free addresses at the end of the page. Also, some of the Page Zero addresses are interesting to investigate and have a look at.
Lines 52 to 55
As mentioned previously screen memory starts at \$0400. We are storing \$00 at \$FB and \$04 at \$FC. Remember we must store a memory address as low byte and high byte ($LLHH). All this was covered in article 4. Why we need to do so? It is because this is how the 6502 stores memory addresses and if you recall this is how memory address should be stored in memory.
Here please note also that I am initialising X with \$04 and storing the same value of X at in \$FC. The value of X will be used later, and this is also an optimisation. I could have used the A register or the Y register but I this this for a reason which will become evident later on.
We are initialising the Y registers with 0. We could have used LDY #\$0 but since we know that the accumulator value is already zero, we just used the instruction TAY which is a faster instruction. I did this to show you optimization.
This is the usual instruction are per previous method and we load the accumulator with screen code \$20 or 32 which is a space character.
This is everything basically and why it makes it a fast routine. We are storing the accumulator value in the memory address found at \$Fb and \$FC plus the Y register.
Here we are using the addressing mode Post Indexed Indirect Y. The memory address we are referring to is \$0400 (remember stored in reverse order) where add the Y register to \$0400 and we store the value of the accumulator there.
Line 60 and 61
We increment Y and if it is not 0, we loop again. When Y is 255 and it is incremented it will be 0 again and so we go to the next instruction.
When we cleared the first 256 characters, we need to clear the next 256 characters. We therefor increment what is store in \$FC by 1 to become $05. Not the address stored at \$FB and \$FC is not anymore \$0400 but $0500 and Y can start modifying this range of memory.
Line 63 and 64
Remember what I said earlier about X. Well here is the answer why I used X. To clear the screen, we need to change the value at \$FC. We need to change this \$05, \$06 and \$07. We exit the loop when X is 0 and do the next instruction which is the routine to wait for the space bar to be pressed. When X is 4, we had memory address \$0400, when X was 3, we had memory location \$0500 and so on stored at \$FB and \$FC.
As stated, this routine code by passes the 1000 character of screen memory so I would use it with caution. If you are not using any of the Sprites, then there is no harm in using it.
Here is a screen capture and as always never forget that SYS 49152 to execute the code.
Here is a listing of all the code
Next Article – 11th May
That is, it for this week. I hope that you could see how the same routine can be used to clear or fill the screen. In theory you are filling screen memory with a space which makes it look like you are actually have clearing it.
Next article is not next week unfortunately but on the 11th of May. The reason for this is I have some commitments that I can’t avoid, and it will be taking a priority in the coming weeks.
The next thing that we will cover will be printing on the screen.
As always if you have any issues please message me. That is all for now.
Coding is Fun 😊