Visiting The VIC-20 Video
Jim Butterfield, Associate Editor
In which the traveller finds that the highest resolutions can be achieved by setting his sights a little lower.
We've spent some time viewing the world (or at least memory) from a video chip's-eye view, and we've noted that the video chip sees memory in its own way:
How the video chip sees memory
We've muddled with the character set, both built-in and home brewed. But we haven't seemed to deal with achieving that mystic goal – high resolution screen control.
We've dealt with custom characters. And as Glinda the Good Witch could have said to Dorothy, "If you had known their powers, you could have done it the very first day." In other words, we've been looking at high resolution all along without recognizing it.
Here's the trick: if every position on the screen contained a different character, and if we can define any character at will, we can define any spot on the screen as we wish.
Mechanically, we do it this way: the first cell on the screen will contain character zero; the next will contain character one; and so on. To change the upper-leftmost pixel on the screen, we modify the upper-left pixel of character zero, and the screen immediately shows the change.
This is a change from our usual use of screen and character set. Our screen memory is now totally fixed and must not change. Normal printout and things like scrolling must stop. The characters, on the other hand, are now completely variable, with pixels turning on and off according to what the picture needs.
Wait – there's a problem. It seems that the screen has room for 506 characters; yet we know that we can make only 256 individual characters. Something doesn't fit. How can we resolve this problem?
There are two ways. One is to use "double characters" — the jumbo-sized characters that we get when we POKE an odd number into address 36867. Each of our 256 characters now occupies twice the space on the screen, so that we can cover the screen easily. The character set table now becomes huge, of course: each character takes 16 bytes to describe, making the whole table up to 4096 bytes long.
Since we're trying to describe things you can achieve in an unexpanded VIC, this becomes impractical — it's hard to take 4K away from a machine that has only 3.5K available to start with. On a machine with memory expansion, however, this is quite practical; read on, for we'll use tricks on the small machine that will come in handy even on the big ones.
The other method is this: cut the size of the screen so that it contains only 256 characters or less. We can store the number of columns and rows we want into 36866 and 36867. POKE 36866, 16 will set 16 columns; and POKE 36867, 32 will set 16 rows (we must multiply the number by two here). How many characters can we store? 256 – and that number may sound familiar by now.
By the way, BASIC won't know how to cope with the peculiar row and column counts if you do this as a direct command, so be prepared for an odd-looking screen. Neatness fanatics will want to center the remaining display by appropriate POKEs to 36864 and 36865, but I'll leave this as an exercise for you.
Enough of this abstract theory. Let's dive into a program to prove that even the humble minimum VIC can do high resolution graphics.
100 POKE 56, 22 : CLR (Drop top of BASIC) 110 POKE 36869, 222 (Relocate screen...) 120 POKE 36866, 144 (and character set)
Note that the above line sets the screen to a half-block (128) and sets up 16 columns instead of the normal 22 (128 plus 16 gives 144). We may as well go ahead and change the rows:
130 POKE 36867, 32 (16 rows times 2) 200 FOR J = 6144 TO 8191 210 POKE J, 0 : NEXT J
We've cleared the entire character set to zero (all pixels off). Now let's set up the screen with character zero in the first slot, etc.:
300 FOR J = 0 TO 255 310 POKE J + 5632, J 320 NEXT J
Let's set all characters to color black:
330 FOR J = 37888 TO 38911 340 POKE J, 0 : NEXTJ
Our screen is now ready. Serious graphics takes quite a bit of math (dividing by 16 to find the row and column; dividing by 8 for the pixel position), but we'll substitute a little simple coding to draw a triangle:
400 FOR J = 6792 TO 6816 STEP 8 410 POKE J, 255 (horizontal line) 420 NEXT J 500 FOR J = 6280 TO 6664 STEP 128 510 FOR K = J TO J + 7 520 POKE K, 128 (vertical line) 530 NEXT K, J 600 FOR J = 6280 TO 6704 STEP 136 610 X = 128 (leftmost pixel) 620 FOR K = J TO J + 7 630 POKE K, PEEK(K) OR X 640 X = X/2 (move pixel right) 650 NEXT K, J 700 GOTO 700
The program is now complete. It will wait in a loop at line 700 until you press RUN/STOP. When you do so, a number of odd things will happen. The computer will try to print the word READY into screen memory, but screen memory is intended for a different usage now, and all that will result is screen "clutter."
Bring everything back to sanity by holding down RUN/STOP and hitting the RESTORE key.
Effective graphics calls for the use of a fair bit of mathematics. To place (or clear) a pixel, you need to find the row and column by dividing the X and Y coordinates by the appropriate scaling factor. You need to change this to a screen character number by multiplying the row number by the total number of columns and then adding the column number. Multiply this by eight, and you'll get the position where the character is located within the character set. Now we must go for the pixels within this character: the bits within a byte are pixels "across" and the eight consecutive bytes are pixels "down." Now you know why people buy a Super Expander – to save them from the math.
Even when you have plenty of memory available, which allows you to use double characters and get lots of pixels on the screen, it's usual to "trim" the screen a little. The normal 22 columns by 23 rows are usually trimmed back to 20 columns by 20 rows (actually ten rows of double characters). This does two things: it makes the arithmetic a little easier, and it drops the memory requirements from 4096 bytes for a full deck down to only 3200 bytes. This, in turn, gives us space to pack screen memory into the same 4K block. That's handy, because we cannot be sure that the video chip will have access to any more than 4K of RAM. BASIC, of course, will long since have been moved to occupy memory from 8192 and up.
If you want to add text to the high resolution display, it's a snap. Just copy the characters you want from the Character Set ROM and transfer them to the appropriate character slots on the screen. Of course, you would have thought of that yourself if I hadn't just told you.
Don't forget that you can POKE appropriate values into 36864 and 36865 to center the graphics neatly. Our example looked a little lopsided; try your hand at making it neater.
High resolution is there and waiting. Yes, you can do it on a small screen PET.
There's a good bit of math needed. You may find this a challenge: after all, isn't that what a computer does best?
Even if the mathematics befogs your mind and causes you to go out and buy a Super Expander, you'll have learned a few new things. First, the Super Expander doesn't make graphics possible – they were there all the time – it just makes them easier. Second, you'll have a better idea of what's going on inside your marvellous VIC computer.
Copyright © 1983 Jim Butterfield.