Commodore 64 BASIC is known for its lack of commands and instructions. On the start-up screen message, it is said to be “Commodore 64 BASIC V2”, but it is actually the old CBM BASIC 2.0 found on old Commodore PET/CBM machines. You don’t have easy access to bitmapped graphics and sound. But, thanks to the Commodore 64 complex architecture, it is possible to achieve nice results even with its native BASIC interpreter.
Commodore 64 custom chips are mapped in RAM. There are some special RAM locations containing a value that it is not data but rather a system parameter. For istance, if you put value 0 on location 53280 (decimal notation) you are not only storing a value in RAM, but you are actually changing border colour. That is, VIC-II border colour register is mapped on location 53280 (decimal).
Another VIC-II register is the raster count register. It is actually split in two locations: 53266 and 53265. You need 9 bits to express the raster count value, so the ninth bit is on bit 7 of location 53265. Let’s talk about what the raster is.
On a raster graphics system, the image is updated a fixed number of times per second. On PAL systems, this is 50 Hz on old CRT TV sets. On NTSC systems, it is 60 Hz but it makes no difference in the concept. So, on PAL systems the image is updated 50 times per second.
You can think of the raster as something that moves from the top to the bottom of the screen and updates the image, one scan-line at a time. A scan-line is a line that is one pixel high and it is as wide as the screen is. If you have tried to take a picture of the image shown by an old CRT TV set, you’ll have seen something moving vertically. Well, that is the raster.
The VIC-II chip can tell you on any istant which scan-line is being drawn on a given time. The raster registers contain that line number.
What knowing that number can be useful for? You can change information on the screen while a given scanline is being drawn, and everything being drawn afterwards will be affected by that change. So, you can set screen color to white, than wait for the scanline to the center of the screen, than you can set that color to black. If you keep repeating these operations like in a cycle, you will have a screen split with two colors.
Usually, raster programming tecniques are intended to be used with assembly language only. Still, it is possible to do some raster effects even by using BASIC. Some examples have been shown in the forums. More than ten years ago, I started playing around with them and I am now going to share my experiments.
If you want to actually code Commodore 64 demos, the only answer is assembly. But if you like to make experiments, or you don’t know how to use machine language, then this article may be of interest to you.
With PEEK and IF BASIC instructions, we cannot wait for a particular scanline. Waiting for a scanline means checking continuosly the raster register’s value until it equals the required scan-line number. By the time you PEEK that register and you check the value, a whole frame may have been drawn.
But, there’s a powerful BASIC instruction that suits our needs: WAIT. In this article, I am not going to tell you all about this instruction, which is one of the most difficult to understand in Commodore BASIC. What we need here to know, is that if we write a statement such as:
WAIT location, value
the computer will wait until some bits in the content of location turn on. Which bits? At least one of those that are set on in value.
So, the statement WAIT 53265,128 will wait until bit 7 of the content of location 53265 will turn on. That is, the computer will stop waiting as soon as the bit 7 of 53265 turns on (2^7 = 128).
For a full explanation of the WAIT statement, you may read this article. But you can just keep on reading here (that’s what I advice, you may look at the WAIT article later).
The statement WAIT 53265,128 is very useful: it waits until the current scanline is out from the viewable screen area. That is, when WAIT 53265,128 stops waiting, the VIC-II chip is drawing the border. Technically speaking, when the ninth bit of the raster value register is set, it means the raster count is more than 255: that just happens in the beginning of the bottom border. The value used in the WAIT statement is 128 because bit 7 of location 53265 is used to store the 9th bit of the raster value register.
If you have tried simple sprites BASIC programs, like the one on the User’s Manual, you’ll have seen some flickering while the sprites move. That happens because the sprite is moved when the VIC-II is still drawing it. If you want smooth motion with no flickering, you have to change sprite position only when the VIC-II is drawing the border.
In other words, in this case changes on the screen must be made when the rasterbeam is out of the viewable area. WAIT 53265,128 just allows you to do this.
Now, we are going to make raster graphics with BASIC. I use VICE 2.4 emulating a PAL machine for testing. Results may slightly differ on the original machine.
We will repeat a set of instructions again and again. But, there is a time constraint: this set of instructions must be executed within a frame. Otherwise, we will have flickering. So, we need to code in an efficient way. To accomplish that, there are some rules to follow:
- keep line numbers low. So, start line numbering from 0 and increment line numbers by 1 (0, 1, 2 and so on). Line 0 is not used normally, but it is useful in this situation;
- use always variables on the code that will be repeated, not numbers. That will make your code faster. Still, small numbers can be used to shorten the whole program.
- avoid spaces and comments;
- try to keep your program as tiny as possible.
These little tricks will make your program go fast. We’ll see other useful tips later.
Now, let’s write a program that splits the border color in different color areas. The idea is to change border color various times within a frame. We can wait for the VIC-II’s driven “rasterbeam” to be in the border, than we can start change border color various times. How many times? Just as much as it makes it possible to execute our repetitive code within a frame. After the border color changes, we’ll wait again for the rasterbeam to be in the border, and so on. The “rasterbeam” may be seen as a “brush” that draws scanlines within a frame, from top to bottom and from left to right.
We start our program with some definitions:
This way, we will be able to use variables instead of numbers. The Commodore 64 BASIC interpreter gains access to variables faster than constant values, that’s why we are doing so.
Now, we have to wait that the rasterbeam is on the border:
1 WAIT Q,W
From now on, we can change border colors:
2 POKEB,1:POKEB,2:POKEB,3:POKEB,4:POKEB,5:POKEB,6:GOTO 1
I didn’t use variables for the border colors to make the program shorter.
The whole program is a closed loop that repeats itself indefinetely, at least until you stop the program by pressing RUN/STOP as usual.
As you can see, you have splits very similar to those accomplished by using machine language.
You will see that the bars will move for a few seconds, then they will stabilize. But still, there will be some flickering.
The tickness of each color bar is just as much as the time a poke requires to be executed. So you can see how many scanlines it takes to execute each poke.
If you press the spacebar while the program is being executed, you will notice some flashing of the colors: that’s the delay due to the operating system processing that keystroke. The system is actually checking the keyboard continuosly. And it is checking many other things. Technically speaking, it is handling system interrupts. To disable the interrupts in Commodore 64 BASIC, we can use the following statement:
Now, let’s add this statement to our code and let’s see if something changes. Modify line 0 to the following:
0 Q=53265:W=128:B=53280:POKE 56334,PEEK(56334)AND254
If you run the program, you will see that the splits are nearly perfect. As we don’t need the operating system reading the keyboard, we can speed up things this way.
To stop the program, you should use the RUN/STOP + RESTORE keys. Those work because NMI interrupts are not maskable. Anid the RESTORE key triggers an NMI.
As you may see, a split still needs improvements. The border changes from white to red just while a scanline is being drawn: as a result, you have an unwanted edge.
We need a way to make a very short pause within our program, and that may fix things up. A colon (:) is just what we need. You usually use one colon to put more statements on a BASIC line. But you can use just as many colons as you wish on a line. They will cause no errors. And they will be processed by the interpreter. As a result, you will have the short pause needed. The more colons in sequence, the longer the pause.
Remember that results may slightly differ between the emulated machine and the real thing.
We can’t achieve perfection with BASIC, but we can neatly improve our program with the following modified line:
2 POKEB,1::POKEB,2::POKEB,3:POKEB,4:POKEB,5:POKEB,6:GOTO 1
As you can see, two colons have been added.
Try to RUN the program several times. You’ll see that sometimes the split will be not perfect, but in most cases it will work fine. Without the added colons, the split was always not perfect.
We can play more with colon delays and make the color bars move smoothly. Try to modify the previous program as follows:
2 pokeb,1:pokeb,2::::pokeb,3:pokeb,4:pokeb,5:pokeb,6:goto 1
Now the bars should be “scrolling” for a while, then start from their initial position. It just happens that with those delays the program can’t follow the rasterbeam perfectly. So, on each frame, every scanline number the WAIT statement catches shifts by 1. That’s why we see a smooth scrolling. Line 0 has been modified to shorten the program and improve performance.
The following code is another example of a screen split. It seems to work always. The program is running with the screen blanked. Screen blanking is obtained by turning off bit 4 of 53265.
I obtained the right number of “:” to use just by trial and error.
Screen blanking allows the CPU tu run a bit faster, as the VIC-II doesn’t steal cycles to the CPU to fetch characters codes any more. So, the pause obtained by the additional colons will be a little shorter and that may allow for more fine tuning. Furthermore, screen blanking lets you see the split at its full width.
Now, we can do things in another way. We can wait that the rasterbeam will be out of the border and start changing border colors from there. Actually, it’s the opposite of what we have done so far.
The WAIT statement will help us do that. We have to use the statement:
If you add another number to the WAIT statement arguments, and this number is the same as the first number, the program will wait until the bits which are set to on in the arguments will turn OFF.
So, that statement just waits until bit 7 of location 53265 turns off. And that just happens when the rasterbeam is out of the border.
The following program uses this technique.
As usual, raster bars may be not always perfect, but if you try to RUN the program a few times, you’ll notice that most of the time it works just fine.
I did a few tests on a 250466 board Commodore 64. I needed slightly different fine adjustments (the “:” delays). Have a look at the following screenshots.
Doing color bars on the border is just one of the many options available. Those bars may have been not that fun, but they just let you see what is happening. Still, we can do many other things. I hope I will be able to recall the experiments I did years ago. I will make those available on other articles.