Fun With Scrolling

David Plotkin

While this article doesn't tackle the finer points of pixel scrolling, it does present several useful BASIC routines to help you learn more about "coarse" scrolling…the ability to move lines of graphics vertically and horizontally.

Many of the graphic capabilities of the Atari home computers have been documented in COMPUTE! Magazine: alternate character sets ("Superfont")1; use of characters in graphics modes ("Textplot")2; and several articles on Player/Missile graphics, including some excellent machine language subroutines. Notably absent has been one of the more spectacular abilities of the Atari – scrolling. For those who don't know, scrolling is the movement of the text or graphics on the screen in whole or in part. The arcade games Scramble and Defender use scrolling. And few of you avid gamesters have not seen Greg Christensen's "Caverns of Mars," a game that is so good that Atari itself is marketing it as "official" Atari. In the pages that follow, I will tell you how to scroll, and provide a program for a game which not only scrolls but includes some other tricks with P/M graphics.

First, though, a few words about the types of scrolling. Horizontal scrolling scrolls left and right; vertical scrolling scrolls up and down. Two subsets are coarse and fine scrolling, both applicable to horizontal and vertical scrolling. Coarse and fine scrolling can be combined to produce combined scrolling (tricky, huh?), which is the type of scrolling that games such as "Caverns of Mars" use.

What does all this mean? Well…coarse scrolling is movement of text or graphics in increments of one letter or one row or one column. Thus, graphics mode 3 has 24 rows from the top to the bottom of the screen, and 24 coarse vertical scrolls will move all the picture on the original screen off the screen. Fine scrolling allows for scrolling in the pixel elements of coarse scrolling, so the motion appears smoother. For example, in graphics mode 3, each coarse scroll is broken into eight finer scrolls. Fine scrolling by itself can only move screen data a total of one row or column, so the combination of coarse and fine scrolling is used to produce smooth motion over as many screens of data as required. Unfortunately (although combined scrolling is not particularly difficult or complicated), the necessary transition from fine to coarse scrolling and back which occurs during combined scrolling must happen very fast, too fast for BASIC. Otherwise, there will be some distracting displays on the screen.

A machine language routine for combined scrolling would probably do the screen manipulations during a vertical blank, which occurs 60 times a second when the TV electron gun has finished drawing the picture and is returning to the top of the tube to draw the next screen. Thus, the distracting graphics which occur when using combined scrolling in BASIC would not be seen.

The balance of this article will deal only with coarse scrolling, which is all you need for most applications. The Tricky Tutorial #2 by Santa Cruz Educational Software presents a machine language routine (for inclusion in a BASIC program – you don't need an assembler cartridge) for vertical combined scrolling which works very well. I will not reproduce it here, but I urge readers interested in learning combined scrolling to obtain the program and try the examples. The Tricky Tutorial #2 and this article will give you the necessary tools for some really great graphics displays.

Atari home computers keep the address of the Display List at memory locations 560 and 561 (PEEK(560) + 256 * PEEK(561)). The Display List is a set of instructions in memory that the computer uses to find out what to put on the screen. Every time you use a graphics # command, the computer creates a Display List somewhere in memory and puts the address at locations 560 and 561. The fifth and sixth numbers in the Display List are the address of screen memory – the first byte to be displayed on the screen. If you adjust the value of the number stored here, all the data on the screen will move – it will scroll!

So plug in your joystick and punch in the following program:

10 GRAPHICS 3 : COLOR 1 : PLOT 0, 0 : DRAWTO 40, 20
20 DL = PEEK(560) + 256 * PEEK(561)
30 DL4 = DL + 4 : DL5 = DL + 5 : NUML = PEEK(DL4) : NUMH = PEEK(DL5)
40 ST = STICK(0)
50 IF ST = 11 THEN NUML = NUML + 1
60 IF ST = 7 THEN GOTO 110
70 IF NUML < 0 THEN GOTO 110
80 IF NUML > 256 THEN GOTO 140
90 NUML = NUML - 256 : NUMH = NUMH + 1
100 GOTO 120
110 NUML = NUML + 256 : NUMH = NUMH - 1
120 IF NUMH < 0 THEN GOTO 40
130 IF NUMH > 255 THEN GOTO 40
140 POKE DL4, NUML : POKE DL5, NUMH
150 GOTO 40

