Hi-Res VIC Drawing
Jeff Wise
There comes a time when programmers want more subtle graphics than can be achieved with characters and low resolution. Do you ever feel like creating swirling, intricate webs of delicate, slender lines? Here's how to achieve high resolution on the VIC.
The designers of the VIC-20 thoughtfully included in the VIC chip a special programmable character generator. Though mainly intended for creating custom alphabets and symbols, it can also be used to generate an entire high-resolution screen.
Each character that the VIC puts on the screen, whether user-defined or standard, is stored in eight bytes of memory. Each byte defines one of the eight rows that comprises a VIC character. Furthermore, each of the rows is split up into eight sections corresponding to the eight bits in that row's byte. If a bit is on (there is a 1 in its location), then its chunk of the row is lit up. If a bit is off (it contains a 0), then its chunk of the row is blank.
Character Matrices
"Microdraw" sets up a matrix of 12 X 15 custom characters, all of which are initially made blank (by POKEing 0 into the defining bytes). Since each character is defined by eight bytes of eight bits each, we have a total of 11,520 bits, or dots, on the screen which we can turn on or off at will. To light up a dot, simply POKE a 1 into its corresponding bit.
Such high resolution comes at a price. In order to use custom characters, we first must set the character memory apart from the BASIC program area. Since we are using so many characters, a lot of memory is consumed—1.5K, nearly half the memory available in an unexpanded VIC.
Now that we've covered the theory, it's time to enjoy your VIC's hi-res capability. Type in Microdraw, save it, then run it. Plug in your joystick, if you have one. Select the foreground and background colors for the drawing area by pressing the number key with the appropriate color on it. The program will then set up the drawing area and display the cursor. You control the cursor by moving the joystick in the direction you want the cursor to go.
Initially, the cursor is in the erase mode, which means that the cursor does not create a line as it travels and will erase any line it comes in contact with. In this mode the TV speaker emits a low beeping tone.
To change to the drawing mode, press the fire button on the joystick. The TV speaker will then beep in a higher-pitched tone, and the cursor will leave a line as it travels. To change back to the erase mode, simply press the fire button once again.
The SAVE Function
The function keys offer three additional options: The fl key erases the drawing screen and leaves the cursor in position; f3 starts the program from the beginning and resets all variables; and f5 causes the program to jump to a screen-saving routine. The saving routine is self-explanatory, as is the retrieval routine. To replay the data you have stored, choose selection 2 ("load an old one").
If you do not have a joystick, a simple modification will allow you to use the keyboard instead. Delete lines 330 and 340, and change line 320 to read:
320 A = PEEK(197) : J0 = -(A=44): J1 = -(A=36):J2= -(A = 20) : J3 = -(A = 12) : IF A = 32 THEN B = ABS(B -1) rem 155
Now the cursor's up, down, left, and right motions are controlled by the I, M, J, and K keys, respectively. To change modes, press the space bar instead of the fire button. It is not necessary to hit the control keys repeatedly; the cursor will move as long as the key is held down. If no key is pressed, the cursor will stop. In all other respects, the program works as before.
Microdraw10 POKE 36869, 240 : POKE 52, 24 : POKE 56, 24 : POKE 36879, 27 : CLR : rem 84 40 PRINT " {CLR}{3 DOWN}l) DRAW A NEW PICTURE. {DOWN}2) LOAD AN OLD ONE. " : POKE 198, 0 : rem 105 60 GET A$ : IF A$ < > " 1 " AND A$ < > " 2 " THEN 60 : rem 133 70 IF A$ = " 2 " THEN 450 : rem 214 80 PRINT "{CLR}{3 DOWN} BORDER COLOR?" : GOSUB 100 : G = VAL(A$) - 1 : rem 123 90 PRINT "{3 DOWN)BACKGROUND COLOR?" : GOSUB 100 : H = VAL (A$): GOTO 120 : rem 180 100 GET A$:IF A$ < " 1 " OR A$ > " 8 " THEN 100 : rem 53 110 RETURN : rem 114 120 POKE 36879, G + 16 * H - 8: PRINT "{CLR}" : rem 77 130 FOR X = 0 TO 21 : FOR Y = 0 TO 22 : POKE 7680 + X + 22 * Y, 160 : POKE 38400 + X + 22 * Y, G : NEXT : rem 44 140 IF W = 1 THEN 160 : rem 175 150 FOR I = 6144 TO 7679 : POKE I, 0 : NEXT : FOR I = 742 4 TO 7431 : POKE I,255 : NEXT : rem 182 160 C = 0 : POKE 36869, 254: FOR X = 5 TO 16 : FOR Y = 3 TO 18 : IF X + Y = 34 THEN NEXT : GOTO 180 : rem 53 170 C = C + 1 : POKE 7680 + X + 22 * Y, C : NEXT : NEXT : rem 235 180 Y = 18 : FOR X = 3 TO 18 : POKE 7680 + X + 22 * Y, 160 : NEXT : C = 90 : rem 191 190 IF J1 THEN F = F + 1 : IF F > 7 AND (C + l)/16 < > INT ((C+l)/l6)THEN F = 0 : C = C + l: GOTO 210 :rem 82 200 IF F > 7 THEN F = 7 : rem 197 210 IF J3 THEN F = F - 1 : IF F < 0 AND(C-1)/16 < >INT (( C-l)/l6) THEN F = 7 : C = C - l : GOTO 230 : rem 85 220 IF F < 0 THEN F = 0 : rem 183 230 IF J0 THEN E = E + 1 : IF E > 7 AND C < 177 THEN E = 0 : C = C + 16 : GOTO 250 : rem 222 240 IF E > 7 THEN E = 7 : rem 199 250 IF J2 THEN E = E - 1 : IF E < 0 AND C > 16 THEN E = 7 : C = C - 16 : GOTO 270 : rem 176 260 IF E < 0 THEN E = 0 : rem 185 270 POKE 6144 + (8 * C) + F, PEEK (6144 + (8 * C) + F) AND NOT(2↑(7 - E)) : rem 203 280 POKE 6144 + (8 * C) + F, PEEK (6144 + (8 * C) + F) OR 2↑(7 - E) : rem 88 290 POKE 36878, 15 : POKE 36874 + 2 * B, 130 + INT (c/2.14): POKE 36878, 0 : rem 221 300 POKE 36874 + 2 * ABS (B - 1), 0 : rem 120 310 IF B = 0 THEN POKE 6144 + (8 * C) + F, PEEK (6144 + (8 * C) + F) - 2↑(7 - E) : rem 75 320 POKE 37154, 127 : Z = 128 AND PEEK (37152) : J0 = - (Z = 0) : rem 123 330 POKE 37154, 255 : Z = PEEK (37151) : rem 217 340 Jl = - ((ZAND8) = 0) : J2 = - ((ZAND16) = 0) : J3 = - ((ZAND4 )=0) : J = -((ZAND32) = 0) : IF J THEN B = ABS(B - l) : rem 91 350 GET A$ : IF A$ lt; > CHR$ (133) AND A$ < > CHR$134) AND A$ < > CHR$ (135) THEN 190 : rem 112 360 IF A$ = CHR$ (134) THEN 10 : rem 68 370 IF A$ = CHR$ (135) THEN 390 : rem 129 380 FOR I = 6144 TO 7423 : POKE I,0 : NEXT : FOR I = 7432 TO 7679: POKE I,0: NEXT : GOTO 190:rem 92 390 POKE 36869, 240 : POKE 36879, 27 : rem 172 400 PRINT "{CLR}{DOWN}{RVS}T{OFF}APE OR {RVS}D{OFF}ISK?" : POKE 198, 0 : rem 237 402 GET A$ : IF A$ < > " T " AND A$ < > " D " THEN 402 : rem 26 405 IF A$ = " T " THEN PRINT "REWIND TAPE" : rem 85 415 PRINT "HIT A KEY WHEN READY" : rem 33 420 B$ = " " : GET B$ : IF B$ < > " " THEN 420 : rem 175 425 IF A$ = " T " THEN OPEN 1, 1, 1 : rem 176 426 IF A$ = " D " THEN INPUT "FILENAME"; N$ : N$ = N$ + ", S, W" :D = 8 : OPEN l, 8, 5, N$ : rem 5 430 PRINT #1, G : PRINT # 1, H : FOR A = 6144 TO 7679 : PRINT # 1, PEEK (A) : NEXT : CLOSE l : rem 192 440 PRINT "{CLR} YOUR PICTURE IS SAVED." : GOTO 10 : rem 120 450 PRINT "{DOWN}{RVS} T {OFF} APE OR {RVS}D{OFF}lSK?" : D = l : N$ = " " : rem 17 455 GET A$ : IF A$ < > " T " AND A$ < > " D " THEN 455 : rem 42 460 IF A$ = " T " THEN PRINT "{3 DOWN} INSERT CASSETTE AND{3 SPACES} REWIND IT" : rem 0 470 PRINT "{DOWN}WHEN YOU ARE READY HIT (SPACE).{DOWN}" : W = l : WAIT 198, l : rem 71 475 IF A$ = " T " THEN OPEN 1, 1, 0 : rem 180 480 IF A$ = " D " THEN INPUT" FILE NAME"; N$ : D = 8 : N$ = N$ + ", S, R" : OPEN 1,8,5, N$ : rem 0 490 INPUT #l, G : INPUT #l, H: FOR A = 6144 TO 7679 : INPUT #1, C : POKEA, C : NEXT : CLOSE 1 : rem 116 500 GOTO 120 : rem 97 10000 OPEN 15, 8, 15 : INPUT #15, A, B$, C, D : CLOSE 15 :rem 198