Monthly Display - December 2017


Creating High Resolution Graphics on the Vic-20

The Vic-20 computer was an 8-bit computer which used a 6502 microprocessor and a 6561 Video Interface Chip (display chip), giving the computer its name. The unexpanded computer came with about 3.5 Kilobytes of RAM for programming (which is tiny by today's computers' standards) and it had a possible ‘high resolution’ graphics display of 176 pixels wide, by 184 pixels high. The computer didn't come with any special graphics routines for drawing lines or circles, so I needed to research how to produce such things. I remember being surprised and disappointed by how complex the task of drawing a line on the screen was. Just setting up a graphics screen and changing the colour of a single pixel seemed to be major operations, and were quite slow using BASIC routines. One of the first things I did was to expand my Vic-20 with some extra RAM. This provided more space for programming, especially for programs involving custom graphics.

While finding expansion RAM blocks for the computer, I came across magazines and manuals that provided programs and information about the computer. After finding an article about drawing lines on a Tandy Colour computer, I modified one of the provided subroutines to use the particular flavour of BASIC on the Vic-20, and eventually came up with a pretty good line drawing routine in BASIC. I later found out that the routine was based on Bresenham's Line Algorithm (an efficient line drawing algorithm that uses integer maths and results in lines with minimal scan-converting 'noise').

After the initial excitement of getting some high resolution graphics created using slow BASIC programming, I came across some machine code routines for setting up a graphics screen, and plotting a pixel on the Vic-20 in a book titled "Mastering the Vic-20" by A. J. Jones, E. A. Coley and D. G. Cole (Ellis Horwood Limited, 1983). I entered these machine code routines and found them to be super-fast and extremely reliable - excellent! They were also very efficient in terms of the memory being used by the routines.

Where machine code routines generally fell down in terms of efficiency was the time taken to produce them, to test them thoroughly, and to fix programming bugs, etc. I started my machine code writing by firstly modifying existing routines, so I could get an idea of how the routines worked, and why they were structured as they were. I enjoyed the logic, the strategies, and the mathematics involved in these machine code routines. I started writing my own machine code routines without any specialised machine code 'monitor', so I needed to plan them well and write them out on paper, as shown in the scans below.

I wrote several sets of machine code graphics routines, evolving the capabilities of each set from the previous ones. Most of the graphics I produced for this month's display were done using a set of graphics machine code routines I titled "BigArt". The routines basically plotted to and showed a section of a 'large' bitmap screen measuring 320 x 352 pixels that was set up within about 14k of added RAM.


Variables Listing Used for the BigArt Routines (one of about 5 similar pages):

Note the addresses in both Hexadecimal (base 16 - more useful for addresses in computer programs) and Decimal (base 10 -more familiar to humans).




Planning sheet for a machine code routine

One of the drafts for a routine to transfer part of the stored large 'hi-res' graphics screen to the smaller 'hi-res' display screen that the Vic-20 was capable of showing. One very important aspect was allowing the user to move the view around over the large screen, without allowing the user to get bytes from beyond the large screen and either getting rubbish shown on the screen or crashing the routines all together. The mathematics, logic and coding had to be done well.



Page of machine code listing 1


This and the next scan were two of about 50 pages written out manually with routines for the "BigArt" set of machine code routines. The final column represented the decimal numbers that were actually entered into each byte of the machine code region of RAM, and would be picked up by the microprocessor as machine code programming. A couple of diagnosed and corrected errors can be seen, with asterisks next to them.


Page of machine code listing 2


The set of machine code routines that made up the "BigArt" system were developed to the point where they were very reliable and accurate. Amongst many functions, they allowed manual editing of each pixel. They also allowed a magnified view of the large screen for more careful editing. The routines included:

Save HiRes Screen

Load HiRes Screen

Setup Small Viewing HiRes Screen

Restore Normal Text Editing Screen

Transfer Large HiRes Screen to Small HiRes Screen

Clear Large HiRes Screen

Plot Pixel on Large HiRes Screen

Line Draw between 2 points (each point defined with 2-bytes for the X coordinate and 2-bytes for the Y coordinate)

Plot a Pixel using Exclusive-OR

Read the Value of a Pixel

Get and Place Bytes for One Character Block (8 x 16 pixels or 16 bytes)

Show Whole of the Large Screen on the Small Display Screen

Draw Cursor A (drawn as larger cross)

Draw Cursor B (drawn as smaller cross)

Change Which Cursor is Active

Hide Active Cursor

Hide Both Cursors

Get Joystick Registers and Update Active Cursor X and Y values

Main Command Routine

Freehand Plot

Plot Point of Given Size (pixels wide x pixels high)

Magnify: Transfer Hi-Res Screen to Text Screen

Magnify: Draw Cursor

Magnify: Plot Point into Large Screen

Magnify: Main Command Routine

Store Section of Screen between Cursors (Copy section of Screen)

Put Stored Section of Screen at Position of Active Cursor

Send Stored Graphic to Printer

Draw Solid Block (Rectangle) between Cursors

Draw Open Rectangle between Cursors

Put Text Characters onto Large Screen

Draw Circle (Outline or Filled with Cursor A as the centre and Cursor B on the outline)

Draw Random Lines Over Entire Screen

Draw Random Lines between Cursors

Draw Random Points over entire Screen

Draw Random Points between Cursors

Draw Stored Sections of Screen at random points over entire Screen


Hopefully, this list gives some idea of the substantial work done in producing this set of machine code routines, which took several months. I am very proud of the work done for this set of routines. The routines all appear to work faultlessly.

The 2 Cursors

Note cursor A (with larger cross), and cursor B (with the smaller cross). Both of the cursors are drawn using an 'exclusive-or' mode. This mode means that as the pixels are drawn, if the underlying pixel value is white, it is drawn as a black pixel, and if the underlying pixel value is black, it is drawn as a white pixel.




Solid Block


Example of drawing a solid block, between the two cursors.



Magnify View:

Note the indication of the cursor, using the asterisk character. Pixels are shown as solid blocks. The magnify view can be moved about over the large screen using the cursor keys. The cursor can be moved using the joystick or the keyboard ("Q", "W", "E", "A", "D", "Z", "X", "C" keys to move in a direction relative to the "S" key).

With this system of graphics routines, I now had a bitmap screen of 320 x 352 pixels (112,640 individual pixels) available for producing graphics. I could easily edit each pixel on this screen. The regularity of the pixel array, and the decisive manner of a pixel either being white or black, gave a sense of high precision.


Monthly Display - December 2017