Line 20 gets the address of the Display List, while line 30 establishes the variable for the fifth and sixth numbers on the Display List (DL4 is the fifth number). The loop from 40 to 60 changes the variable corresponding to the low part of the screen memory based on the position of the joystick. Lines 70 to 110 adjust the low part (NUML) and high part (NUMH) of screen memory to keep the values from going outside "legal" values. Thus, if NUML gets above 255, then you subtract 256 from it and add one to NUMH. And if NUML gets below zero, then you add 256 to it and subtract one from NUMH. Lines 120 and 130 keep the high part of screen memory from going outside of its limits. Once you reach NUMH = 0 or NUMH = 256 that's as far as you can go. Finally, line 140 POKEs the adjusted values of the address of screen memory and goes back to start again.

A few things you will notice about this program: as you scroll right with your joystick, the picture on the screen disappears off the left edge of your screen and reappears from the right edge. After ten horizontal scrolls, the line is once more on the screen, but now is displaced up one line. This is because in graphics 3, there are ten bytes per line of memory. Below is a chart of graphics modes versus some useful quantities.

GRAPHICS MODE 0 1 2 3 4 5 6 7 8
Rows per screen 24 24 12 24 48 48 96 96 192
Bytes per row 40 20 20 10 10 20 20 40 40

Every time you scroll a horizontal distance equal to the number of bytes per line (ten times in graphics 3, 40 times in graphics 7, etc.) you have scrolled vertically by one line. It looks, then, like horizontal and vertical scrolling are really the same thing. Of course, if you have ever played "Eastern Front" by Chris Crawford, you know it's possible to scroll horizontally without the same data coming back on the screen. As far as I can tell, to do that you have to modify the Display List to get the Atari to think that your TV screen is really more than one screen wide.

For the rest of this article, we'll stick to vertical scrolling. Let's change a few lines of the previous program:

50 NUML = NUML + 10 * (ST = 4) - 10 * (ST = 13) : NUMH = NUMH + (NUML > 255) - (NUML < 0)
60 NUML = NUML + 256 * (NUML < 0) - 256 * (NUML > 255)

and delete lines 70-110. Run the program and push your joystick forward and back. The new line 50 increments the value of NUML by 10, depending on the joystick position. It also takes care of incrementing the value of NUMH. Line 60 is responsible for adjusting the value of NUML if it goes outside its limits. Note that the expressions in parentheses are equal to one if the expression is true, and zero if the expression is false. This is much more efficient than the first program. By scrolling up and down in increments of ten (the number of bytes per line), you can achieve vertical scrolling without any horizontal movement.

So far you have not done anything really useful for making graphics displays. You can scroll down, leaving you with an empty screen, or up, which shortly produces a brightly colored jumble on the screen. What has happened is that you are displaying an area of RAM which has data in it. What you need is an empty protected area of RAM to put your own pictures into. To get the memory you need, we'll use a standard Atari trick. Location 106 holds the number of pages available in RAM. You can find this number, which will vary depending on how much memory you have installed in your computer, by doing a PEEK(106). If you then POKE a number into location 106 which is less than the original number, the difference is now protected and won't be used by the computer because it doesn't know that it is there. See the program following to see exactly how to code these commands. Now set up a loop to read zeroes into your protected memory and it will be blank.

The key to scrolling is defining the multi-screen picture to scroll across. I've already told you about locations DL4 and DL5, which hold the address of the beginning of screen memory. To understand how to set up your own pictures, there are two more memory locations you need to know about: 88 and 89. These memory locations hold the address of the start of write memory – the memory location where the computer is to execute commands from the keyboard or from a running program. The reason that you see the results of keyboard or program inputs on the screen is that, normally, the address of Display Memory and the address of Write Memory are the same. But they don't have to be. If you change the address of Write Memory and then execute some PLOTs and DRAWTOs, you will see nothing on the screen. However, when you change the Display Memory to match the Write Memory, the picture you've drawn will flash onto the screen. This is a technique known as page flipping.

To utilize this technique, change the Write Memory to write into your protected area of memory and draw the screen as you normally would. Then change the address of the Write Memory to be one screen away from where it was, and draw another screen. You can keep this up as long as you like, generating as many screens edge-to-edge as your memory allows. Then place your Display Memory at one end or the other (or in the middle if you like), and scroll away. The screens will run together if you've done it right, so you won't see the start of one screen and the end of another. And what is the memory length of one screen, for incrementing the Write Memory? Refer back to my chart. If you take the number of rows per screen and multiply by the number of bytes per row, you'll get the number of bytes per screen to move the Write Memory. In Graphics 3, for example, one screen is 24 * 10 = 240 bytes. Note that, in general, you will have to change both the high and low parts of Write Memory (locations 89 and 88, respectively) to get a total move of 240 bytes. The math is the same as that for the Display Memory since:

