Very basic BASIC: plotting characters on screen (C64 and VIC-20)

As we all know, CBM BASIC V2 does not support printing characters on screen starting from a given x, y location of the cursor (that is, plotting characters).

However, some techniques are available so that we can achieve this result without the need of expanding BASIC or using an ML utility.

Back in the old days, when computers did not support bitmap graphics (most machines from the 70s and early 80s come to mind, including Commodore PETs or CBM 2 machines with no hardware add-ons), the only way to plot functions was based on plotting characters on the screen as they were dots.

So, let’s have a look at how we could plot a character with BASIC V2, starting with simple techniques using the available commands.

 

Plotting characters using PRINT

The TAB function can be used for X coordinates. It accepts values from 0 to 255, but we are interested on values from 0 to 39 (covering all screen columns).

The statement PRINT TAB(0)”HI” is the same as PRINT “HI”. PRINT TAB(1) “HI” will print the message HI starting from the second column and so on.

Please note that the SPC function will work the same way on this case.

Now we have to deal with Y position. There is no function for this coordinate, so we must use control characters. To start printing from a given Y coordinate, we can set the cursor to home position, then print the CURSOR-DOWN control characters as many times as required, for instance using a FOR… NEXT cycle.

This approach consists of method 1 in the following program (subroutine starting from line 200). XP and YP are the coordinates of the character to plot.

 

DOWNLOAD: plotting characters on screen (Commodore 64 and unexpanded VIC-20 )

Note: to successfully load the program on a Commodore VIC-20, use the command LOAD”*”,8 (and not ,8,1).

 

POKEing characters on screen

Another method we can use deals with POKEing screen codes on screen. If 1024 decimal is the screen memory base address, a character can be plotted on screen by using the statement:

poke 1024+yp*40+xp, sc

In the above, sc is the screen code of the character to be plotted.

It’s important to note that both xp and yp must be integer here. Otherwise, an incorrect poke address would result from calculations. That’s why line 222 is included.

This is method two in the program, used by the subroutine starting from line 220.

 

Using the KERNAL routine PLOT

There is another method for plotting characters that allows the direct use of X and Y coordinates. There is a KERNAL routine called PLOT that can both read cursor position and set it.

The easiest method to use it is to make a direct call to the routine in ROM without using the KERNAL jump table. This requires two pokes with the X and Y coordinates. Locations 211 and 214 decimal are used for X and Y coordinates respectively. On the Commodore 64, the routine itself is located at 58732 decimal. This approach is used by method 3.

If we want to use the KERNAL routine via a jump table address, setup is less straight. The KERNAL PLOT routine (with jump table address 58634 decimal) requires before being called that the X and Y plot coordinates are placed in the Y and X registers respectively (yes, they are reverted). Then, the carry flag must be cleared so that the routine knows it must set the cursor to a given position. Otherwise, if we set the carry then we call the routine, it will return the current X and Y coordinates of the cursor on registers Y and X respectively.

To call this routine from BASIC, we must use locations from 781 to 783 decimal for setup. These are used by the SYS instruction, which puts the contents of these locations on the CPU registers before calling the machine language routine. Location 780 is also used for the A register, but it is not useful here.

Location 781 decimal is used for the X register, location 782 for the Y register and location 783 for the status register. The carry flag is bit 0 of this last location (thus, its bit value is 1). We only have to set or clear the carry flag. Clearing all flags is safe, setting them all is not. In facts, if we happen to set the interrupt disable flag, we will cause troubles.

This approach (method 4) is used in the program on the subroutine starting from line 260. This method requires one more POKE than method 3, but allows for some compatibility among Commodore 8 bit computers, as an address from the standard KERNAL jump table is used.

In case the circumference is plotted using either method 1, 3 or 4, cursor coordinates are also printed on screen by using the KERNAL PLOT subroutine in “read mode” (carry flag set). The subroutine starting from line 300 does this.

 

What method is best

Method 1 is the slowest, but it doesn’t require POKEs to machine-specific locations. So, you may use it if you need compatibility with other Commodore systems.

Method 2 is faster, but it makes use of POKEs to the screen memory (video matrix). So, starting address must be changed when switching to another machine. Furthermore, on the Commodore 64 the video matrix base address can be changed, so the POKE statement must be adjusted accordingly.

Method 3 is as fast as method 2, but it only works with a given machine as well, as a direct call to ROM is used. So, when switching on another machine, the direct address to call must be changed.

Method 4, using an indirect jump via a standard jump table, can provide compatibility with other 8 bit Commodore computers. It requires an additional POKE, but it is more or less as fast as method 3.

 

VIC-20 compatibility  – the KERNAL routine SCREEN

One problem for compatibility is that the VIC 20 computer has a 22 x 23 characters text screen. If we want our program to run on a VIC-20, we must have some way of determining what machine the program is running on. The KERNAL routine SCREEN  returns the X and Y organization of the text screen, thus allowing to determine if the machine in use is a VIC-20.

The SCREEN routine address is 65517 decimal (of course, in the KERNAL jump table).

We also have to take note that on an unexpanded Commodore VIC-20 the text screen base address is 7860 decimal. Also, when POKEing characters on screen, we must set the color code in color memory for each character cell, otherwise characters will not be visible. Color memory on a VIC-20 starts from 38400 decimal.

The KERNAL routine PLOT has the same jump table address on both the VIC-20 and the C64, so C64 method 4 will work fine on the VIC-20 as well. Instead, if we want to use a direct ROM call, the entry point for the VIC-20 is  location 58759 decimal.

In the program, the flag variable VF is used to signal if the machine is a VIC-20 or not. Check is performed on line 2 using the KERNAL routine SCREEN, and some variables in the program are adjusted accordingly.

 

A Sinclair ZX Spectrum version

Sinclair BASIC does include support for plotting characters on screen. This can be done by using the PRINT item AT, which allows you to set the cursor on a given X, Y position right before printing information.

AT is followed by the Y and X coordinates of the cursor, separated by a comma. So:

print at 15,11;"h"

will print an h to the center of the screen.

So, characters plotting is quite easy on a Spectrum machine, and the following short program does the same plot as the above Commodore versions.

 

DOWNLOAD: plotting characters on screen (Sinclair Spectrum)

 

 

Simons’ BASIC version (C64)

If using Simons’ BASIC, things get simple on the Commodore 64 as well. In facts, the print item AT is available, and works in a similar way as the Sinclair’s counterpart.

Syntax is as follows:

print at(x,y)"string"

Unlike the Sinclair version,  X, Y coordinates are not reverted here. This is better, as usually the X coordinate comes first in math.

The Simons’ BASIC version is as follows.

 

DOWNLOAD: plotting characters on screen (Simons’ BASIC, C64)

 

6 Replies to “Very basic BASIC: plotting characters on screen (C64 and VIC-20)”

  1. I liked this article. Gave me exactly what I needed to get started in my little @ adventure around some petscii graphics. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

Insert math as
Block
Inline
Additional settings
Formula color
Text color
#333333
Type math using LaTeX
Preview
\({}\)
Nothing to preview
Insert