Write Memory = PEEK(88) + 256 * PEEK(89)

and the low part and high part of Write Memory have the same limits as those for the Display Memory. Also notice that each Graphics 7 screen uses up almost 4K of memory! The subroutine which begins at location 4900 sets up the cavern for the game. I've used the same screen pattern several times to generate a long cavern from just a few different screens. Each time one screen is drawn, I change the Write Memory by 240 bytes and draw the next screen. The POKE 559, 0 just turns off the screen and processor to speed up drawing the cavern. POKE 559, 34 turns them back on again.

P/M graphics is pretty much ideal for the user-controlled shapes when using scrolling, since it is displayed through a separate system from normal graphics and, as a result, doesn't move when scrolling or page flipping. The excellent machine language routine VBLANK PM3 was used for moving the space ship, missile, and pterodactyls in the program at the end of this article. I will refer you to that issue to familiarize yourself with VBLANK PM. One thing that it does not seem to be able to do is to change the shapes of the players. Thus, there is no way to blow up the ship or missile, or make the shapes appear different when moving left or right. This is not criticism. The authors were trying to make calls of the program from BASIC unnecessary, and they've done an excellent job. Nonetheless, I needed to change the shapes, and there's a fast and easy way to do that.

Remember "Extending Player Missile Graphics"4? In that article, a machine language program was presented. Its strong suit was that it could change the shape of players very quickly. It was called by a command of the form:

A = USR(XXX, PMBASE + FM + Y, MEM)

where XXX = address of the machine language routine

FM = First memory location of the player you want to change (512 for pl.0, double line resolution, 1024 for pl.0, single line resolution, etc.)

Y = horizontal coordinate of player

MEM = memory address of shape to change player to.

I read this routine into memory between 256 and 511, which are empty and protected, since page 6 (1536-1792) is used for VBLANK PM. The data for player shapes was put into the empty P/M memory from PMBASE to the beginning of Player 0. Once done, every time I needed to change a player shape, I used a call to Mr. Stoltman's routine, and voilà!

And so I present "Cavern Battle." Your spaceship hangs poised over a deep cavern, at the bottom of which lies a big blue box full of treasure. The object: get to the bottom of the cavern, retrieve the treasure, and get out again, all the while avoiding or destroying the pterodactyls trying to keep you from reaching the treasure. The pterodactyls can move through the walls of the cavern, but don't you try it or you'll blow up! To move your spaceship, use joystick 0, and press the red button to fire your missile. You can only have one missile in flight at a time, so don't waste them. If the pterodactyls catch you, you'll probably blow up, so be careful. You have several things in your favor – your ship is faster and there are only so many prehistoric birds per cavern. But they are tenacious and come unerringly for you.

When you reach the bottom of the cavern, hover over the treasure and you'll hear a tune announcing recovery of the treasure. Head for the surface and if you make it, you'll hear the little tune again. If you want to play again, just start down the cavern again. But this time there will be more pterodactyls. One note of warning: When you first RUN the program, the screen will go blank for about 45 seconds while the caverns are drawn. This is normal. Good luck and good hunting!!

LIST OF VARIABLES

NUML: Low part of screen memory

NUMH: High part of screen memory

SF: Ship flag position-equal to 1 when ship is facing right, equal to -1 when ship is facing left

MF: Missile position flag – works like SF except also equal to zero when missile is exploded or not launched

P2, P3: Position flags for Players 2 and 3. Work like MF

X0, X1, X2, X3: X coordinates of Players

Y0, Y1, Y2, Y3: Y coordinates of Players

PMBASE: Memory location of beginning of PM graphics

T2, T3: Temporary variables for remembering values of P2 and P3

M, MON: Keep track of number of Pterodactyls.

BOT: = 0 when ship has not reached bottom of cavern
= 1 when ship has reached bottom of cavern

PROGRAM DESCRIPTION

Line 40: Sets high and low part of screen memory variables.

Lines 50-180: Moves ship, scrolls background, keeps Pterodactyls and missile from moving off the screen, and makes Pterodactyls move up and down when background scrolls.

Lines 150 and 160: Changes ship direction.

Line 155: Detects arrival of ship at bottom of cavern.

Line 156: Detects arrival of ship at top of cavern after recovery of treasure.

Lines 162, 165: Line 165 detects a hit on the ship. Line 162 clears the register which detects a collision between the ship and the background. The need to do this arises from the fact that occasionally the background flashes when you are scrolling. This will register as a collision unless the collision register is cleared. This sequence also will give an element of randomness to the detection of a collision, since a collision will only be registered if a resetting of the collision register occurs between the execution of line 162 and 165. If you don't like this randomness, add a small waiting loop to the end of line 162. Since you only have to delay 1/60 of a second to allow the collision register to reset, only a small loop is required (resetting occurs during a Vertical Blank).

Lines 170 and 180: Resets ship position flags.

Lines 200-215: Launches missile.

Line 220: Advances missile and detects for a collision.

Lines 230-240: Explodes missile.

Lines 250-260: Determines if a Pterodactyl is hit – if it is, moves it off the screen.

Lines 310-350: Launches new Pterodactyls.

Lines 380-440: Changes bird positions and advances them.

Lines 500-560: Resets ship to top of cavern when it is destroyed. Starts game over again when five ships are lost.

Lines 600-640: Plays tune for arrival at the treasure and at top of cavern.

Lines 1000-2100: Initializes VBLANK PM and reads it into memory.

Line 1075: Reads data for various player shapes into memory.

Line 4900: Steps back top of memory.

Line 4910: Clears protected memory.

Lines 4920-4965: Changes Write Memory and draws each screen.

Lines 4970-4980: Defines Display Memory address variables.

Lines 5100-5500: Data for drawing screens.

References:

1"Superfont," COMPUTE!, January, 1982, #20

2"Textplot," COMPUTE!, November, 1981, #18

3"P/M Graphics Made Easy," COMPUTE!, February, 1982, #21

4"Extending Player Missile Graphics," COMPUTE!, October, 1981, #17

PROGRAM. Fun With Scrolling.

20 GOSUB 4900
30 GOSUB 1000
40 NUML = PEEK(DL4) : NUMH = PEEK(DL5) : SF = 1 : MF = 0 : NS = 5 : P2 = -1 : P3 = -1 : M = 25 : BOT = 0 : MON = M
50 IF STICK(0) = 15 THEN GOTO 50
60 ST = STICK(0) : IF ST = 15 AND STRIG(0) = 1 AND PEEK(53260) = 0 THEN GOTO 215
80 NUML = NUML + 10 * (ST = 14) - 10 * (ST = 13) : NUMH = NUMH + (NUML > 255) - (NUML < 0)
90 NUML = NUML + 256 * (NUML < 0) - 256 * (NUML > 255)
100 IF NUMH = RT + 14 AND NUML > 48 THEN NUML = 48 : GOTO 60
110 IF NUMH = RT + 1 AND NUML < 136 THEN NUML = 136 : GOTO 60
115 IF P2 = 0 THEN GOTO 126
120 Y2 = Y2 - 8 * (ST = 14) + 8 * (ST = 13) : IF Y2 < 32 THEN Y2 = 32
125 IF Y2 > 224 THEN Y2 = 224
126 IF P3 = 0 THEN GOTO 139
130 Y3 = Y3 - 8 * (ST = 14) + 8 * (ST = 13) : IF Y3 < 32 THEN Y3 = 32
135 IF Y3 > 224 THEN Y3 = 224
139 IF MF = 0 THEN GOTO 145
140 Y1 = Y1 - 8 * (ST = 14) + 8 * (ST = 13) : IF Y1 < 32 THEN Y1 = 32
143 IF Y1 > 224 THEN Y1 = 224
145 POKE PLY + 2, Y2 : POKE PLY + 3, Y3 : POKE DL4, NUML : POKE DL5, NUMH : IF MF< >0 THEN POKE PLY + 1, Y1 : POKE 53278, 1
150 X0 = X0 + 8 * (ST = 7) - 8 * (ST = 11) : POKE PLX, XO : IF ST = 7 AND SF = -1 THEN D = USR(260, PMBASE + 1024 + Y0, PMBASE + 1)
155 IF NUML = 194 AND NUMH = RT + 13 AND X0 = 124 THEN BOT = 1 : GOSUB 600
156 IF NUML = 136 AND NUMH = RT + 1 AND BOT = 1 THEN BOT = 0 : M = MON + 5 : MON = M : GOTO 600
160 IF ST = 11 AND SF = 1 THEN D = USR(260, PMBASE + 1024 + Y0, PMBASE + 9)
162 POKE 53278, 1
165 IF PEEK(53260)< >0 OR PEEK(53252)< >0 THEN GOTO 500
170 IF ST = 7 THEN SF = 1
180 IF ST = 11 THEN SF = -1
190 IF STRIG(0) = 1 OR MF = 1 OR MF = -1 THEN GOTO 215
200 MF = SF : X1 = X0 + 8 * (MF = 1) - 8 * (MF = -1) : Y1 = Y0 : POKE PLX + 1, X1 : POKE PLY + 1, Y1
210 D = USR(260, PMBASE + 1280 + Y1, PMBASE + 17 * (MF = 1) + 25 * (MF = -1)) : IF PEEK(53253)< >0 OR PEEK(53261)< >0 THEN GOTO 230
215 IF MF = 0 THEN GOTO 300
220 IF PEEK(53253) = 0 AND PEEK(53261) = 0 THEN X1 = X1 + 4 * (MF = 1) -4 * (MF = -1) : POKE PLX + 1, X1 : GOTO 300
230 D = USR(260, PMBASE + 1280 + Y1, PMBASE + 33) : SOUND 0, 100, 8, 8
235 FOR W = 1 TO 50 : NEXT W : D = USR(260, PMBASE + 1280 + Y1, PMBASE + 41) : MF = 0 : SOUND 0, 0, 0, 0
240 IF PEEK(53261) = 0 THEN GOTO 270
250 IF PEEK(53262)< >0 THEN X2 = 0 : Y2 = 0 : POKE PLX + 2, X2 : POKE PLY + 2, Y2 : T2 = P2 : P2 = 0 : M = M - 1
260 IF PEEK(53263)< >0 THEN X3 = 0 : Y3 = 0 : POKE PLX + 3, X3 : POKE PLY + 3, Y3 : T3 = P3 : P3 = 0 : M = M - 1
270 POKE 53278, 1
300 IF M <= 0 THEN GOTO 380
310 IF P2< >0 THEN GOTO 345
320 X = INT(RND(0) * 3) : IF X< >0 THEN GOTO 345
330 P2 = T2 : Y2 = INT(RND(0) * 180 + 32) : X2 = INT(RND(0) * 130 + 48) : POKE PLX + 2, X2 : POKE PLY + 2, Y2
345 IF P3< >0 THEN GOTO 380
346 X = INT(RND(0) * 3) : IF X< >0 THEN GOTO 380
350 P3 = T3 : Y3 = INT(RND(0) * 180 + 32) : X3 = INT(RND(0) * 130 + 48) : POKE PLY + 3, Y3 : POKE PLX + 3, X3
380 IF P2 = 0 THEN GOTO 415
390 IF X2 > X0 AND P2 = 1 THEN P2 = -1 : D = USR(260, PMBASE + 1537 + Y2, PMBASE + 57) : GOTO 410
400 IF X2 < X0 AND P2 = -1 THEN P2 = 1 : D = USR(260, PMBASE + 1537 + Y2, PMBASE + 65)
410 X2 = X2 + 4 * (X2 < X0) - 4 * (X2 > X0) : Y2 = Y2 + 4 * (Y2 < Y0) - 4 * (Y2 > Y0) : POKE PLX + 2, X2 : POKE PLY + 2, Y2
415 IF P3 = 0 THEN GOTO 60
420 IF X3 > X0 AND P3 = 1 THEN P3 = -1 : D = USR(260, PMBASE + 1793 + Y3, PMBASE + 57) : GOTO 440
430 IF X3 < X0 AND P3 = -1 THEN P3 = 1 : D = USR(260, PMBASE + 1793 + Y3, PMBASE + 65)
440 X3 = X3 + 4 * (X3 < X0) - 4 * (X3 > X0) : Y3 = Y3 + 4 * (Y3 < Y0) - 4 * (Y3 > Y0) : POKE PLX + 3, X3 : POKE PLY + 3, Y3
450 GOTO 60
500 D = USR(260, PMBASE + 1024 + Y0, PMBASE + 33) : NS = NS - 1 : SOUND 1, 200, 4, 10 : FOR W = 1 TO 500 : NEXT W : SOUND 1, 0, 0, 0
510 IF NS< >0 THEN GOTO 540
520 NS = 5 : M = MON
530 IF STICK(0) = 15 THEN GOTO 530
540 POKE DL4, 136 : POKE DL5, RT + 1 : POKE PLX, 116 : POKE PLY, 95 : SF = 1 : D = USR(260, PMBASE + 1024 + 95, PMBASE + 1)
545 X0 = 116 : Y0 = 95 : NUML = 136 : NUMH = RT + 1
550 X2 = 0 : Y2 = 0 : X3 = 0 : Y3 = 0 : POKE PLX + 2, X2 : POKE PLY + 2, Y2 : POKE PLX + 3, X3 : POKE PLY + 3, Y3 : BOT = 0
555 IF P2< >0 THEN T2 = P2 : P2 = 0
556 IF P3< >0 THEN T3 = P3 : P3 = 0
560 MF = 0 : D = USR(260, PMBASE + 1280 + Y1, PMBASE + 41) : POKE 53278, 1 : FOR W = 1 TO 500 : NEXT W : GOTO 60
600 SOUND 1, 40, 10, 8 : FOR W = 1 TO 30 : NEXT W : SOUND 1, 32, 10, 8 : FOR W = 1 TO 30 : NEXT W
610 SOUND 1, 26, 10, 8 : FOR W = 1 TO 30 : NEXT W : SOUND 1, 22, 10, 8 : FOR W = 1 TO 30 : NEXT W
620 SOUND 1, 32, 10, 8 : FOR W = 1 TO 30 : NEXT W : SOUND 1, 26, 10, 8 : FOR W = 1 TO 70 : NEXT W : SOUND 1, 0, 0, 0
630 IF BOT = 1 THEN RETURN
640 GOTO 530
1000 REM INITIALIZE VBLANK PM
1010 FOR I = 1536 TO 1706 : READ A : POKE I, A : NEXT I
1020 FOR I = 1774 TO 1787 : POKE I, 0 : NEXT I
1030 PM = PEEK(106) - 16 : PMBASE = 256 * PM
1040 FOR I = PMBASE TO PMBASE + 2047 : POKE I, O : NEXT I
1050 FOR I = PMBASE + 1025 TO PMBASE + 1029 : READ A : POKE I, A : NEXT I
1060 FOR I = PMBASE + 1537 TO PMBASE + 1545 : READ A : POKE I, A : NEXT I : RESTORE 3010
1065 FOR I = PMBASE + 1793 TO PMBASE + 1800 : READ A : POKE I, A : NEXT I
1070 POKE 704, 18 : POKE 705, 226 : POKE 706, 179 : POKE 707, 82
1075 FOR I = PMBASE + 1 TO PMBASE + 72 : READ A : POKE I, A : NEXT I
1080 PLX = 53248 : PLY = 1780 : PLL = 1784
1090 POKE 559, 62 : POKE 623, 1 : POKE 1788, PM + 4 : POKE 53277, 3 : POKE 54279, PM
1100 X = USR(1696)
1110 POKE PLL, 8 : POKE PLL + 1, 8 : POKE PLL + 2, 8 : POKE PLL + 3, 8
1115 X0 = 116 : Y0 = 95 : X2 = 190 : Y2 = 175 : X3 = 170 : Y3 = 175
1120 POKE PLX, X0 : POKE PLY, Y0 : POKE PLX + 2, X2 : POKE PLY + 2, Y2 : POKE PLX + 3, X3 : POKE PLY + 3, Y3
1130 FOR A = 260 TO 284 : READ I : POKE A, I : NEXT A
1140 RETURN
2000 REM DATA FOR VBLANK INTERRUPT {8 SPACES} ROUTINE-SEE COMPUTE! FEB. 1982
2010 DATA 162, 3, 189, 244, 6, 240, 89, 56, 221, 240, 6, 240, 83, 141, 254, 6, 106, 141
2020 DATA 255, 6, 142, 253, 6, 24, 169, 0, 109, 253, 6, 24, 109, 252, 6, 133, 204, 133
2030 DATA 206, 189, 240, 6, 133, 203, 173, 254, 6, 133, 205, 189, 248, 6, 170, 232, 46, 255
2040 DATA 6, 144, 16, 168, 177, 203, 145, 205, 169, 0, 145, 203, 136, 202, 208, 244, 76, 87
2050 DATA 6, 160, 0, 177, 203, 145, 205, 169, 0, 145, 203, 200, 202, 208, 244, 174, 253, 6
2060 DATA 173, 254, 6, 157, 240, 6, 189, 236, 6, 240, 48, 133, 203, 24, 138, 141, 253, 6
2070 DATA 109, 235, 6, 133, 204, 24, 173, 253, 6, 109, 252, 6, 133, 206, 189, 240, 6, 133
2080 DATA 205, 189, 248, 6, 170, 160, 0, 177, 203, 145, 205, 200, 202, 208, 248, 174, 253, 6
2090 DATA 169, 0, 157, 236, 6, 202, 48, 3, 76, 2, 6, 76, 98, 228, 0, 0, 104, 169
2100 DATA 7, 162, 6, 160, 0, 32, 92, 228, 96
3000 DATA 128, 64, 127, 24, 48
3010 DATA 1, 54, 52, 248, 28, 103, 74, 138
3020 DATA 128, 64, 127, 24, 48, 0, 0, 0, 1, 2, 254, 24, 12, 0, 0, 0, 224, 56, 224, 0, 0, 0, 0, 0, 7, 28, 7, 0, 0, 0, 0, 0
3050 DATA 219, 219, 60, 231, 231, 60, 219, 219
3060 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
3070 DATA 1, 54, 52, 248, 28, 103, 74, 138, 128, 108, 44, 31, 56, 230, 82, 82
4000 DATA 104, 104, 133, 204, 104, 133, 203, 104, 133, 207, 104, 133, 206, 160, 0, 177, 206, 145, 203, 200, 192, 8, 208, 247, 96
4900 RT = PEEK(106) : RT = RT - 16 : POKE 106, RT
4910 POKE 559, 0 : FOR I = RT * 256 TO (RT + 16) * 256 : POKE I, 0 : NEXT I : GRAPHICS 3 + 16 : COLOR 1 : POKE 765, 1
4920 POKE 89, RT + 2 : POKE 88, O : GOSUB 5100
4930 POKE 89, RT + 2 : POKE 88, 240 : GOSUB 5100
4940 POKE 89, RT + 3 : POKE 88, 224 : GOSUB 5200
4950 POKE 89, RT + 4 : POKE 88, 208 : GOSUB 5300
4951 POKE 89, RT + 5 : POKE 88, 192 : GOSUB 5100
4952 POKE 89, RT + 6 : POKE 88, 176 : GOSUB 5200
4953 POKE 89, RT + 7 : POKE 88, 160 : GOSUB 5300
4954 POKE 89, RT + 8 : POKE 88, 144 : GOSUB 5100
4955 POKE 89, RT + 9 : POKE 88, 128 : GOSUB 5200
4956 POKE 89, RT + 10 : POKE 88, 112 : GOSUB 5300
4957 POKE 89, RT + 11 : POKE 88, 96 : GOSUB 5100
4958 POKE 89, RT + 12 : POKE 88, 80 : GOSUB 5200
4960 POKE 89, RT + 13 : POKE 88, 64 : GOSUB 5400
4965 POKE 89, RT + 14 : POKE 88, 48 : GOSUB 5500
4970 DL = PEEK(560) + 256 * PEEK(561) : DL4 = DL + 4 : DL5 = DL + 5
4980 POKE DL5, RT + 1 : POKE DL4, 136 : POKE 559, 34
4990 RETURN
5100 PLOT 0, 0 : PLOT 29, 0 : DRAWTO 39, 0 : PLOT 0, 1 : PLOT 1, 1 : PLOT 30, 1 : DRAWTO 39, 1 : PLOT 0, 2 : DRAWTO 2, 2 : PLOT 31, 2 : DRAWTO 39, 2 : PLOT 0, 3 : DRAWTO 3, 3 : PLOT 32, 3
5105 DRAWTO 39, 3
5110 PLOT 0, 4 : DRAWTO 6, 4 : PLOT 34, 4 : DRAWTO 39, 4 : PLOT 0, 5 : DRAWTO 7, 5 : PLOT 32, 5 : DRAWTO 39, 5 : PLOT 0, 6 : DRAWTO 8, 6 : PLOT 31, 6 : DRAWTO 39, 6 : PLOT 0, 7 : DRAWTO 7, 7
5120 PLOT 32, 7 : DRAWTO 39, 7 : PLOT 0, 8 : DRAWTO 5, 8 : PLOT 34, 8 : DRAWTO 39, 8 : PLOT 0, 9 : DRAWTO 4, 9 : PLOT 35, 9 : DRAWTO 39, 9 : PLOT 0, 10 : DRAWTO 5, 10 : PLOT 34, 10 : DRAWTO 39, 10
5130 PLOT 0, 11 : DRAWTO 7, 11 : PLOT 32, 11 : DRAWTO 39, 11 : PLOT 0, 12 : DRAWTO 8, 12 : PLOT 31, 12 : DRAWTO 39, 12 : PLOT 0, 13 : DRAWTO 7, 13 : PLOT 32, 13 : DRAWTO 39, 13
5140 PLOT 0, 14 : DRAWTO 5, 14 : PLOT 34, 14 : DRAWTO 39, 14 : PLOT 0, 15 : DRAWTO 4, 15 : PLOT 34, 15 : DRAWTO 39, 15 : PLOT 0, 16 : DRAWTO 5, 16 : PLOT 34, 16 : DRAWTO 39, 16
5150 PLOT 0, 17 : DRAWTO 7, 17 : PLOT 32, 17 : DRAWTO 39, 17 : PLOT 0, 18 : DRAWTO 8, 18 : PLOT 31, 18 : DRAWTO 39, 18 : PLOT 0, 19 : DRAWTO 7, 19 : PLOT 32, 19 : DRAWTO 39, 19
5160 PLOT 0, 20 : DRAWTO 5, 20 : PLOT 34, 20 : DRAWTO 39, 20 : PLOT 0, 21 : DRAWTO 4, 21 : PLOT 35, 21 : DRAWTO 39, 21 : PLOT 0, 22 : DRAWTO 5, 22 : PLOT 34, 22 : DRAWTO 39, 22
5170 PLOT 0, 23 : DRAWTO 7, 23 : PLOT 32, 23 : DRAWTO 39, 23
5180 RETURN
5200 PLOT 12, 23 : DRAWTO 16, 19 : DRAWTO 16, 8 : DRAWTO 8, 0 : DRAWTO 0, 0 : POSITION 0, 23 : XI0 18, #6, 0, 0, "S :" : PLOT 39, 19 : DRAWTO 39, 8 : DRAWTO 23, 8
5210 POSITION 23, 19 : XI0 18, #6, 0, 0, "S :"
5220 X = 31 : FOR Y = 0 TO Y : PLOT X, Y : DRAWTO 39, Y : X = X - 1 : NEXT Y
5230 X = 24 : FOR Y = 20 TO 23 : PLOT X, Y : DRAWTO 39, Y : X = X + 1 : NEXT Y
5240 RETURN
5300 PLOT 17, 23 : DRAWTO 7, 12 : DRAWTO 18, 12 : DRAWTO 22, 8 : DRAWTO 20, 8 : DRAWTO 12, 0 : DRAWTO 0, 0 : POSITION 0, 23 : XIO 18, #6, 0, 0, "S :"
5310 X = 27 : FOR Y = 0 TO 7 : PLOT X, Y : DRAWTO 39, Y : X = X + 1 : NEXT Y
5320 X = 29 : FOR Y = 8 TO 13 : PLOT X, Y : DRAWTO 39, Y : X = X - 1 : NEXT Y
5330 X = 33 : FOR Y = 14 TO 23 : PLOT X, Y : DRAWTO 39, Y : X = X - 1 : NEXT Y
5340 RETURN
5400 PLOT 11, 23 : DRAWTO 11, 13 : DRAWTO 3, 13 : DRAWTO 3, 8 : DRAWTO 16, 0 : DRAWTO 0, 0 : POSITION 0, 23 : XI0 18, #6, 0, 0, "S :"
5410 X = 24 : FOR Y = 0 TO 10 : PLOT X, Y : DRAWTO 39, Y : X = X + 1 : NEXT Y
5420 PLOT 34, 11 : DRAWTO 39, 11 : PLOT 34, 12 : DRAWTO 39, 12
5430 X = 27 : FOR Y = 13 TO 23 : PLOT X, Y : DRAWTO 39, Y : NEXT Y : PLOT 0, 23 : DRAWTO 39, 23
5440 COLOR 3 : PLOT 18, 22 : DRAWTO 20, 22 : PLOT 17, 22 : DRAWTO 20, 22
5450 RETURN
5500 COLOR 1 : FOR Y = 0 TO 23 : PLOT 0, Y : DRAWTO 39, Y : NEXT Y : RETURN

Return to Table of Contents | Previous Section | Next Section