When the first huge computers were built, games were not what the owners had in mind. Millions of dollars were invested in every machine. Computer time was valuable, and not to be wasted.
As computers shrank in size and increased in power, however, it was inevitable that weary programmers would begin exploring and programming, devising the forerunners of Pac-Man and Donkey Kong. Today, a vast number of the world’s computers are built for one purpose only – to play games with whoever puts in a quarter.
Your Atari is not a dedicated game machine – it is much more versatile than that. But the Atari’s designers knew that one of the most common uses of the machine would be play. Like the arcade machines, the Atari can give you experiences and entertainment that you could never find anywhere except in the worlds the computer can create.
This book serves a double purpose. First, it provides you with a variety of games which you merely type into the computer, save on tape or diskette, and then play again and again, as often as you like. Second, because the program is printed you can see exactly how the game’s creator brought off the effects you like. It will be fairly easy for you to learn techniques that you can use in your own programs.
In fact, to make this book as useful as possible, many of the games are accompanied by explanations of how the program works. Chapters at the beginning and end of the book will also help you learn how to write your own games.
Much of the value of this book comes from its variety:
Besides being fun, MathMan and Word Hunt, for instance, are educational; Ski! can improve eye-hand coordination.
There are games that are simple and slow enough for small children. There are also games as fast and challenging as anything in the arcades.
No matter what level of programming skill you have reached, there will be programs for which you can learn techniques, ranging from fairly simple BASIC games to sophisticated all-machine language games like Shoot and Chiseler.
Even if you are a subscriber to COMPUTE! Magazine, there are things here you haven’t seen before. One-third of the games in this book have never been published before and some of the others have been since refined and improved.
Some of the games here were originally programmed on other computers, and were “translated” for the Atari. Computer translation often requires as much creativity as the original program, since the requirements and features of computers can be very different.
Some games require more than simple translation: they require new coding in order to take advantage of the capabilities of the Atari. This is the case with three games in this book. Charles Brannon, of our editorial staff, has rewritten Tag, Ski! and Thunderbird for the Atari. In addition, E.H. Foerster has made important improvements to Brannon’s version of Ski!.
Since the first printing of this book, Atari has introduced a new line of computers called the XL series. They’ve become very popular. We’ve ensured that all the games, save one, will run on any of the XL machines. That game, Ski, would have to be almost completely rewritten to run on an XL model computer. You can, however, play Ski on your 600 XL or 800 XL if you have the Atari BASIC cartridge. Simply plug it into the cartridge slot, type the program in, and play. Since the cartridge disables the built-in BASIC of the XL model computers, Ski will work.
All the rest of the games in this book can be typed in and played as is on an Atari XL computer.
When you push the cartridge into the slot, unbelievable things happen. Basketball players dribble and pass and shoot and steal. Spaceships go through complex maneuvers and blast asteroids out of the sky. Robots chase you through a maze. A little man climbs a ladder and puts out fires. Your computer has turned your TV screen into a universe of dazzling worlds, and it seems like whenever you aren’t playing, your children or your parents are.
But you bought a computer, not just a game machine. And you bought an Atari, not just a computer. Which means that all the techniques that the wizard programmers used to create the games you like to play are all within your reach.
It probably won’t surprise you that game designers like the Atari, too. That’s because the computer was designed with many of the features that help programmers make their games run smoothly, with lots of graphic effects, and without a lot of extra, unnecessary programming steps.
At their simplest level, computers consist of two basic parts, the central processing unit that performs operations, and the memory that holds all the instructions and data and results of those operations. The power of the computer is that it’s very, very fast. The weakness is that it can still do only one thing at a time.
But there are ways of getting around that. The Atari computer saves a lot of time by actually having two processors: the 6502 handles the main business of whatever program is running, and the other, the ANTIC chip, handles what’s going on on the TV screen. Once the main processor has told the ANTIC what to do, it can pretty well forget the screen and let the ANTIC go on telling the TV, every sixtieth of a second, what to put on the screen.
The Atari also has a sound system with four voices that plays through your TV speakers or your stereo system. There’s a little speaker built into your console, too, that can be made to beep and click. And if you have a cassette or disk drive for permanent memory storage, the Atari has several ways of storing and reading information on both devices, some fast and complicated, some slow and simple.
That’s the machinery, the hardware. Many of the most powerful features of your Atari as a game machine, however, are hidden in the computer’s operating system and in its BASIC language. It isn’t just the things that your computer can do – it’s also the way you can get the computer to do them. It isn’t quite as easy as wishing – this is the real world, after all. But with planning and a little study, you’ll find that all those dazzling tricks the wizard programmers use aren’t so miraculous after all. Or maybe that’s the wrong way of looking at it. Maybe the tricks are miraculous – but the Atari makes it relatively easy for you to become a wizard.
To understand how these features work, it’s important to understand how the Atari’s memory is set up. Perhaps it’s easiest to visualize computer memory as a long chain. The first link in the chain is memory location zero; the highest-numbered link your computer can read is location 65535.
Each link, or location, can hold one item of information. Your computer knows how to go from location to location and either read the item stored there or store a new item there. Whenever it stores something, it erases whatever was stored there before. However, when it reads something, the information at that location is unharmed – it can be read again and again without change.
What is stored at each location? The same thing every time: a number from 0 to 255. That’s all – a long chain of memory locations, each holding a number from 0 to 255. What matters, then, is what the computer does with that information.
It can interpret each number three ways:
Sometimes the computer reads those numbers as instructions, machine language commands that tell the 6502 processor what operations to perform.
Sometimes the computer reads the numbers as numbers, positive integers from 0 to 255 – or as positive and negative integers from -128 to +127.
And sometimes the computer reads the numbers as addresses – numbers which tell the computer where in memory another instruction or item of information is to be found.
How a number is interpreted depends on what you have told the computer to do with that information.
Of great importance to arcade-type games is a long section of the memory chain that is used for screen memory. The Operating System (OS) tells ANTIC to look for screen memory starting at a certain address in memory. Then ANTIC interprets that screen memory according to certain predetermined patterns, called graphic modes.
Depending on the graphic mode your program is in, ANTIC will read screen memory as instructions to turn on or off little squares of color on the TV screen, or as instructions to display a certain character on the screen. When you type words on your computer, ANTIC doesn’t care what you’re saying. It only knows that at certain places in screen memory, the number stored in that location is the code for a certain letter.
So when alien invaders march back and forth across your screen, your 6502 is really just storing numbers in different memory locations, and ANTIC will make different patterns of color in different places on the screen.
Machine language is very fast when compared to BASIC. It can move large groups of numbers from one place to another in screen memory so quickly that it causes objects to move smoothly on the screen.
However, many computer users haven’t yet learned how to use machine language. Instead, most of us rely on BASIC, a language a little closer to English, which, while a program is RUNning, translates our commands so the 6502 can understand them. The trouble is, this translation takes time. Our BASIC program often can’t move numbers through screen memory quickly enough to make smooth movements on the screen.
Here is where your Atari really starts to shine. ANTIC doesn’t only look for screen memory – it can also look for another section of memory that holds up to five player shapes (or four player shapes and four narrower missile shapes), which can be moved across the screen, independent of what the rest of the screen memory is doing.
These player shapes can move much more quickly and with a lot less calculation, than shapes in regular screen memory. They also are displayed on the screen without affecting the screen memory that is supposed to be displayed in the same place. This is why in “Tank Duel” you will see the tanks move right over trees – when the tank passes, the tree is still there, undisturbed.
You can also tell the computer which overlapping objects should have priority – does your airplane shape go in front of the cloud, or behind it, when they occupy the same place on the screen?
Your computer also notices what players or missiles are overlapping on the screen. That’s how in Asteroids the game program notices whether you have crashed into a big rock or not, or whether another ship’s missile has collided with your ship. If it doesn’t matter, the program can ignore the collision; if it does matter, your program can go into its special effects routine and make an explosion.
The important thing to remember is that all of this activity is controlled by telling the 6502 what numbers to store in what locations. The Atari is designed so that you have almost complete control over all the numbers that matter. If you are working in machine language, you control all those numbers directly, but even in BASIC you can store numbers by using the POKE command, or read numbers by using the PEEK function. Some ways of moving the numbers around are faster than others. In these games, you’ll see as many different techniques as there are programmers. But in the end, all the programmers are just putting numbers somewhere in the chain.
The Atari’s power derives from the way it uses those numbers.
Do you want to change the color of some object on the screen? You have 128 different combinations of color and brightness available to you – and to change a color, you merely have to POKE one number into one memory location. You can change the background, for instance, with the command POKE 712,66.
How many different colors can you display at once? Using the simplest graphics modes, you can show four colors at the same time. Add the five possible players, each with its own color, and there can be nine colors snowing, each controlled by a single POKE. And the advanced graphics modes – 9, 10, and 11 – allow even more.
Your computer has four voices through the TV speaker. Four notes can sound at the same time – or two can be used together to make a combined sound. From BASIC, you can choose eight different distortion levels, 16 different loudness settings, and a wide range of pitches. Let’s explore a bit.
Here’s the sound of the sea:
10 FOR I=4 TO 14 STEP 2:SOUND 0,76-I,8,I:FOR X=0 TO 150*RND(1):NEXT X:NEXT I 20 FOR I=14 TO 4 STEP -1:SOUND 0,60,8,I:FOR X=0 TO RND(1)*800:NEXT X:NEXT I:GOTO 10 30 FOR I=12 TO 4 STEP -1:SOUND 0,60,8,I:FOR X=0 TO RND(1)*800:NEXT X:NEXT I:GOTO 20
And here’s the tick-tock of a clock:
5 FOR X=0 TO 1 10 SOUND 0, 50+10*X, 10, 8: SOUND 0,0,0,0 20 FOR I=0 TO 150:NEXT I 30 NEXT X:GOTO 5
Program 1-1 is a simple program that will allow you to create sounds and modify the pitch and distortion while the sound is going on. If you have two pairs of paddles, you can work with two sounds at once.
Paddles One and Two control the first voice. Paddle One sets the pitch of the sound. Hold down the button, and the voice goes on and off in a staccato pattern.
Paddle Two controls the distortion level. Hold down the button, and the screen will report, over and over, what the number of the pitch is and what the number of the distortion is for the sound you’re hearing.
If you find a sound you like, push the button, get the numbers, write them down, and then use them in a SOUND statement in a program. The SOUND statement looks like this:
SOUND 0,76,10,10
The first number is the voice number. The four voices are 0, 1, 2, and 3. The second number is the pitch number, ranging from 0 to 255. The third number is the distortion, which is always an even number from 0 to 14. The fourth number is the volume, any number from (silent) to 15 (loud).
You can reproduce the sound you want by putting the pitch and distortion number shown on the screen in the right place in a SOUND statement in your own program.
Machine language programmers can even make their music or sound effects take place during interrupt time, when the TV screen isn’t being actively displayed – but that’s much too fast for BASIC to take advantage of.
10 DIM PITCH(3),DISTORT(3),J(3):? "{CLEAR}" 20 ? "How many voices? (1, 2, 3, or 4)":OPEN #1,4,0,"K:" 30 GET #1,A:IF A<49 OR A>52 THEN 30 40 CLOSE #1:PRINT CHR$(A):A=A-49 50 ? "Paddles or Joysticks":OPEN #1,4,0,"K:" 60 GET #1,N:IF N<>74 AND N<>80 AND N<>106 AND N<>112 THEN 60 70 PRINT CHR$(N):CLOSE #1:ON N=74 OR N=106 GOTO 200 80 REM JOYSTICK-ONLY USERS MAY DELETE LINES 50 TO 190 100 FOR I=0 TO A:PITCH(I)=27+PEEK(624+I*2):DISTORT(I)=2*INT(PEEK(625+I*2)/29):NEXT I 110 FOR I=0 TO A:SOUND I,PITCH(I),DISTORT(I),8:NEXT I 120 FOR I=0 TO A:ON NOT PTRIG(I*2) GOSUB 150:ON NOT PTRIG(I*2+1) GOSUB 140:NEXT I 130 GOTO 100 140 POSITION 1,I+1:2 "Voice ";I,"pitch ";PITCH(I);" distortion ";DISTORT(I);" ":RETURN 150 SOUND I,0,0,0:RETURN 190 REM PADDLE-ONLY USERS MAY DELETE LINE 50 TO 70 AND 200 TO 290 200 FOR I=0 TO A:PITCH(I)=100:DISTORT(I)=10:SOUND I,PITCH(I),DISTORT(I),8:NEXT I 205 J(I)=J(I)-10:IF J(I)<0 OR J(I)>4 THEN J(I) =0 210 FOR I=0 TO A:J(I)=STICK(I):IF J(I)=7 THEN J(I)=12 220 J(I)=J(I)-10:IF J(I)<0 OR J(I)>4 THEN J(I)=0 230 ON J(I) GOSUB 240,250,260,270:ON NOT STRIG(I) GOSUB 290:NEXT I:ON PEEK(53279)=6 GOSUB 280:GOTO 210 240 DISTORT(I)=DISTORT(I)-2:DISTORT(I)=DISTORT(I)+14*(DISTORT(I)<0):SOUND I,PITCH(I),DISTORT(I),8:RETURN 250 DISTORT(I)=DISTORT(I)+2:DISTORT(I)=DISTORT(I)-14*(DISTORT(I)>14):SOUND I,PITCH(I),DISTORT(I),8:RETURN 260 PITCH(I)=PITCH(I)+1:PITCH(I)=PITCH(I)-256*(PITCH(I)>255):SOUND I,PITCH(I),DISTORT(I),8:RETURN 270 PITCH(I)=PITCH(I)-1:PITCH(I)=PITCH(I)+256*(PITCH(I)<0):SOUND I,PITCH(I),DISTORT(I),8:RETURN 280 POSITION 2,1:FOR I=0 TO A:? "Voice ";I;" Pitch ";PITCH(I);" Distortion ";DISTORT(I);" ":NEXT I:RETURN 290 SOUND I,PITCH(I),DISTORT(I),8:SOUND I,0,0,0:RETURN
One of the tricks the Atari can play is changing the meaning of numbers in the middle of a program. For instance, several of the programs in this book will have statements that look like this:
A$="hhh*VLd"
And then, later, a statement that looks like this:
X=USR(ADR(A$))
What the first statement does is store a group of numbers as a string of characters. Ordinarily, the computer would interpret those numbers from then on as the letters or symbols shown.
But the second statement tells the computer to go to the address where those letters are stored – ADR(A$) – and interpret those numbers as machine language instructions – X=USR. What looked like a string of characters is really a subroutine for loading data from a disk file, very, very quickly.
There are other ways to get short machine language routines into game programs. What is important is that it allows programmers to write most of a program in BASIC, the language most programmers know best – and only write machine language in the sections of the program that really require speed.
Some of the programs in this book are entirely in machine language. You can tell which ones they are – they’re the ones that consist almost entirely of lines like this:
DATA 15,233,0,55,99,5,23,120,120,0,0,0,40
Long, slow typing – but very fast games.
Most programs, though, are in BASIC, and even without a lot of training, you can follow most of what’s going on. And because of those embedded machine language subroutines, most of those BASIC games play just as fast as you could ever want.
There are other features we’ve hardly touched on:
FOR I=0 TO 10000:A=PEEK(53279):PRINT A:NEXT I
If you type in that line and then press those three buttons, one at a time or in combination, you will see what numbers the computer automatically stores, ready for you to read within a program.
All of these features were carefully built into the Atari – this computer was designed to be a powerful game machine.
But much of its value comes from the simple fact that it is a computer. Playing word games, doing mathematical calculations, designing mazes, remembering intricate patterns – these are all things that computers do very well. They were originally developed to do vast amounts of tedious work very quickly.
It’s just a bonus that they can be such a lot of fun.
Richard Mansfield, Senior Editor of COMPUTE! Publications, explains the details of a simple game. A beginning programmer can learn a great deal studying this short program.
If you are tempted to write your own games, go ahead. It’s a good way to learn to program. Games are basically the same as any other kind of programming.
Computer games fall into two broad categories: imitations of old standards (checkers, Othello), and games which could not be played without a computer (Space Invaders, Pac-Man). This second category is more difficult to program for several reasons. For one thing, you’ve got to think up a new and entertaining concept and then adjust the action until it is just hard enough to be challenging but not so difficult that people want to give up.
This category (basically “arcade” games) is especially hard to program precisely because a good computer-only game exploits all of the computer’s special attributes: speed, color, sound. To do this well, to make things look and respond just the way you imagine them, requires a good bit of programming experience. Usually, too, several things are happening at once in an arcade game. This often means that such a program must be written in machine language, which is far faster than BASIC.
Old standards, on the other hand, can often be the best way to get started programming games. You already know the game concept, and cards or dice or game boards are fairly easily constructed and manipulated on your computer screen. To illustrate, let’s take a look at a simple simulation of one of the oldest card games, High Card. The rules are simple: you place a bet, and then you draw a card from the deck. The computer, your opponent, draws a card too, and the highest card wins the money.
One simplification here is that there is no attempt to represent the cards on the screen. The entire game relies simply on words (“Ace of Spades,” for example) when cards are drawn.
Like most computer programs, the program can be visualized as having four distinct zones: initialization, main loop, subroutines, data tables. We can go through the steps in programming this game by looking at each zone separately.
From lines 10 through 80 we are “teaching” the computer some basics about this game. Initialization is the activity which must take place before any of the action can begin. Computers are so fast that they will zip up through these lines and start things off in the main loop at line 100 in a flash. However, as programmers, we are aware that several preliminary events took place inside before anything else.
In line 20, the computer discovers that there is a variable called “dollars” which is equal to 500. It sets aside a section (like a small box) in its memory which it labels “dollars.” When the game is running, it will add or subtract from this “box” (lines 230-240) to keep a running total of how much money you have left to bet. From time to time (line 110), it will check the box and report to the player how much he has. The box labelled “dollars” is called a variable because during the game the amount in it will vary.
Lines 30 through 60 are simple enough – they ask the player to give his or her name. The computer “memorizes” it in another “box” called “name$” and can now speak more personally to the player in lines 140 and 230. Also, the computer prints the rules of the game in line 60.
Line 70 “reads” four names (the face cards) from the data tables in lines 510 on. It also makes a “mental note” that it has already READ four items. So, when it’s asked to READ again (line 80), it will start with the next unread item of data, which will be “clubs.” By now, the computer has “memorized” a variety of important facts: the player’s name, the amount of his or her betting purse, the names of the face cards, and the suits of a standard deck. In less than a second, the computer has grasped and filed away the necessary facts to go on to the main loop where all the action takes place.
After checking that the player has money to bet, the computer asks for the bet, checks again that the bet is possible, and then runs through one cycle of the game starting in line 160. At this point, a programmer might find it worthwhile to visualize the steps involved in the game:
Since both draws are essentially identical actions (the only difference will be that we say “Bob draws a...” instead of “The computer draws”), we don’t need to program the draw twice. This is where subroutines come in handy.
Twice in the main loop, we GOSUB 300. First the player draws, then the computer draws. Line 310 randomly picks two numbers, the card and the suit. If line 320 finds that this selection matches the one drawn just before by the player, it goes back for another draw. Line 330 makes the name of the card be the number if it wasn’t a number higher than 10 (a face card).
Then line 340 announces the draw using three variables. The first variable (player$) is set up in either line 160 or 190 as appropriate. Then the card$ and suit$ variables are selected from the lists that were “memorized” back in the initialization phase (lines 70-80). The subroutine then RETURNS to the main loop.
Lines 210-240 decide and announce the winner of this round. First, if the variable “card” (the computer’s card) is greater than (>) “yourcard,” the computer is declared the winner in line 240, the purse is adjusted, and the main loop is restarted (GOTO 100). If the cards are equal, nothing happens to the purse and the next round begins. Notice that we don’t need to say “IF YOURCARD > CARD” at the start of line 230 to test if the player has won. It’s the only possible thing if the computer has gotten this far.
Once you’ve solved a particular problem, you’ll find you can use the solution in many future games. This subroutine which draws cards, for instance, would work just as well for poker, or blackjack, or dozens of other games. Subroutines are handy not only because they can be used repeatedly within a program, but because they can be saved and used repeatedly in future programs. So think up a simple, traditional game and teach it to your computer. There is probably no more pleasurable way to learn programming than to write a game.
10 REM *NECESSARY INITIAL INFORMATION* 20 DOLLARS=500:DIM NAME$(20),PLAYER$(20) 30 GRAPHICS 0:PRINT " WITH WHOM DO I HAVE THE PLEASURE" 40 PRINT " OF PLAYING HIGH CARD SLICE?" 50 INPUT NAME$ 60 PRINT " HIGH CARD WINS IN THIS GAME!" 70 DIM CARD$(14*5),T$(10):FOR I=11 TO 14:READ T$:CARD$(I*5-4,I*5)=T$:NEXT I 80 DIM SUIT$(8*4):FOR I=1 TO 4:READ T$:SUIT$(I*8-7,I*8)=T$:NEXT I 90 REM 100 REM **MAIN PROGRAM LOOP** 110 PRINT :PRINT " YOU HAVE $";DOLLARS 120 IF DOLLARS<=0 THEN PRINT " THE GAME IS OVER. YOU ARE OUT OF CASH.":END 130 PRINT " WHAT IS YOUR BET";:INPUT BET 140 IF DOLLARS<BET THEN PRINT " YOU ONLY HAVE $";DOLLARS;" TO BET",NAME$:GOTO 130 150 YOURCARD=0:YURSUIT=0 160 PLAYER$=NAME$ 170 GOSUB 300 180 YOURCARD=CARD:YURSUIT=SUIT 190 PLAYER$="THE COMPUTER" 200 GOSUB 300 210 IF CARD>YOURCARD THEN GOTO 240 220 IF CARD=YOURCARD THEN PRINT " A TIE!":GOTO 100 230 PRINT NAME$;" WINS":DOLLARS=DOLLARS+BET:GOTO 100 240 PRINT " THE COMPUTER WINS":DOLLARS=DOLLARS-BET:GOTO 100 290 REM 300 REM *SUBROUTINE TO DRAW THE CARDS* 310 CARD=INT(RND(0)*13)+2:SUIT=INT(RND(0)*4)+1 320 IF CARD=YOURCARD AND SUIT=YURSUIT THEN 300:REM NO IDENTICAL DRAWS 330 IF CARD<11 THEN T$=STR$(CARD):GOTO 340 335 T$=CARD$(CARD*5-4,CARD*5) 340 PRINT " ";PLAYER$;" DRAWS THE ":PRINT " ";T$;" OF ";SUIT$(8*SUIT-7,SUIT*8):PRINT 350 RETURN 490 REM 500 REM **DATA TABLE** 510 DATA JACK ,QUEEN,KING , ACE 520 DATA CLUBS ,DIAMONDS,HEARTS , SPADES
“Mastermaze,” an extremely challenging game, uses page flipping and machine language to create up to 32 levels. This revised version of Mastermaze will create 27 mazes in less than one minute.
Almost everyone finds mazes an enjoyable challenge. If you are like me, however, you feel that mazes take only minutes to solve and can soon become monotonous. That is why I chose to use my personal computer to its fullest, having it perform functions impractical with paper and pencil. This three-dimensional maze game is the result.
First, let me explain how to use the program. Since it is impractical and nearly impossible to display an entire three-dimensional maze at one time, the program displays only the level that the player is on, which is really of no consequence to the user, but makes life a lot easier for the programmer. What we are doing is analogous to a book: instead of showing the entire book in one screen, we are displaying only one page at a time — the page that is being read.
After you have typed in the entire program, the first thing you must do is SAVE a copy to tape or disk. This program plays around with the display list, so typos could cause problems and possibly crash your computer.
Once a copy has been SAVEd, type RUN and you will be prompted with the question “# OF LEVELS?” What the computer really wants to know is how deep you would like your maze to be. In other words, the computer wants you to tell it one more than the minimum number of down “tunnels” the user must pass through before he reaches the end. In terms of our book analogy, the computer is asking for the number of pages in the book.
For a first-time player, I suggest three or four levels at most. The minimum number of levels is one, and the maximum, for computers with 48K, is 32. The maximum number of levels will be less on computers with DOS present or less memory.
Once you have entered your desired number of levels, the program will ask “INVISIBLE (1) OR VISIBLE (2)?” If you try invisibility, beware. Although the screen appears to be blank, the walls to the maze are still there.
Now that the program has the necessary data, the computer begins to build the maze to your specifications. Before work actually begins, the screen informs you of the work to be done. After this short delay, the screen is turned off and the maze is constructed. The actual time needed to construct the mazes is relatively fast thanks to a machine language routine written by David Butler.
Once the computer has completed construction of the maze, the screen is turned back on, and you are asked to PRESS START TO BEGIN. Watch the word START closely. See how it is flashing on and off? This effect is produced by toggling CHACT (location 755 or hex 2F3) in rapid succession (alternately POKEing in one and two). You are asked to press START when you are ready because the program times you, and it would not be fair to start timing from the moment the maze was completed.
Therefore, when you are ready to begin, you press START, which tells the program that you are poised with joystick in hand; the top level is displayed and timing begins. You will see an S in the upper left corner of the screen, with the ball character (control-T) underneath. You are the ball character.
Just move the joystick in the direction you want to go. “Sure,” you say, “but where do I want to go?” Simple enough. If you chose a one-level maze (chicken), you will see an F at the lower right corner of the maze. That’s where you want to go. If you were gutsy, however, and chose any number of levels greater than one, you will see five graphics “+” characters at random points throughout the top level. These symbols represent tunnels, through which you must pass to reach the finish (which is always in the lower right of the bottom level of the maze). As you might have guessed, you always start at the upper left of the top level.
To pass through a tunnel, simply move onto the “+” symbol and press the fire button. Voila! The new level is displayed instantly. Have you gone up or down? Well, if you were on the top level, the only place you could go is down. If you are in the middle of a maze of four or more levels, then I have absolutely no idea which direction you’ll go; you may pass through the same level three or four times before you realize that you’ve gone nowhere.
In mazes of ten or more levels, be prepared to see the same level a few times before you make any progress. No matter how many levels you choose, however, the goal is still the same. You must try to go down to unexplored levels; if you end up on a level you have been on already, you have looped, and you must figure out whether you’ve gone up or down.
In any case, find the F on the lowest level, go to the space directly above it, and move down. If you do not push the joystick down, the timer will continue, and your record time will be lost. When the timer has stopped, you will hear five beeps.
If you do not hear the five beeps, you have not stopped the timer, or the sound is gone on your machine. Either way, just remember to go down when you reach the finish — as you get better and better, times will get tougher and tougher to beat, and each second will become important.
That’s all there is to it. After the five beeps have informed you that the timer has stopped, the screen will become visible (no change for visible mazers), and the time used to complete the maze will be displayed in hours: minutes: seconds format. The program will loop until you press the START button again, which will cause the program to re-RUN.
There are a few caveats, however. First, if you are attempting an invisible maze, some joystick directions may not work. There is nothing wrong with the program; if you cannot move in a certain direction, you have hit a wall (I told you they were still there). Second, don’t even try to do deep invisible mazes without the consent of your psychologist. Third, each tunnel can be used only once, so make your moves wisely.
Last, and most important, don’t ever remove lines 14 and 15. This program, as mentioned earlier, will cause the computer to do some strange things if you hit the BREAK key. Lines 14 and 15 turn off the BREAK key; the only way to get out of the program is to hit the SYSTEM RESET button.
Now let’s look at how the program accomplishes what it does. Line 8 is self-explanatory. Line 10 resets the screen and sets the variable TOP to the address of the LSB of the screen memory address. By POKEing different numbers into TOP and TOP+1, we can display any area of memory. Line 12 stores the value of SAVMSC (locations 88 and 89, 58 and 59 hex) into RL and RH, respectively. This step is necessary to reset the destination of PRINT statements after these locations have been modified by the maze generator routine.
Lines 20 and 23 obtain the required data from the user and determine the value of BOT, the page number of the lowest memory address to be used. Line 25 makes sure that we haven’t used up all available memory, and informs the user of any memory conflict. Line 26 lets the user know that the delay which will follow is intentional, not something gone wrong with the program. Line 27 loads the machine language maze generator program from the DATA statements (lines 1000-1070) into free RAM at page six. The routine, written by David H. Butler, is a modification of Charles Bond’s original maze generator in BASIC.
Line 28 turns off the screen and sets up the display for the start of the game. Line 29 clears memory using the CLEAR key. Line 30 establishes the top of maze memory and sets up a loop to construct each of the MAXLEV levels of the maze. Lines 60-80 set up the screen and call the maze generator routine.
Line 120 restores the PRINT statement destination to its original value by POKEing RL and RH back into SAVMSC. Line 130 establishes the S in the upper left and the F in the lower right of the maze. Line 135 checks to see if any tunnels have to be built; in other words, if the maze is only one level, jump over the tunnel building routine (lines 140-170).
The tail end of line 170 restores the screen and sets up the console switches for reading. Line 172 executes a GOSUB to the routine that randomly sets the color of the background at the beginning and also each time the user passes through a tunnel. Line 173 loops indefinitely until the user presses the START button. This line is the one that toggles CHACT, as described earlier.
Line 174 makes the maze visible or invisible, based on your response to the second prompt at the beginning of the program. Line 175 resets the three-byte timer RTCLOK to zero. Line 180 determines the start position for the player and tells the display list where the first level of the maze is. Lines 185-321 are the main loop and should be self-explanatory.
A few notes, though: Line 190 reads the joystick and the trigger, lines 200-230 perform routine motion, line 235 checks for a win, line 240 checks for walls, and lines 300-321 change levels. Lines 400-415 stop the timer, sound the bell, and display the time used. Line 420 sets up the console switches for reading and POKEs a 124 into the attract mode flag ATRACT (location 77, hex 4D). The 124 in ATRACT gives the user approximately 16 seconds before the screen goes into attract mode.
Line 430 loops until the START button is pressed. Line 450 is the string A$ (we can’t PRINT it because we’ve changed the screen memory locations). Don’t forget to put the quotation marks towards the end of the line; doing that fools BASIC into reading trailing blanks to fill up A$. Finally, line 500 reads a random number from the random number generator RANDOM (location 53770, D20A hex), masks out the four low-order bits, and uses it to set the background color. If you’re interested in the technical aspects of the game, read on. If not, RUN the program and have some fun.
The programming tool behind the entire program is called page flipping. What this technique involves is changing the address that the ANTIC chip reads to determine the start of screen memory. This address is always in the display list, which is pointed to by SDLSTL and SDLSTH (locations 560 and 561, hex 230 and 231) in standard LSB, MSB order.
In the display list you will find all sorts of numbers; all have a meaning and should not be tampered with by the inexperienced programmer. In different graphics modes, the display list changes both in length and location.
In general, the display list follows two rules. First, all graphics modes accessible through BASIC have display lists that start with 112, 112, 112 in three successive bytes. These three bytes tell the ANTIC that there are to be 24 blank lines on the television screen.
Second, the fourth location of the display list contains a byte which has its sixth bit set. The rest of the byte varies depending on the graphics mode, but bit six is always set. Bit six, when set, tells the ANTIC chip that it is to begin direct memory access (DMA) at the location pointed to by the next two bytes. Therefore, any area in memory can be displayed by POKEing the address (LSB, MSB) into the location pointed to by SDLSTL and SDLSTH plus four.
This is the basis of this program. All screens are constructed before play begins, and, instead of drawing an entirely new screen, all the program does is change these addresses to point to the first byte of the new screen.
During the blank-out period at the start of the program, the entire maze is constructed, layer by layer, and the resulting mazes are stored in IK decrements, starting with the last free kilobyte memory block before the display list. The maze generator routine does not even need to be modified for this purpose; all that was done was to change the PRINT destination pointer SAVMSC (location 88, hex 58, mentioned earlier). In other words, all I did was fool the maze generator routine into thinking that screen memory was located in middle area RAM (instead of the top), and since 960 bytes are needed for the standard GRAPHICS screen, IK blocks were very convenient.
The tunnels used this information both at construction time and at level-changing time. Random numbers were all that was necessary to build the tunnels; checks were required only to make sure that the tunnels would be within the maze and that they did not cut through maze walls. Since no other checks are made, it is possible to have many tunnels packed closely together.
The simple method of checking upward and downward movement causes tunnels to be disabled as they are used. When the player changes levels, a control-T character is left where the graphics plus symbol was previously As a result, the checks for the graphics plus symbols will always fail on an already-used tunnel. This feature, added only to make the mazes more challenging, can easily be altered by changing the GOTO 185 in line 250 to GOTO 190.
This simple change makes the program think that you have just moved across or down (i.e., you have not changed levels). Therefore, the program replaces the previous space with the variable T, which contains the screen memory value of the space you were on before. When you move, the control-T is moved in the proper direction, and T is POKEd into the space you just moved from. It is confusing, but it works, and it works fast.
The tunnels, when used, merely change the value of the sixth byte of the display list. Since IK memory blocks are used, it is not necessary to change the fifth, LSB of the display list DMA address; it will always be zero. Either the sixth byte is added to four, or four is subtracted from it. The reason for this change should be evident — four pages constitute one kilobyte of memory.
Locating the mazes in this fashion greatly simplifies all checks. Instead of going through a series of different LSB, MSB checks to determine the location (two-dimensionally) of a space on two different levels, all that is required is a PEEK to the address plus 1024 (IK) and the address minus 1024. Again, this is how tunnel checking is done in lines 305 and 310.
Last, let’s look at the timer. From the time the computer is powered up until the time it is powered down, the OS, as part of its stage one VBLANK (vertical blank) routine, increments the three-byte jiffy counter RTCLOK. RTCLOK is located in three consecutive bytes starting at address 18 decimal, 12 hex.
Unlike most of the system numbers, this clock is stored in MSB first, LSB last order. Since vertical blanks occur once every sixtieth of a second, this timer counts “jiffies” (sixtieths of a second). When the game start is pressed, zeros are POKEd into the clock addresses (line 175). As soon as the player has completed the maze, the locations are read and stored in the variable ET (for elapsed time). Simple mathematical manipulations derive the hours, minutes, and seconds and store them in the variables EH, EM, and ES, respectively.
That’s all there is to it. Since we know that we started at zero, no other manipulations are needed. (Incidentally, it is possible to stop the clock, but doing so requires a shutdown of the entire system VBLANK routine, which can have disastrous effects on your program.)
1 REM ****MASTERMAZE**** 2 REM **Mazing in Three* 3 REM ****Dimensions**** 8 DIM A$(37):SW=0 10 GRAPHICS 0:TOP=PEEK(560)+256*PEEK(561)+4 12 RL=PEEK(88):RH=PEEK(89) 14 O=PEEK(16)-128:IF O<0 THEN O=O+128 15 POKE 16,O:POKE 53774,O 20 ? :? "# OF LEVELS";:INPUT MAXLEV:MA XLEV=MAXLEV−1:? "INVISIBLE (1) OR VISI BLE (2)";:IF MAXLEV<0 THEN MAXLEV=0 23 BOT=INT(TOP/256)−MAXLEV*4−4:INPUT I NV 25 IF BOT*256<PEEK(144)+256*PEEK(145) THEN ? "***INSUFFICIENT MEMORY***":GOT O 20 26 POKE 752,1:? ".":POSITION 4,10:? "C ONSTRUCTING MAZE...WAIT FOR START" 27 RESTORE 1000:FOR I=1536 TO 1690:REA D A:POKE I,A:NEXT I:POKE 755,1 28 POKE 559,0:? ".":POSITION 10,11:? " PRESS START TO BEGIN" 29 TM=PEEK(106):POKE 106,TM−6:POKE 88, 0:POKE 89,BOT:? ".":POKE 106,TM 30 R1=BOT+MAXLEV*4:FOR X=BOT TO R1 STE P 4:POKE 77,0:POKE 88,0:POKE 89,X 40 REM MAZE GENERATOR ROUTINE BY C. BO ND 60 SC=PEEK(88)+256*PEEK(89):A=SC+43 65 POSITION 2,0:POKE 752,1:FOR I=1 TO 23:? " ":NEXT I 70 POKE A,5 80 G=USR(1536,1675,A):GOSUB 500 120 NEXT X:POKE 88,RL:POKE 89,RH 130 POKE BOT*256+917,38:POKE R1*256+3, 51 135 IF MAXLEV=0 THEN POKE 559,34:POKE 53279,8:GOTO 172 140 FOR X=BOT TO R1−4 STEP 4:FOR Y=1 T O 5 150 J=INT(RND(0)*876)+43 151 W=J−(INT(J/40)*40):IF W<3 OR W=39 THEN 150 155 IF PEEK(X*256+J)=0 AND PEEK(X*256+ 1024+J)=0 THEN POKE X*256+J,83:POKE X* 256+1024+J,83:GOTO 170 160 GOTO 150 170 NEXT Y:NEXT X:POKE 559,34:POKE 532 79,8 172 GOSUB 500 173 IF PEEK(53279)<>6 THEN POKE 755,−P EEK(755)+3:GOTO 173 174 POKE 755,INV 175 POKE 18,0:POKE 19,0:POKE 20,0 180 ST=R1*256+43:WIN=BOT*256+960:POKE TOP,0:POKE TOP+1,R1 185 S=PEEK(ST):T=ST:POKE ST,84 190 Q=STICK(0):R=STRIG(0):IF R=0 AND S =83 THEN 300 200 IF Q=7 THEN ST=ST+1 210 IF Q=11 THEN ST=ST-1 220 IF Q=14 THEN ST=ST-40 230 IF Q=13 THEN ST=ST+40 235 IF PEEK(ST)=38 THEN 400 240 IF PEEK(ST)=128 OR PEEK(ST)=51 THE N ST=T 250 IF ST<>T THEN SW=0:POKE T,S:POKE 7 7,0:GOTO 185 251 GOTO 190 300 IF SW=1 THEN 190 305 IF PEEK(ST+1024)=83 THEN R1=R1+4:S T=ST+1024:GOTO 320 310 IF PEEK(ST−1024)=83 THEN R1=R1−4:S T=ST−1024 320 IF R1<BOT OR R1>MAXLEV*4+BOT THEN 330 321 POKE TOP+1,R1:SW=1:GOSUB 500:GOTO 185 330 A=USR(58484) 400 ET=PEEK(18)*65536+PEEK(19)*256+PEE K(20):EH=INT(ET/216000):EM=INT((ET−EH* 216000)/3600) 401 FOR X=1 TO 5:FOR Y=15 TO 0 STEP −0 .2:SOUND 0,9,10,Y:NEXT Y:NEXT X:POKE 7 55,2 402 ES=INT((ET-EH*216000-EM*3600)/60) 403 ? ".":? :? "445 DATA ELAPSED TIME: ";EH;":";EM;":";ES;" :" 404 ? "CONT":POSITION 0,0:POKE 842,13: STOP 405 POKE 842,12 406 POSITION 2,15:RESTORE :FOR Y=0 TO 1 410 READ A$:FOR X=BOT*256+Y*40 TO BOT* 256+Y*40+LEN(A$)−1:POKE X+2,ASC(A$(X−B OT*256+1−Y*40,X−BOT*256+1−Y*40))−32 415 NEXT X:NEXT Y 420 POKE 53279,8:POKE 77,124 430 IF PEEK(53279)<>6 THEN 430 440 RUN 450 DATA PRESS START FOR ANOTHER MAZE " 500 AA=PEEK(53770):AB=AA−(INT(AA/16)*1 6):SETCOLOR 2,AB,4:POKE 712,PEEK(710): RETURN 1000 DATA 104,104,133,208,104,133,207, 104,133,204,104,133,203,173,10,210,41, 3,133,212 1010 DATA 133,213,24,10,168,165,203,11 3,207,133,205,165,204,200,113,207,133, 206,160,0 1020 DATA 177,205,201,128,208,40,165,2 12,24,105,1,145,205,105,3,10,168,165,2 03,113 1030 DATA 207,133,203,200,165,204,113, 207,133,204,169,0,168,145,203,165,205, 133,203,165 1040 DATA 206,133,204,24,144,183,230,2 12,165,212,41,3,133,212,197,213,208,18 0,160,0 1050 DATA 177,203,133,212,152,145,203, 169,251,24,101,212,176,24,198,212,165, 212,24,10 1060 DATA 168,56,165,203,241,207,133,2 03,200,165,204,241,207,133,204,24,144, 131,96,2 1070 DATA 0,176,255,254,255,80,0,1,0,2 16,255,255,255,40,0
Presented here is a two-player game in graphics mode 1 — with a total of ten colors on the screen at once.
When playing real-life tag with only two players, nobody really wins because the number of tags per player remains constant. But in computer Tag, the clock decides who will be the champion. Every 15 seconds, if the person who is It cannot tag the other, the computer will reverse the It player. This feature allows a real fight for points. If you are not skilled in attacking, you can become skilled in evasive tactics and win the game.
Plug a joystick into jacks one and two, and get ready for some furious chasing and desperate dodging. After the game initializes, each player can type in his initials (three letters). You then select the final score (what you play to) from 1-10. Press OPTION to increase the final score, and SELECT when the desired number appears. The game will begin with player one in the upper left-hand corner, and player two in the opposite corner. Player one will be flashing, which indicates that he is It.
Play consists of It trying to catch the “victim” as fast as possible, while the “victim” tries to evade It for at least 15 seconds. Both players must maneuver about the screen, turning and twisting among a maze of pink rocks. But if you dally too long, the rocks will wake up, open their eyes, and further confound the conflict. Don’t let one of the Living Rocks touch you.
Tag uses character graphics in graphics mode one, but with a twist. Usually, if you want a redefined character set along with letters and numbers, you are limited to redefining punctuation and other special symbols and have to wait 10 to 15 seconds for a POKE loop that downloads the ROM character set to RAM.
Tag, however, uses a Display List Interrupt (DLI) to “flip” the character set midway down the screen. This lets you use the upper portion of the display for normal text (using the entire character set), and the lower portion for as few or as many custom characters as desired. The DLI used in TAG also changes the screen colors, so you get five colors in each portion, for a total of ten simultaneous colors.
Another interrupt-driven machine language routine in Tag uses Count-Down Timer 2 to “flip” the character set pointer every 16/60 of a second. In Tag, there are two character sets. The first character set, for example, displays one view of a running person. The other character set, at an offset of 512 bytes, displays another view.
When the CHBASE pointer is switched between the two views, the character appears to be running. Character set flipping can also be used to represent blinking, flashing, spinning, bouncing, or any other simple motion. And, since the flipping is controlled by machine language, the motion is fast and regular. It also simplifies the BASIC program.
This game offers a different twist to maze puzzles; you can see only a very small section of the maze at a time.
Mazes present a challenge different from arcade-type “shootout” games, but the appeal of a maze can quickly fade once it has been solved. I have enhanced the challenge by hiding the complete maze from the player and showing only a realistically limited view from any position inside it. Although the view is from above rather than ground level, the player still gets a claustrophobic feeling similar to that of actually being inside the maze and groping along the corridors.
The objective is simply to find a way out of the maze in the least amount of time. You start at the center of the maze with only your player character visible. As you move through the passages, the walls around your player become visible, and the maze unfolds.
Use the joystick to move your ebullient little character around the maze, your goal being the upper-left-hand corner of the screen. The challenge is in how long it takes you to get there. You can take a “cheat peek” of the entire maze by pressing the fire button. This will display the maze for about three seconds, then turn to black and delay your movement for another three seconds as a penalty. If you want a really good score, don’t use it!
We can construct the maze directly on the screen (GRAPHICS 1 is used here, with custom characters for the walls and player). We make it invisible by setting its color equal to the background color (done here with SETCOLOR 2,0,0).
Then, to open up the maze, we just have to PEEK (into screen memory) the eight characters surrounding the player character, and if the PEEKed character is an “invisible wall,” replace it with a visible wall.
Scoring is provided with RTCLOCK, Atari’s realtime clock, which is found at location 18, 19, and 20. These are used in the opposite of the normal LSB/MSB order. Chaining all three locations together will give the current “jiffy time” since the machine was turned on, measured in sixtieths of a second:
JIFFY=PEEK(20)+PEEK(19)*256+PEEK(18)*65536
Since location 18 only ticks every once in a long while, you can leave it out for most measurements. Dividing the jiffy time by 60 gives you the time in seconds:
SEC=(PEEK(20)+256*PEEK(19))/60
The ability to add timing to your programs will enhance them. Many games would lose their challenge without the time element. Try experimenting with locations 18, 19, and 20. Experimenting is an excellent way to learn more about your computer’s capabilities.
“Blockade” is an exciting two-player game that also demonstrates a simple joystick routine.
Surround (or Blockade) was a popular arcade game in the early days of video games. The format of the game is not complex, but it is still enjoyable and challenging. The object of the game is to build walls to trap the opposing player and force him to collide with: his own walls, the opposing player’s walls, or the boundaries of the playfield. When this occurs, the player who did not crash receives a point. Upon every collision, the walls of the player who crashed will blink. The screen is then cleared and the game continues.
The first player to reach nine points is the winner. To start the next game, just press the fire button. To play, plug joysticks into the first two joystick ports (sticks 1 and 2).
Lines 1-2 set up the title display. Line 5 sets up a mixed graphics mode with one line of GR. 1 followed by one line of GR. 2 and 44 lines of GR. 5. START calculates the address of the display list in memory. This pointer is needed since the location of the display list depends upon the amount of memory installed in the Atari. The two POKEs then place instructions for the desired graphics modes at the appropriate memory locations. Line 10 initializes the variables X and Y, the starting location of player 1, and S and T which give the location of player 2. Variables X1 and Y1 and S1 and T1 are the increment or decrement values for plotting the walls on the screen. F is a flag to determine whether there was a simultaneous collision between the two players. H1 and B1 are used to keep score. Line 12 plots the boundaries of the playing field in blue. POKEing memory location 87 (current screen mode) with 5 directs the computer to plot in GR. mode 5. This is needed only in a mixed graphics mode. Line 14 goes to a subroutine at line 300 which prints the score in GR. 2 characters. Line 15 checks for the end of the game.
Lines 20-120 contain the main game loop. Lines 25 to 43 check for joystick movement and assign the move variable (X1, Y1, S1, T1), and a value for P and L. One of the nice features of Atari BASIC is that you can use a variable as a GOSUB address. This feature is used in line 50 to branch to different subroutines depending upon the value of P (player 1) and L (player 2). Note that in line 23 you must POKE 5 into memory location 87 again because it was changed during subroutine 300 (line 14). Lines 150 to 185 first check for a collision. If there is none, it plots the new block. A collision is found by locating the next position in front of the plotted block and finding its color. If the color is (which is the background default color), it continues and plots the next block. If it is any other color, there is a collision. If the first player has collided, the program branches to line 201 to check for a simultaneous collision by the other player. Flag F is set if a simultaneous collision is found. Lines 210-220 update the score and blink the losing player’s walls. Subroutine 300 prints the score at the top of the screen in GR. 2 characters. Subroutine 350 blinks the colors of the colliding player’s walls. Lines 400-410 check if you want to start a new game (prints in GR. 1 characters).
If you haven’t played “Blockade” before, grab a friend and try it. It requires quick decisions and good strategy. You’ll like it.
“Tank Duel” is a two-player action game requiring a pair of joysticks. Two program listings are included: standard Atari BASIC (16 RAM required), and BASIC A+ (48K and BASIC A+ language required). Only the Atari BASIC version will run on an XL-model computer.
Most video and computer games pit you against the computer itself. They also tend to be tests of reaction reflexes. So it’s no surprise that you, a mere human, are doomed to eventual failure. Computers have a way to go before they catch up with people in all aspects of intelligence, but when it comes to response time, silicon beats protoplasm any day.
That’s why I’ve always enjoyed computer games that pit two people against each other. These games bring the full range of human characteristics into play, characteristics that are very difficult to program into a computer: real (as opposed to “artificial”) intelligence; deception; skill that improves with experience; and emotions of excitement, frustration, and panic. The computer becomes the tool of interaction, the battlefield of conflict, like a chessboard. The unique capabilities of a computer also allow it to act as a referee, by creating a stage for the contest which precludes any actions not sanctioned by the program.
“Tank Duel” transforms the screen into a large battlefield occupied by two tanks. Each player controls one of the tanks with a joystick. The tanks are fully maneuverable and armed with a cannon fired by pressing the joystick trigger button. In addition to the tanks on the screen, each player also has two extra tanks in reserve. When a player’s on-screen tank is destroyed, it is automatically replaced by one of these reserve tanks. The object of the game is to survive: destroy all the enemy tanks before the enemy destroys yours.
First, type the program listing carefully, especially the DATA statements. Some of these DATA statements contain machine language subroutines, and a mistyped number could cause your computer to crash (the keyboard locks up and refuses to respond to your commands). If this happens, and the SYSTEM RESET key also locks up, the only way to recover is to turn the computer off and then on again. Of course, this means the program will be erased. So to be safe, save the program on disk or tape at least twice before running it for the first time. Then if the computer crashes, you can turn the computer off and on to clear it, and simply reload the program to start looking for the mistake.
Also make sure to type in the correct program listing. If you are using the standard Atari BASIC cartridge, type the Atari BASIC version. The other version is for people with BASIC A+, an advanced BASIC on disk that requires 48K (see “Technical Details,” below).
When you’re ready to play, type RUN and press RETURN. A title screen appears for 30 seconds while the program initializes (sets itself up). When the battlefield appears and you hear the low rumble of two idling tank engines, the game is ready to start.
Here’s how the joystick controls work: to rotate a tank in place, move the stick right or left. Moving the stick right rotates the tank clockwise, and moving the stick left rotates the tank counterclockwise. Pushing the joystick forward drives the tank in whichever direction it’s pointed. If these joystick controls sound familiar, it’s because they are almost identical to the way you manipulate the spaceship in the Atari computer version of Asteroids. The only difference is that pulling backward on the joystick does not flip your tank into hyperspace!
The battlefield, surrounded by a screen border, is dotted with trees, houses, and other buildings of varying shapes and sizes. Note that you can drive your tank behind trees for concealment, but that you cannot drive through buildings (your tank just bounces off). You also cannot drive through the screen border. And if you try ramming the enemy tank, your own tank blows up, so forget about kamikaze charges.
To fire your tank’s cannon, press the joystick trigger button. The gun’s range is limited to about two-thirds the breadth or height of the screen.
When a player’s tank is destroyed, action stops for a few seconds while it is replaced by one of the reserve tanks. The number of tanks each player has in reserve is indicated by the tank symbols in the lower left and right corners of the screen. Each time a player’s tank is blown up, one of these tank symbols is replaced by a tiny cross.
Just to make the game a little more interesting, there is another hazard besides the enemy tanks — minefields. Every game, a minefield — with four mines — is planted at random somewhere on the battlefield. The minefield is about an inch square and is invisible. The only way you’ll know that you found a minefield is when your tank blows up. (Hint: minefields are planted in otherwise empty space, never beneath trees, so you’re safe in the forest.)
When all three of one player’s tanks are destroyed, the game ends. The winner’s tank flashes colors for a few seconds, and then the battlefield disappears. A screen message explains how to start a new game of Tank Duel by pressing either joystick trigger button.
Tank Duel originally was written, not in Atari BASIC, but in BASIC A+. If you’re not familiar with BASIC A+, it’s an enhanced version of Atari BASIC produced by Optimized Systems Software, Inc., of Cupertino, California. At this writing, BASIC A+ is available only on disk, although a cartridge version is being planned. The disk version requires at least 32K of memory (48K recommended). BASIC A+ is upward compatible with Atari BASIC, which means any program written in Atari BASIC will run in BASIC A+ (and will run faster, since BASIC A+ is more streamlined). However, most programs written in BASIC A+ will not run in Atari BASIC.
Why was BASIC A+ my first choice? Because this program was my first attempt to use some of the Atari’s special features such as player/missile graphics and redefined characters. This was easier done in BASIC A+ than in Atari BASIC.
When standard Atari BASIC was created, it was decided to fit the whole language into a single cartridge within only 8K of memory. Although Atari BASIC has many powerful features (i.e., instant syntax checking, unlimited-length strings, built-in commands for graphics and sound, etc.), it lacks special commands for more advanced features such as player/missile graphics. P/M graphics, known on some other home computers as “sprites” allows you to create shapes and move them around the screen without disturbing other screen objects. It’s also easy to determine if a P/M object is colliding with any other objects. This makes P/M graphics a powerful feature for games.
However, since Atari BASIC lacks built-in P/M commands, this feature is hard to learn and use. That’s where BASIC A+ really shines. It has many more commands than Atari BASIC, including keywords such as PMGRAPHICS, PMCOLOR, and PMMOVE. I found it much easier to learn P/M graphics with these commands than to struggle with the many POKEs necessary in Atari BASIC. To see for yourself, compare the BASIC A+ program listing with the Atari BASIC listing.
After finishing Tank Duel in BASIC A+, though, I decided to translate it into standard Atari BASIC. Why? For one thing, I wanted to give copies of the game to a few friends who did not have BASIC A+. Second, the program could not have been published in this book unless it appealed to the widest possible range of readers, and only a minority of Atari users have BASIC A+. And finally, I wanted to learn how to use P/M graphics and other special features in my computer’s standard language, Atari BASIC. However, writing Tank Duel first in BASIC A+ was a valuable experience. It introduced me to some of the Atari’s advanced techniques in a more friendly way.
So if we have an Atari BASIC translation that anyone can use, why are we including the original BASIC A+ version here? For two reasons: Atari users unfamiliar with BASIC A+ can compare the two listings to see the differences, and people who already own BASIC A+ can type in that listing and take advantage of the language’s superior features. The BASIC A+ version still runs a little faster and more smoothly than the Atari BASIC translation. Note that this is despite the fact that the Atari BASIC version includes two machine language subroutines to speed up the animation, while the original version is pure unadulterated BASIC.
If you are interested in trying some game programming yourself, there are a few tricks you can learn by studying these program listings. (For the rest of this discussion, we’ll assume you have some fundamental understanding of Atari BASIC.)
Tank Duel was programmed with two goals in mind: to make it run as fast as possible in BASIC, and to consume as little memory as possible. When writing any program that may be published or given to others, it is a good idea to make it workable on minimum systems so the widest possible range of people can use it. Tank Duel fits in 16K, which is the minimum Atari system that has been sold recently. Several techniques were used to make the program compact and fast. Note that not all of these are considered good programming techniques in programs which do not have to meet such requirements.
REM statements are kept to a minimum to save memory. To make up for this somewhat, most of the variable names are not meaningless single letters, but rather short words which mean what they do. (Luckily, Atari BASIC allows very long variable names.) For instance, the string variable SHAPES holds the player shape data; MISSILES holds the missile shape data; HORIZ is the player horizontal position value, and VERT is the vertical value; MHORIZ is the missile horizontal value; and so on. This doesn’t consume as much memory as you might think, because Atari BASIC stores variables as short tokens internally after the first occurrence. What’s more, it’s really helpful to have meaningful variables when you stop working on a program for a few days and come back later.
Another way of saving memory, and speeding up execution, is to pack as many statements on a program line as will fit.
Also, look at the Atari BASIC listing and notice how the program is structured (the BASIC A+ version is structured somewhat differently). Many people group their subroutines at the bottom of the program. But when Atari BASIC encounters a GOSUB, it starts at the top of the program and searches downward for the target line number. Subroutines which are called often, and which need to be executed fast, should be grouped at the top of the program. In Tank Duel, the subroutines for moving tanks (lines 1000-1180), firing shots (lines 2000-2200), and checking for hits (lines 4000-4820) are placed above the “main loop” (lines 10040-10900). The subroutines for initialization (setting up the program) are tucked away beneath the main loop. Many of these lines are executed only once, when the game is first run.
As mentioned, the BASIC A+ version of Tank Duel was fast enough to get along fine all by itself. But the Atari BASIC version needed a little help from machine language.
Since machine language, not BASIC, is actually the language which the computer uses internally, programs written directly in machine language do not have to be interpreted by the computer and always run much faster. Unfortunately, machine language is the hardest language for humans to master. Tank Duel needed machine language for two things: to rotate the tanks, and to move the tanks vertically and diagonally (the Atari has built-in provisions for easily moving P/M objects horizontally, but not for moving them in any other direction). When I wrote Tank Duel, I knew absolutely nothing about machine language. The solution was to use two machine language routines published in COMPUTE!. These are “canned” routines; that is, you can be totally ignorant about machine language and still use them. Since they are very short and very handy, let’s review them briefly here.
The first one allows fairly fast vertical and diagonal movement. It originally appeared as “Adding High-Speed Vertical Positioning To P/M Graphics,” by David H. Markley, in COMPUTE!, December 1981. It was reprinted in COMPUTE’s First Book of Atari Graphics. To use this routine in your own programs, copy lines 11100-11160 from the Atari BASIC listing. The DATA statements are decimal equivalents of the machine language instructions; type them very carefully. Line 11160 POKEs the routine into page six, an area of free memory in the Atari.
This routine requires that the first number in the DATA statement which defines the shape of your player be equal to the height of the player. For example, look at line 12020. This DATA statement defines the shape of a tank facing “north” (up). There are nine numbers in the DATA statement. The first number is an eight because the player shape is eight bytes high. The following eight numbers are the eight bytes (the second and third numbers just happen to be eights by coincidence). If the player were ten bytes high, the DATA statement would contain 11 numbers — a ten followed by the ten bytes.
To call this routine, use this statement:
A=USR(1536,SHAPE,CURRENT LOCATION,NEW LOCATION)
“A” is a dummy variable which doesn’t mean anything, but is required by the syntax of the USR statement. There are four parameters in the parentheses of the USR statement. The first parameter is the address of the machine language routine itself; 1536 is the start of page six. The next parameter is the address of the player shape. Tank Duel stores the player shapes in SHAPES and uses the ADR function to find the address. The third parameter is the player’s current location, the actual memory address of the vertical position. The last parameter is the new location, the memory address of the vertical position to which you want to move the object.
For an example, see the first statement in line 4200:
A=USR(1536,ADR(SHAPE$(64)),VERT,VERT+2)
The ADR function finds the address of the substring starting at SHAPE$(64). This is where the player shape that is being moved is stored. Remember that the first number in this shape is an eight, the height of the player. The third parameter, VERT, is a variable containing the memory address of the player’s vertical position (it is an offset from PMBASE). The last parameter tells the routine to move the player to VERT +2, or two notches down the screen (shifting a player up in memory moves it down the screen, and vice versa).
The second machine language routine in the Atari BASIC version of Tank Duel allows you to instantly change a player’s shape. This is how the tanks rotate; the rotation is really an illusion. Actually there are eight different tank shapes stored in SHAPES, one for each direction a tank can face. Pushing the joystick right or left calls this routine and draws the appropriate shape.
The routine originally appeared in the article “Extending Player/Missile Graphics,” by Eric Stoltman, COMPUTE!, October 1981, and also was reprinted in COMPUTE!’s First Book of Atari Graphics. To use this routine in your own programs, copy lines 11180-11220. The DATA in line 11220 is the machine language, and line 11200 stores the routine in a string called MOVES, since we already used page six for the other routine (although there was plenty of room left). The variable MOVE is the address of MOVES, making it easier to call the routine later.
Like the previous routine, this one also needs to know the height of the player. It handles this differently, though. It stores the player’s height in the 22nd number of the DATA statement. Notice that this is an eight. For a ten-byte player, you would change this number to a ten.
Call the routine with this statement:
A=USR(MOVE,CURRENT LOCATION,SHAPE)
“A” is the usual dummy variable. This routine uses only three parameters in the USR statement. The first is the address of the routine itself. Remember, we stored this routine in MOVES and set MOVE equal to the string address. You could replace MOVE with ADR(MOVES) and get the same effect. The second parameter is the actual memory address of the player’s vertical position, just as required before. And the last parameter, SHAPE, is where the player’s shape is stored, also as before. See line 4700 for an example.
If you intend to tackle some game programming with player/missile graphics, these two routines will be invaluable additions to your routine library. They are short, easy to use, and relatively fast. For a fuller explanation, be sure to look up the original articles. Since they were first published, they’ve been the basis of several fine games in Atari BASIC.
This game demonstrates that good games can be written completely in BASIC. “Pick-up Sticks” doesn’t even use the statements PEEK or POKE.
“Pick-up Sticks” requires two players. Each player uses one joystick. The screen displays 15 sticks and two players. The players will appear at random, but always immediately beside each other. A stick will begin to flash, indicating that it is the next target. The first player reaching the stick gets the point. The player who has the most points, when all 15 sticks are gone, wins. A complication is that if both players reach the stick at the same time, no one gets the point. Since both players start out at virtually the same place on the screen, this can play a deciding role.
You’ll notice that when a player moves, he leaves a trail behind him. This does not affect the game. But it does let you draw pretty pictures if you like.
One of the first things I discovered about my computer was that Atari 8K BASIC is slow. It is so slow, in fact, that many games cannot be written without PEEKs or POKEs. And when it comes to moving images or players across a playfield, nothing comes in handier than a POKE or a USR command to call some machine language subroutine.
How do we get by with such a slow language? We could use PEEK and POKE or Assembler routines. But then there would be no reason for this article. The first criterion is to make the most of what you have. Don’t get too fancy, either. It’s been my experience that in BASIC, when you get fancy, you get slow. The second criterion that we must impose is that the more graphically oriented your program is, the more overhead involved by the computer. (Remember, it’s not the amount of RAM used in a particular graphics mode that hurts you; it’s the amount of coding required in your program to address it all.) Finally, when it comes to sound, experiment. Many good sound effects can be done by a simple SOUND command with various distortions. It may take awhile to achieve the results that you desire, but it can be done.
Here’s proof: a program that I wrote called Pick-up Sticks. Nowhere in the entire program will you find one POKE or one USR statement. The game itself is quite simple and will run easily on any Atari.
Variable | Usage |
---|---|
X$,Y$ | Players’ initials |
A(15) | Array used to determine sticks’ positions |
XHOR,XVERT | Player X’s horizontal and vertical position |
YHOR,YVERT | Player Y’s horizontal and vertical position |
XDIR | Player X’s current direction of travel |
YDIR | Player Y’s current direction of travel |
NORTH, EAST, SOUTH,WEST | Playfield boundaries |
CBLINK | Color cycle for blinking of sticks |
SUBSC | Subscript for scanning through array A |
MATCH | Used to determine which player picked up the stick |
NUMMATCH | The number of sticks which have been picked up |
XMAT | The number of sticks picked up by player X |
YMAT | The number of sticks picked up by player Y |
BLINK | Selected stick board position |
This strategy game is for one or two players, although more can play if your machine has more than 16K memory.
“Poker Solitaire” is a strategy game played with a standard deck of cards. The object is to create the best ten poker hands possible within a five-by-five matrix, using the first 25 cards in the deck. These are dealt one at a time and, once positioned in the matrix, cannot be moved. When 25 cards have been played, each hand of five cards (five across, five down) is scored; the final score is the sum of the ten individual hands.
The version presented here requires 13K of free RAM, without the REM statements, which are provided only to clarify the listing. One or two persons can play, although more players can easily be added if enough RAM is available.
After typing RUN, you will see a title screen while initialization is taking place. When the game has been set up, the option/score screen will appear. The first time you see this screen, the top half will be blank. The bottom half will contain the options.
Only the option that is blinking can be changed. To change the value, execute the command, or view a screen, press the trigger of the joystick plugged into port one or press the OPTION console key. To move to another option, move the joystick in any direction or press the SELECT console key. You may start the game at any time by pressing START.
The options are fairly obvious, except for “DECKS.” If there is more than one player, this option allows each player to have either a unique set of cards or the same sequence as the other players. In the former case, the cards received by one player have no bearing on the cards dealt to the other players — they are not being dealt from the same “deck.” In the latter case, players will see who gets the highest score using the same cards.
After you have indicated you wish to START the game, there will be a delay of a few seconds, followed by the playing screen of the first player. This will consist of a five-by-five matrix, the notice PLAYER 1 vertically along the right-hand side, and the first card displayed in the lower right-hand corner.
The colored rectangle is a cursor that can be moved in any direction by the joystick. When you find a location you like, press the joystick trigger. The card will appear at that position and also remain at the bottom of the screen.
If you change your mind, simply move the joystick to reposition the card. Once you are satisfied with the location, press the trigger a second time to finalize your selection.
If there is more than one player, the next player’s screen will immediately appear. Play continues until 24 rectangles have been filled for each player. It is not necessary to do anything to position the 25th card. It will be placed in the remaining location automatically. You can hold the trigger to view the screen; otherwise the next screen comes up automatically. Release the trigger to continue.
After the final card for the last player has been positioned, the first player’s screen will appear and be scored. The final score will appear in the lower right-hand corner. When the screen has been scored, either move the joystick in any direction or press the trigger to bring the next player’s screen to be scored.
These are the scores for each possible hand:
SCORE | HAND |
---|---|
One Pair | 2 |
Two Pair | 5 |
Three of a Kind | 10 |
Straight | 15 |
Flush | 20 |
Full House | 25 |
Four of a Kind | 50 |
Straight Flush | 75 |
Royal Flush | 100 |
After the scoring of the final player, moving the joystick or pressing the trigger will cause the option/score screen to appear. In addition to the options listed before, this screen will now contain each player’s score for the game just completed, plus the highest score since RUN. By using the joystick or the console keys, you can review these screens. Press the BREAK key to end the game and return to BASIC.
Any time joystick or console input is required, you can instead press START to begin a new game, or OPTION or SELECT to return to the option/score screen.
The program is divided into five general areas: the game itself, the scoring routine, the options routine, initialization, and character set redefinition. The game and the scoring routines, since they are the most frequently used, are located near the beginning of the program to take advantage of the faster execution speed for statements near the beginning. Also near the beginning is a subroutine used by several of the routines for blinking displays while checking for input.
Extensive use is made of the capability to relocate the display and write screens. The location of the pointer for the display list is figured by calculating PEEK(560)+PEEK(561)*256+4. The start of screen memory is the two-byte address beginning at location 88.
Each player in this game has his or her own playing screen. In addition, two screens are used to display the option/score data and to retain the high-score hands. Redrawing these screens each time they are needed would be time-consuming. Instead, each screen has its own memory location, which is stored in an array. When a screen is required, the appropriate numbers are POKEd into the pointers and the screen appears.
The screens are stored below RAMTOP (PEEK(106)*256). The first four pages below RAMTOP are used for the redefined character set. Each page holds 256 bytes of information. We need to set aside 240 bytes for each Graphics 2 screen we need. Each screen will begin on an even page. This way the least significant byte of the pointers will be zero, making housekeeping chores easier.
Before anything is stored in the area we have set aside, we must check to see if there is enough memory to hold everything. If the end of the program — PEEK(144) + PEEK(145)*256 — extends into the memory for the screens, the program will stop.
Memory requirements change with the number of players that could play With the REM statements removed, the program requires 13K RAM with two players. Each player beyond the first one uses about 900 additional bytes. Up to five people can play without affecting the game at all. Nine players will cause the option/score screen to display incorrectly but will not affect the playing of the game. The variable MAXPL in line 4010 sets the maximum number of players. Set this to whatever your system can handle.
The character set is redefined in lines 5000-5110. Graphics 2 displays can use only half the character set. We need uppercase and non-inverse characters most of the time. The machine language routine in line 5020 copies one page of memory. It is used to copy the first two pages of the ROM character set to the memory location set up in RAM. It is also used to copy a new high score display.
We redefine four unused characters to be the suit characters. These are copied directly from ROM. Also, we create a single character 10, designed using SuperFont (see COMPUTE!’s First Book of Atari Graphics), and an inverse blank by turning on all bits.
This program “deals” the cards by randomly choosing a number between one and 13 for the value and a second number between one and four for the suit. In order to make certain that no card is used more than once, these numbers are mapped into a 52-element array to represent each card. If the card has been used, a new value and suit are chosen. Note that while this is a good method for choosing cards for this game, it would be inadequate if all the cards in the deck were eventually to be used, because there could be problems finding an unused card near the end of the deck. In that case the deck would have to be “reshuffled.”
Logical assignments are used to reduce the number of IF-THEN statements. If a variable could take on many values depending on several conditions, then memory requirements are decreased by replacing many IF-THEN statements with one line containing many logical assignments. This technique is used in lines 90 and 100, for instance, to determine the new cursor position caused by the motion of the joystick. These two lines replaced 12 statements otherwise needed to test all joystick positions.
Whenever possible, the variables N0 and N1 are used to replace 0 and 1. The variables take up one byte for each occurrence after the first; the constants require six bytes every time they are used. Since there are more than 250 occurrences, this is a considerable savings.
Entertaining animation makes this math practice game fun to play.
Here’s a program which proves that computer-aided math practice need not be boring. In the guise of a game, “MathMan” teaches multiplication facts by presenting random problems. The player (or student) types in the answer and presses RETURN. If he is correct, his friends gathered below cheer, but if the player fails to guess correctly, one of his friends will run away in shame. If all six friends flee, the game is over.
A good player can advance to the next level by successfully completing ten problems. The problems get successively more difficult, so this single program will provide challenge for almost any elementary school child. (Adults may also enjoy the animation.)
Word search puzzles are interesting and enjoyable. This computerized word search game creates a puzzle using words entered by the players.
This game is designed to test your ability to find specific words or letter sequences hidden in a ten-by-ten letter matrix. Scoring is based on the time it takes to enter your correct answer within a given time period determined by the skill level selected. The program uses very little memory and will easily run in 8K.
To play the game, first select the skill level you want to play at, between one and five. One is the easiest, allowing the maximum time of approximately 1.5 minutes to find each word. Skill level five, however, will allow only about 20 seconds to find each word.
Next enter a list of ten words, each being three to eight characters long. Only the letters A to Z may be entered, but they really do not have to be words. You can even use the game to make learning foreign languages more fun. If two people are playing, let one player enter the words for the other to find. Try to mix the word lengths entering both long and short words for best results. If too many long words are entered, it may take awhile for the puzzle to be generated. If any word will not fit into the matrix, enter a new list of words when asked.
When the puzzle is ready, hit any key to start the game. Timing starts when the first word is shown.
Scoring for a correct answer is based on the amount of time it takes to respond, with 100 points maximum for each of ten words. If a correct answer is given in five seconds, you score 100 points. After that, your possible score decreases with time to a minimum of ten points for a correct answer. A wrong answer does not score any points, and you get only one try for each word.
To enter your answer, you give a row and column number of the first character of the word, followed by the direction code (see the diagram in the game). Any invalid entries are discarded, and you type only numbers; you do not type a comma or RETURN.
Before looking at how the program actually works, let’s take a look at the major variables used in the program:
S — defines the size of the letter matrix to be created.
W — defines the number of words to be entered and used in the matrix.
M(S,S) — is the actual letter matrix; note that a floating point numeric matrix is used instead of a string matrix. More about this later.
W$(W) — contains the word list.
L(W,3) — remembers the starting location and direction of each word after it has been placed in the letter matrix. Each entry directly corresponds to the entry in the same position in the word matrix.
P(S,S) and F(8) — are working matrices used to create the actual letter matrix used in the game.
Now let’s take a look at how the program works. First the program gets the desired skill level (SL) as a number between one and five. The program sets a default value of three on the input line that the user can change before hitting the RETURN key. Lines 130-290 then get the list of words and check if each is a valid character string (A-Z). Each word is put into the word list in alphabetical order as it is entered by the user. This avoids the time-consuming process of sorting the entire word list at the end. In this way there is a short delay as each word is entered. This short delay is not even noticeable by the user.
Line 340 initializes the letter matrix to all *’s (decimal value 42). Now each word in the word list is inserted randomly in the letter matrix in the following fashion:
When all words have been put into the matrix, the remaining unused positions (still *) are filled in with random letters (lines 760-770).
Everything is now set to play the game, as soon as the player hits a key (lines 780-800). The letter matrix is displayed along with a direction code diagram and a score box (lines 820-960). A word is given to the player for him or her to find in the matrix, and the timer is restarted (lines 970-1000). Then the program prompts the player for the starting location and direction code (lines 1020-1170). The values entered are then checked to see if correct, first against the values saved when the word was put into the matrix (lines 1190-1210). If the value does not match, then the program checks to see if a “double” was created when the unused positions were filled with random letters. Thus the program checks the player’s answer again to insure it is right or wrong (lines 1230-1280). If a bad answer is entered, it is indicated, and the correct answer is displayed with no score added (lines 1360-1430). A good answer is indicated and the appropriate score is displayed and added to the player’s total. The score is based on the selected skill level and the time it takes to enter the answer.
That’s all there is to it. I should explain that a numeric vector is used for the actual letter matrix since it is easier and faster to use. Most people who have tried this game have found it to be very interesting and fun to play. At times it can even be educational.
“Total Recall” is a simple memory game. It’s easy at first, but as the computer adds more and more to remember, the game becomes more difficult.
After playing a game or two of “Simon,” it occurred to me that this would be a terrific game to write for the Atari. After all, the Atari has color graphics, sound — everything I could possibly need. However, I couldn’t come up with an easy way to display more than four colors on the screen at one time without painting my television set.
Then along came the articles on Player/Missile Graphics. At last I have access to a multitude of colors. What a perfect solution to my problem:
Using Player/Missile Graphics I drew four vertical bars, giving each a separate color and sound. As the selection routine makes each decision, the luminescence of the bar chosen is changed and its tone sounded. Several counting routines are called upon to keep track of the events; and there are, of course, timing loops.
There are also times when the screen is needed for text. Instructions to the game might be needed. And since I have not discovered a way to make the Atari laugh, we need to be able to convey a message to the poor person who loses the game.
To clear the screen for the text display, you can position the bars to the far right where they are not visible. They can be returned to their playing positions at any time.
The keys V B N M are used to identify the bars. The keyboard is monitored to determine if your responses are correct. The Atari keeps score.
How good is your memory? Play a few games of “Total Recall” and you will soon find out.
Who writes arcade-quality games? John Scarborough is nineteen years old and learned machine language from a book. He wrote “Chiseler” on an Atari 400 with 16K, a cassette recorder, and an Assembler Editor cartridge. He didn’t even have a full memory map. It doesn’t take a college education or years of experience. It just takes patience, careful design, and love for what the computer can do. A little wizardry doesn’t hurt, either.
It seems like an easy enough job. Four boards are laid out in front of you, and your task is to chisel them away To help you, you have five sets of four chisels each. And not just ordinary tools — these chisels will hurl themselves at the boards and chip away strips of wood at a pretty reckless speed.
But it isn’t as easy as it sounds. Your chisels also hurl themselves away from the boards each time they strike, and if you don’t catch them and bounce them back, they’ll get away for good. And you’ll soon discover that every time you get rid of one board, another appears in its place.
The only way you can keep going on the job is either to be incredibly quick at catching chisels, or to get as many chisels as possible behind the new board when it appears. If you can trap them there, you can sit back and watch while they do the work for you. But don’t doze off — you never know when they’ll escape again, and you’ll be back to work.
This is an arcade-speed game, but don’t worry if you aren’t an accomplished arcader. “Chiseler” begins at a slow enough speed that a beginner can pick it up pretty well. But it keeps its challenge, no matter how good you get.
You’ll need a paddle controller. The game doesn’t require any cartridges to play, but you will need either BASIC or an Assembler Editor to enter the program the first time.
There are two ways to enter and SAVE Chiseler. If you have an Assembler Editor, you can use it and the assembly listing, or you can use the “Machine Language Editor (MLX)” program found in Appendix C and the DATA listing. If you don’t have an Assembler Editor, then you must use the MLX program to enter the DATA statements. It is important that those who use the MLX program read the article that accompanies it. When you use the MLX program, it may seem like extra work at first to have to type in two programs, but you’ll save time later when you end up with a virtually error-free program.
Once you have entered the game and saved it on cassette or disk, you can start one of two ways.
If you entered the game from BASIC using MLX, then the game was saved as an autoboot program. If you have it on cassette, just remove all cartridges, put the cassette in the recorder, and turn on the computer while holding down the START button. You will hear one beep. Push PLAY on the recorder, then RETURN on the computer keyboard. The game will load in automatically. If Chiseler is on disk, turn on the disk drive, put in the disk, and turn on the computer.
If you entered the game with an Assembler Editor, then Chiseler must be loaded from the assembler cartridge or DOS.
From the assembler cartridge, use the LOAD command. Then the debug command G2800 will start the game.
If you created a binary file with MLX, then you must LOAD from the DOS menu. Choose option L, Binary Load. Enter the filename, then select M, RUN at $2800.
Chiseler comes up with two side walls and a back wall, with four colored boards stretching across from side to side. When you press the paddle trigger, the first of four chisels will come at you. You must move your paddle at the bottom of the screen to catch the chisel and hurl it back at the boards. It will bounce off the first board and come back toward the bottom of the screen.
Meanwhile, another chisel will start down toward you. If you catch it — and keep the first one going as well — two more chisels will come. As soon as you miss one chisel, new chisels will stop appearing, and you will never have more than four chisels at a time.
You will notice that as each chisel strikes the board, a thin strip of wood disappears. When all the wood is chipped away at one point, the chisels can get behind the first board, and start bouncing back and forth between the first and second boards. This can be repeated with every board.
When the last bit of a board has been destroyed, a new board will appear in its place. Try to have your chisel strike the last strip of wood from above, so the chisel will bounce back up on the screen and be trapped behind the new board. Then you can relax and watch the chisel do your work for you — until it breaks through again and starts coming back at you.
When the last chisel has got by you, that turn is over. To start the next turn, press the paddle trigger. Four new chisels will be launched. You get a total of five turns.
Each strip of wood in the first board is worth one point; each in the second is worth two; in the third, three; and in the fourth, four.
Every time a new board is put in place, the chisels on the screen speed up slightly. The more new boards, the faster the chisels. After a while, it gets going faster than human dexterity can handle. But try to handle it, because if you let the chisels get by you, they don’t start slowly again on the next turn — they keep every bit of the speed they’ve built up.
If the chisel strikes on the right half of your paddle, it will bounce off at an angle toward the right. If it strikes on the left half, it will bounce off toward the left. When you first start, youll probably feel lucky to catch the chisel at all. But quite soon you’ll start getting some finesse, and the chisels will go pretty much where you want them.
The last program in this book is the Machine Language Editor: MLX. It isn’t a game — it’s a utility to make sure that entering this long machine language program is easy and accurate.
MLX prompts you by asking for the program’s starting address: enter 8192. Then MLX will prompt you again for the ending address: enter 11136. Finally it will ask for the RUN/initialization address: enter 10240. Start entering numbers exactly as they appear in this listing.
The seventh number on every line is a test number. When you enter that, MLX uses it to check to see if every number was entered correctly on that line. If it was, you will be prompted to enter the next line. If there was a mistake, you will hear a beep and you will be prompted to enter the same set of numbers again.
If you aren’t a machine language programmer, don’t worry. Just enter the program from BASIC with MLX. This listing is included for those who are learning machine language for their Atari’s 6502 microprocessor. Instead of an inscrutable list of numbers, you can read the actual commands — with many remarks (which don’t have to be entered), explaining exactly what is going on in every part of the program.
If you’ve ever felt the urge to get inside the arcade machine and see how Pac-Man or Super Breakout achieves those dazzling effects, this listing is for you. Once you have actually gone through the process of making the computer do tricks just by loading the right numbers into the Accumulator and the X and Y registers, performing the right operations on them, and then storing them into the right locations in memory, you’ll realize that putting together a fantastic arcade game isn’t such a mystery after all. You’ve got it right within your reach.
This program was written entirely in machine language, using the Assembler Editor cartridge. It can be assembled in a computer with only 16K of memory, then saved as a single program on cassette. To accomplish this, the program is divided into six subdivisions. This enables the 16K computer owner to assemble the programs without having to worry about running out of memory for the source code. Each unit must be typed in and assembled independently. This shouldn’t be too monotonous if you read the remarks as you type. After all six have been assembled, the object code can be SAVED to cassette with this command:
SAVE#C:<2000,2B80
To retrieve the object code from cassette, enter
LOAD#C:<2000,2B80
These commands are utilized exactly like CLOAD and CSAVE.
Then the command DEBUG, followed by G2800, will start the game.
8192:162,000,169,000,157,000,232 8198:060,232,224,008,208,248,218 8204:169,255,157,000,060,232,117 8210:224,016,208,248,169,000,115 8216:133,176,169,062,133,177,106 8222:160,000,169,000,145,176,168 8228:200,208,251,166,177,232,246 8234:134,177,224,063,240,238,094 8240:169,034,141,006,062,169,117 8246:033,141,007,062,169,044,254 8252:141,008,062,141,009,062,227 8258:169,013,141,011,062,169,119 8264:016,141,013,062,141,023,212 8270:062,141,024,062,141,025,021 8276:062,141,026,062,141,027,031 8282:062,162,000,189,201,006,198 8288:157,033,062,232,224,005,041 8294:208,245,169,000,133,176,009 8300:169,062,133,177,160,042,083 8306:169,001,145,176,200,192,229 8312:059,208,249,160,062,169,003 8318:001,145,176,152,024,105,217 8324:016,168,169,001,145,176,039 8330:152,024,105,004,168,056,135 8336:201,241,144,233,166,177,026 8342:232,134,177,224,064,240,197 8348:005,160,006,076,125,032,048 8354:169,001,141,242,062,141,150 8360:002,063,169,000,133,176,199 8366:169,062,133,177,160,103,210 8372:162,068,138,145,176,232,077 8378:200,224,083,208,247,160,028 8384:163,162,147,138,145,176,099 8390:232,200,224,162,208,247,191 8396:160,223,162,098,138,145,106 8402:176,232,200,224,113,208,083 8408:247,169,063,133,177,160,141 8414:027,162,177,138,145,176,023 8420:232,200,224,192,208,247,251 8426:169,032,133,178,169,060,207 8432:133,179,160,000,152,145,241 8438:178,200,208,251,169,061,033 8444:133,179,169,000,145,178,032 8450:200,192,224,208,249,169,220 8456:032,133,178,169,060,133,201 8462:179,160,000,177,178,208,148 8468:008,200,192,120,208,247,227 8474:032,000,034,169,152,133,034 8480:178,160,000,177,178,208,165 8486:008,200,192,120,208,247,245 8492:032,049,034,169,016,133,221 8498:178,169,061,133,179,160,162 8504:000,177,178,208,008,200,059 8510:192,120,208,247,032,060,153 8516:034,169,136,133,178,160,110 8522:000,177,178,208,008,200,077 8528:192,120,208,247,032,071,182 8534:034,096,000,000,000,000,216 8540:000,000,000,000,000,000,092 8546:000,000,000,000,000,000,098 8552:000,000,000,000,000,000,104 8558:000,000,000,000,000,000,110 8564:000,000,000,000,000,000,116 8570:000,000,000,000,000,000,122 8576:000,000,000,000,000,000,128 8582:000,000,000,000,000,000,134 8588:000,000,000,000,000,000,140 8594:000,000,000,000,000,000,146 8600:000,000,000,000,000,000,152 8606:000,000,000,000,000,000,158 8612:000,000,000,000,000,000,164 8618:000,000,000,000,000,000,170 8624:000,000,000,000,000,000,176 8630:000,000,000,000,000,000,182 8636:000,000,000,000,000,000,188 8642:000,000,000,000,000,000,194 8648:000,000,000,000,000,000,200 8654:000,000,000,000,000,000,206 8660:000,000,000,000,000,000,212 8666:000,000,000,000,000,000,218 8672:000,000,000,000,000,000,224 8678:000,000,000,000,000,000,230 8684:000,000,000,000,000,000,236 8690:000,000,000,000,000,000,242 8696:000,000,000,000,000,000,248 8702:000,000,169,032,133,178,254 8708:169,060,133,179,160,000,193 8714:177,178,208,034,200,192,231 8720:120,208,247,160,000,169,152 8726:255,145,178,200,192,120,088 8732:208,249,169,041,141,210,022 8738:006,173,209,006,201,001,118 8744:240,006,056,233,001,141,205 8750:209,006,096,169,152,133,043 8756:178,169,060,133,179,076,079 8762:008,034,169,016,133,178,084 8768:169,061,133,179,076,008,178 8774:034,169,136,133,178,169,121 8780:061,133,179,076,008,034,055 8786:000,000,000,000,000,000,082 8792:000,000,000,000,000,000,088 8798:000,000,000,000,000,000,094 8804:000,000,000,000,000,000,100 8810:000,000,000,000,000,000,106 8816:000,000,000,000,000,000,112 8822:000,000,000,000,000,000,118 8828:000,000,000,000,000,000,124 8834:000,000,000,000,000,000,130 8840:000,000,000,000,000,000,136 8846:000,000,000,000,000,000,142 8852:000,000,000,000,000,000,148 8858:000,000,000,000,000,000,154 8864:000,000,000,000,000,000,160 8870:000,000,000,000,000,000,166 8876:000,000,000,000,000,000,172 8882:000,000,000,000,000,000,178 8888:000,000,000,000,000,000,184 8894:000,000,000,000,000,000,190 8900:000,000,000,000,000,000,196 8906:000,000,000,000,000,000,202 8912:000,000,000,000,000,000,208 8918:000,000,000,000,000,000,214 8924:000,000,000,000,000,000,220 8930:000,000,000,000,000,000,226 8936:000,000,000,000,000,000,232 8942:000,000,000,000,000,000,238 8948:000,000,000,000,000,000,244 8954:000,000,000,000,000,000,250 8960:169,062,141,047,002,169,078 8966:001,141,008,208,169,239,004 8972:141,192,002,169,015,141,160 8978:193,002,141,194,002,141,179 8984:195,002,141,199,002,169,220 8990:048,141,007,212,169,003,098 8996:141,029,208,169,000,133,204 9002:180,169,048,133,181,160,145 9008:000,152,145,180,200,208,165 9014:251,166,181,232,134,181,175 9020:224,056,208,242,169,255,190 9026:141,196,052,141,197,052,077 9032:141,198,052,169,255,141,004 9038:221,052,141,222,052,141,139 9044:223,052,169,000,141,196,097 9050:006,141,197,006,141,198,011 9056:006,141,199,006,169,001,106 9062:141,175,006,162,000,173,247 9068:010,210,056,201,075,144,036 9074:248,024,201,186,176,243,168 9080:157,176,006,232,224,004,151 9086:208,235,162,000,169,047,179 9092:157,180,006,169,112,157,145 9098:171,006,232,224,004,208,215 9104:241,162,000,173,010,210,172 9110:041,001,157,184,006,232,003 9116:224,004,208,243,162,000,229 9122:169,001,157,188,006,232,147 9128:224,004,208,246,162,000,244 9134:169,001,157,164,006,232,135 9140:224,004,208,246,173,112,123 9146:002,074,024,105,070,141,090 9152:160,006,169,255,056,237,051 9158:160,006,056,201,177,144,174 9164:002,169,177,141,000,208,133 9170:141,163,006,096,000,000,104 9176:000,000,000,000,000,000,216 9182:000,000,000,000,000,000,222 9188:000,000,000,000,000,000,228 9194:000,000,000,000,000,000,234 9200:000,000,000,000,000,000,240 9206:000,000,000,000,000,000,246 9212:000,000,000,000,174,162,076 9218:006,189,164,006,208,001,064 9224:096,189,184,006,208,012,191 9230:189,176,006,056,233,001,163 9236:157,176,006,076,035,036,250 9242:189,176,006,024,105,001,015 9248:157,176,006,189,188,006,242 9254:208,012,189,180,006,056,177 9260:233,001,157,180,006,076,185 9266:061,036,189,180,006,024,034 9272:105,001,157,180,006,189,182 9278:180,006,056,201,219,144,100 9284:044,208,009,173,175,006,171 9290:056,233,001,141,175,006,174 9296:169,001,141,199,006,189,017 9302:180,006,201,252,208,021,186 9308:169,000,224,003,208,006,190 9314:141,199,002,076,107,036,147 9320:157,193,002,169,000,157,014 9326:164,006,096,189,188,006,247 9332:208,003,076,228,036,189,088 9338:180,006,201,193,240,004,178 9344:201,218,208,096,189,176,192 9350:006,056,205,163,006,144,202 9356:087,056,233,016,024,205,249 9362:163,006,176,078,173,199,173 9368:006,208,029,162,001,189,235 9374:195,006,208,017,169,001,242 9380:157,195,006,173,175,006,108 9386:024,105,001,141,175,006,110 9392:076,184,036,232,224,004,164 9398:208,229,174,162,006,169,106 9404:000,157,188,006,169,017,213 9410:141,000,210,189,176,006,148 9416:056,233,005,141,160,006,033 9422:173,163,006,056,205,160,201 9428:006,144,008,169,000,157,184 9434:184,006,076,228,036,169,149 9440:001,157,184,006,189,176,169 9446:006,201,072,208,010,169,128 9452:001,157,184,006,169,029,014 9458:141,002,210,189,176,006,198 9464:201,190,208,010,169,000,002 9470:157,184,006,169,029,141,172 9476:002,210,189,180,006,201,024 9482:047,208,010,169,001,157,090 9488:188,006,169,029,141,002,039 9494:210,189,176,006,157,001,249 9500:208,189,180,006,133,182,158 9506:224,003,208,005,169,051,182 9512:076,047,037,138,024,105,211 9518:053,133,183,160,000,152,215 9524:145,182,200,224,003,208,246 9530:005,169,003,076,066,037,158 9536:169,192,145,182,200,145,073 9542:182,200,145,182,200,169,124 9548:000,145,182,096,000,000,243 9554:000,000,000,000,000,000,082 9560:000,000,000,000,000,000,088 9566:000,000,000,000,000,000,094 9572:000,000,000,000,000,000,100 9578:000,000,000,000,000,000,106 9584:000,000,000,000,000,000,112 9590:000,000,000,000,000,000,118 9596:000,000,000,000,000,000,124 9602:000,000,000,000,000,000,130 9608:000,000,000,000,000,000,136 9614:000,000,000,000,000,000,142 9620:000,000,000,000,000,000,148 9626:000,000,000,000,000,000,154 9632:000,000,000,000,000,000,160 9638:000,000,000,000,000,000,166 9644:000,000,000,000,000,000,172 9650:000,000,000,000,000,000,178 9656:000,000,000,000,000,000,184 9662:000,000,000,000,000,000,190 9668:000,000,000,000,000,000,196 9674:000,000,000,000,000,000,202 9680:000,000,000,000,000,000,208 9686:000,000,000,000,000,000,214 9692:000,000,000,000,000,000,220 9698:000,000,000,000,000,000,226 9704:000,000,000,000,000,000,232 9710:000,000,000,000,000,000,238 9716:000,000,000,000,000,000,244 9722:000,000,000,000,000,000,250 9728:174,162,006,189,171,006,196 9734:240,007,056,233,001,157,188 9740:171,006,096,189,180,006,148 9746:056,201,062,144,047,024,040 9752:201,070,176,003,076,071,109 9758:038,056,201,086,144,034,077 9764:024,201,094,176,003,076,098 9770:084,038,056,201,110,144,163 9776:021,024,201,118,176,003,079 9782:076,097,038,056,201,134,144 9788:144,008,024,201,142,176,243 9794:003,076,110,038,096,169,046 9800:070,141,170,006,169,004,120 9806:032,123,038,076,170,038,043 9812:169,094,141,170,006,169,065 9818:019,032,123,038,076,170,036 9824:038,169,118,141,170,006,226 9830:169,034,032,123,038,076,062 9836:170,038,169,142,141,170,170 9842:006,169,049,032,123,038,019 9848:076,170,038,141,169,006,208 9854:169,080,141,194,006,189,137 9860:176,006,024,205,194,006,231 9866:176,011,173,170,006,056,218 9872:253,180,006,141,168,006,130 9878:096,173,194,006,024,105,236 9884:008,141,194,006,172,169,078 9890:006,200,140,169,006,076,247 9896:131,038,173,169,006,024,197 9902:201,032,176,011,169,000,251 9908:133,178,169,060,133,179,008 9914:076,203,038,169,000,133,037 9920:178,169,061,133,179,173,061 9926:169,006,056,233,032,173,099 9932:169,006,010,010,010,072,225 9938:174,162,006,189,188,006,167 9944:240,011,104,024,105,008,196 9950:056,237,168,006,076,237,234 9956:038,104,024,105,008,056,051 9962:237,168,006,168,177,178,144 9968:208,001,096,169,000,145,091 9974:178,173,200,006,141,004,180 9980:210,032,007,033,032,000,054 9986:042,174,162,006,169,009,052 9992:157,171,006,189,188,006,213 9998:208,006,169,001,157,188,231 10004:006,096,169,000,157,188,124 10010:006,096,000,000,000,000,128 10016:000,000,000,000,000,000,032 10022:000,000,000,000,000,000,038 10028:000,000,000,000,000,000,044 10034:000,000,000,000,000,000,050 10040:000,000,000,000,000,000,056 10046:000,000,072,138,072,169,001 10052:008,162,056,141,010,212,145 10058:141,022,208,142,023,208,050 10064:169,224,141,009,212,169,236 10070:112,141,000,002,104,170,103 10076:104,064,000,000,000,000,004 10082:000,000,000,000,000,000,098 10088:000,000,000,000,000,000,104 10094:000,000,072,138,072,152,032 10100:072,169,152,162,120,160,183 10106:056,141,010,212,141,022,192 10112:208,142,023,208,140,024,105 10118:208,169,060,141,009,212,165 10124:169,224,141,000,002,104,012 10130:168,104,170,104,064,000,244 10136:000,000,000,000,000,000,152 10142:000,000,000,000,000,000,158 10148:000,000,000,000,000,000,164 10154:000,000,000,000,000,000,170 10160:000,000,000,000,000,000,176 10166:000,000,000,000,000,000,182 10172:000,000,000,000,000,000,188 10178:000,000,000,000,000,000,194 10184:000,000,000,000,000,000,200 10190:000,000,000,000,000,000,206 10196:000,000,000,000,000,000,212 10202:000,000,000,000,000,000,218 10208:072,138,072,169,088,162,157 10214:216,141,010,212,141,023,205 10220:208,142,024,208,169,064,027 10226:141,000,002,104,170,104,251 10232:064,000,000,000,000,000,056 10238:000,000,032,000,043,162,235 10244:000,169,080,157,201,006,105 10250:232,224,005,208,248,169,072 10256:000,141,008,210,169,001,033 10262:141,192,006,169,020,141,179 10268:209,006,032,000,032,032,083 10274:000,035,169,000,141,210,077 10280:006,169,166,141,001,210,221 10286:141,003,210,169,170,141,112 10292:005,210,141,007,210,169,026 10298:000,141,000,210,141,002,040 10304:210,141,004,210,141,006,008 10310:210,032,184,035,173,124,060 10316:002,208,248,169,001,141,077 10322:195,006,169,000,133,176,249 10328:169,062,133,177,173,192,226 10334:006,024,105,016,160,013,162 10340:145,176,174,210,006,240,027 10346:012,202,142,210,006,169,079 10352:060,141,006,210,076,124,217 10358:040,169,000,141,006,210,172 10364:169,000,133,077,141,000,132 10370:210,141,002,210,141,004,070 10376:210,169,000,141,162,006,056 10382:032,119,041,032,000,036,146 10388:032,000,038,162,001,142,011 10394:162,006,189,195,006,240,184 10400:009,032,119,041,032,000,137 10406:036,032,000,038,162,002,180 10412:142,162,006,189,195,006,104 10418:240,009,032,119,041,032,139 10424:000,036,032,000,038,162,196 10430:003,142,162,006,189,195,119 10436:006,240,009,032,119,041,131 10442:032,000,036,032,000,038,084 10448:173,199,006,240,126,162,090 10454:000,189,164,006,208,008,021 10460:232,224,004,208,246,076,186 10466:241,040,189,195,006,208,081 10472:106,232,224,004,208,233,215 10478:076,241,040,173,192,006,198 10484:201,005,208,063,169,006,128 10490:133,176,169,062,133,177,076 10496:160,000,169,039,145,176,177 10502:200,169,033,145,176,200,161 10508:169,045,145,176,200,169,148 10514:037,145,176,200,200,169,177 10520:047,145,176,200,169,054,047 10526:145,176,200,169,037,145,134 10532:176,200,169,050,145,176,184 10538:032,184,035,173,031,208,193 10544:201,006,208,246,076,015,032 10550:040,032,184,035,173,031,037 10556:208,201,006,208,003,076,250 10562:015,040,173,124,002,208,116 10568:238,174,192,006,232,142,032 10574:192,006,032,000,035,174,005 10580:209,006,142,211,006,032,178 10586:184,035,173,031,208,201,154 10592:006,208,003,076,015,040,188 10598:160,160,136,208,253,174,169 10604:211,006,202,142,211,006,118 10610:208,229,076,084,040,189,172 10616:180,006,024,201,080,176,019 10622:011,169,072,141,200,006,213 10628:169,005,141,213,006,096,250 10634:024,201,100,176,011,169,051 10640:108,141,200,006,169,004,004 10646:141,213,006,096,024,201,063 10652:128,176,011,169,144,141,157 10658:200,006,169,003,141,213,126 10664:006,096,169,217,141,200,229 10670:006,169,002,141,213,006,199 10676:096,000,000,000,000,000,020 10682:000,000,000,000,000,000,186 10688:000,000,000,000,000,000,192 10694:000,000,000,000,000,000,198 10700:000,000,000,000,000,000,204 10706:000,000,000,000,000,000,210 10712:000,000,000,000,000,000,216 10718:000,000,000,000,000,000,222 10724:000,000,000,000,000,000,228 10730:000,000,000,000,000,000,234 10736:000,000,000,000,000,000,240 10742:000,000,000,000,000,000,246 10748:000,000,000,000,169,000,165 10754:133,176,169,062,133,177,084 10760:174,213,006,202,142,213,190 10766:006,240,006,032,024,042,108 10772:076,008,042,096,174,175,079 10778:006,138,072,032,038,042,098 10784:104,170,202,208,246,096,034 10790:160,027,177,176,201,025,036 10796:208,009,169,016,145,176,255 10802:136,192,022,208,241,024,105 10808:105,001,145,176,169,033,173 10814:141,207,006,169,023,141,237 10820:208,006,172,207,006,177,076 10826:176,056,233,064,172,208,215 10832:006,056,209,176,144,023,182 10838:208,039,172,208,006,200,151 10844:140,208,006,172,207,006,063 10850:200,140,207,006,192,038,113 10856:208,220,076,127,042,162,171 10862:000,160,023,177,176,024,158 10868:105,064,157,201,006,232,113 10874:200,192,028,208,242,160,128 10880:033,162,000,189,201,006,207 10886:145,176,200,232,224,005,092 10892:208,245,096,000,000,000,177 10898:000,000,000,000,000,000,146 10904:000,000,000,000,000,000,152 10910:000,000,000,000,000,000,158 10916:000,000,000,000,000,000,164 10922:000,000,000,000,000,000,170 10928:000,000,000,000,000,000,176 10934:000,000,000,000,000,000,182 10940:000,000,000,000,000,000,188 10946:000,000,000,000,000,000,194 10952:000,000,000,000,000,000,200 10958:000,000,000,000,000,000,206 10964:000,000,000,000,000,000,212 10970:000,000,000,000,000,000,218 10976:000,000,000,000,000,000,224 10982:000,000,000,000,000,000,230 10988:000,000,000,000,000,000,236 10994:000,000,000,000,000,000,242 11000:000,000,000,000,000,000,248 11006:000,000,169,112,141,000,164 11012:006,141,001,006,169,198,013 11018:141,002,006,169,000,141,213 11024:003,006,169,062,141,004,145 11030:006,169,134,141,005,006,227 11036:169,006,141,006,006,141,241 11042:007,006,141,008,006,141,087 11048:009,006,141,010,006,169,125 11054:134,141,011,006,169,006,001 11060:162,000,157,012,006,232,109 11066:224,017,208,248,169,065,221 11072:141,029,006,169,000,141,038 11078:030,006,169,006,141,031,197 11084:006,169,000,141,047,002,185 11090:141,048,002,169,006,141,077 11096:049,002,169,064,141,000,001 11102:002,169,039,141,001,002,192 11108:169,192,141,014,212,169,229 11114:034,141,047,002,096,000,170 11120:000,000,000,000,000,000,112 11126:000,000,000,000,000,000,118 11132:000,000,000,000,000,000,124
10 ; 20 ;PROGRAM CONTROL 30 ; 40 *=$2800 50 PTRGST=$6C2 60 BALOFS=$6A2 70 BALLNB=$6C0 80 PDLCNT=$23B8 90 LAUNCH=$6C3 0100 STIMER=53279 0110 BRKFRQ=$6C8 0120 PTRIG0=$27C 0130 ATRACT=$4D 0140 BALLS=$6AF 0150 NOMORE=$6C7 0160 BALIFE=$6A4 0170 SCRCNT=$2A00 0180 SCRNPL=$B0 0190 SCRNPH=$B1 0200 BALSPD=$6D1 0210 HIGH1=$6C9 0220 RSTFRQ=$6D2 0230 TMPDLY=$6D3 0240 BL1VPS=$6B4 0250 AUDCTL=$D208 0260 BRKVAL=$6D5 0270 STDLST=$2B00 0280 SETPLF=$2000 0290 SETPMG=$2300 0300 BALLCT=$2400 0310 BRKCNT=$2600 0320 ; 0330 ;SET UP DISPLAY LIST 0340 JSR STDLST 0350 ; 0360 ;SET HIGH SCORE EQUAL TO 00000 0370 LDX #0 0380 LDA #$50 0390 CLRHGH STA HIGH1,X 0400 INX 0410 CPX #5 0420 BNE CLRHGH 0430 ; 0440 ;THIS IS THE INTRODUCTION TO 0450 ;THE MAIN LOOP 0460 ; 0470 ;SET THE AUDIO CONTROL 0480 START LDA #0 0490 STA AUDCTL 0500 ; 0510 ;SET BALL NUMBER TO 1 0520 LDA #1 0530 STA BALLNB 0540 ; 0550 ;SET BALL SPEED 0560 LDA #20 0570 STA BALSPD 0580 ; 0590 ;SET PLAYFIELD 0600 JSR SETPLF 0610 ; 0620 ;SET P/M GRAPHICS 0630 JSR SETPMG 0640 ; 0650 ;CLEAR BRICK RESET FREQUENCY 0660 LDA #0 0670 STA RSTFRQ 0680 ; 0690 ;SET AUDIO CONTROL 0700 LDA #$A6 0710 STA $D201 0720 STA $D203 0730 LDA #$AA 0740 STA $D205 0750 STA $D207 0760 ; 0770 ;MAKE SURE FREQUENCY IS OFF 0780 LDA #0 0790 STA $D200 0800 STA $D202 0810 STA $D204 0820 STA $D206 0830 ; 0840 ;WAIT FOR PADDLE TRIGGER 0850 TRGCNT JSR PDLCNT 0860 LDA PTRIG0 0870 BNE TRGCNT 0880 ; 0890 ;SHOW THAT BALL 1 0900 ;HAS BEEN LAUNCHED 0910 LDA #1 0920 STA LAUNCH 0930 ; 0940 ;THE MAIN LOOP 0950 ; 0960 ;SET SCREEN POINTER TO $3E00 0970 MAINLP LDA #$0 0980 STA SCRNPL 0990 LDA #$3E 1000 STA SCRNPH 1010 ; 1020 ;DISPLAY BALL NUMBER 1030 LDA BALLNB 1040 CLC 1050 ADC #$10 1060 LDY #$D ;DISPLAY 1070 STA (SCRNPL),Y ;BALL NUMBER 1080 ; 1090 ;IF A BLOCK HAS RECENTLY BEEN 1100 ;RESET, THEN PRODUCE SOUND 1110 LDX RSTFRQ 1120 BEQ NOSND 1130 DEX 1140 STX RSTFRQ 1150 LDA #$3C 1160 STA $D206 1170 JMP FIXATC 1180 NOSND LDA #0 1190 STA $D206 1200 ; 1210 ;INHIBIT ATTRACT MODE 1220 FIXATC LDA #0 1230 STA ATRACT 1240 ; 1250 ;TURN OFF FREQUENCY 1260 STA $D200 1270 STA $D202 1280 STA $D204 1290 ; 1300 ;ENABLE BALL 1 CONTROL 1310 BALCNT LDA #0 1320 STA BALOFS 1330 ; 1340 ;UPDATE BALL 1'S STATUS 1350 JSR GETFRQ 1360 JSR BALLCT 1370 JSR BRKCNT 1380 ; 1390 ;ENABLE BALL 2 CONTROL 1400 LDX #1 1410 STX BALOFS 1420 ; 1430 ;HAS BALL 2 BEEN LAUNCHED? 1440 LDA LAUNCH,X 1450 BEQ CHKLN2 1460 ; 1470 ;IF SO, THEN UPDATE ITS STATUS 1480 JSR GETFRQ 1490 JSR BALLCT 1500 JSR BRKCNT 1510 ; 1520 ;FOLLOW THE SAME PROCEDURE FOR 1530 ;BALLS THREE AND FOUR 1540 CHKLN2 LDX #2 1550 STX BALOFS 1560 LDA LAUNCH,X 1570 BEQ CHKLN3 1580 JSR GETFRQ 1590 JSR BALLCT 1600 JSR BRKCNT 1610 CHKLN3 LDX #3 1620 STX BALOFS 1630 LDA LAUNCH,X 1640 BEQ CHKEND 1650 JSR GETFRQ 1660 JSR BALLCT 1670 JSR BRKCNT 1680 ; 1690 ;CHECK IF ANY BALLS 1700 ;ARE STILL ALIVE 1710 CHKEND LDA NOMORE 1720 BEQ DELAY 1730 LDX #0 1740 LFECHK LDA BALIFE,X 1750 BNE CHKVOD 1760 INX 1770 CPX #4 1780 BNE LFECHK 1790 JMP DEAD 1800 CHKVOD LDA LAUNCH,X 1810 BNE DELAY 1820 INX 1830 CPX #4 1840 BNE LFECHK 1850 JMP DEAD 1860 DEAD LDA BALLNB 1870 CMP #5 1880 BNE GTPTRG 1890 ; 1900 ;ALL BALLS ARE DEAD 1910 ;DISPLAY "GAME OVER" 1920 LDA #$6 1930 STA SCRNPL 1940 LDA #$3E 1950 STA SCRNPH 1960 LDY #0 1970 GMEOVR LDA #$27 ;G 1980 STA (SCRNPL),Y 1990 INY 2000 LDA #$21 ;A 2010 STA (SCRNPL),Y 2020 INY 2030 LDA #$2D ;M 2040 STA (SCRNPL),Y 2050 INY 2060 LDA #$25 ;E 2070 STA (SCRNPL),Y 2080 INY 2090 INY 2100 LDA #$2F ;O 2110 STA (SCRNPL),Y 2120 INY 2130 LDA #$36 ;V 2140 STA (SCRNPL),Y 2150 INY 2160 LDA #$25 ;E 2170 STA (SCRNPL),Y 2180 INY 2190 LDA #$32 ;R 2200 STA (SCRNPL),Y 2210 ; 2220 ;WAIT FOR USER TO PRESS START 2230 CHKSTM JSR PDLCNT 2240 LDA STIMER 2250 CMP #6 2260 BNE CHKSTM 2270 ; 2280 ;START OVER 2290 JMP START 2300 ; 2310 ;ALL BALLS ARE DEAD, BUT NOT 2320 ;ALL BALL SETS 2330 ;WAIT FOR TRIGGER OR START KEY 2340 GTPTRG JSR PDLCNT 2350 LDA STIMER 2360 CMP #6 2370 BNE TRIGER 2380 ; 2390 ;START OVER 2400 JMP START 2410 TRIGER LDA PTRIG0 2420 BNE GTPTRG 2430 ; 2440 ;INCREMENT BALL NUMBER 2450 LDX BALLNB 2460 INX 2470 STX BALLNB 2480 ; 2490 ;RESET 2500 JSR SETPMG 2510 ; 2520 ;DELAY PROGRAM EXECUTION 2530 DELAY LDX BALSPD 2540 STX TMPDLY 2550 DLY1 2560 JSR PDLCNT 2570 LDA STIMER 2580 CMP #6 2590 BNE CNTDLY 2600 JMP START 2610 CNTDLY LDY #$A0 2620 DLY2 DEY 2630 BNE DLY2 2640 LDX TMPDLY 2650 DEX 2660 STX TMPDLY 2670 BNE DLY1 2680 ; 2690 ;EXECUTE MAIN LOOP AGAIN 2700 JMP MAINLP 2710 ; 2720 ;SET BRICK FREQUENCY 2730 ;AND BRICK VALUE 2740 GETFRQ LDA BL1VPS,X 2750 CLC 2760 CMP #$50 2770 BCS FRQ2 2780 LDA #$48 2790 STA BRKFRQ 2800 LDA #5 ;ADD 1 TO COMPENSATE 2810 STA BRKVAL ;FOR OFFSET 2820 RTS 2830 FRQ2 CLC 2840 CMP #$64 2850 BCS FRQ3 2860 LDA #$6C 2870 STA BRKFRQ 2880 LDA #4 2890 STA BRKVAL 2900 RTS 2910 FRQ3 CLC 2920 CMP #$80 2930 BCS FRQ4 2940 LDA #$90 2950 STA BRKFRQ 2960 LDA #3 2970 STA BRKVAL 2980 RTS 2990 FRQ4 LDA #$D9 3000 STA BRKFRQ 3010 LDA #2 3020 STA BRKVAL 3030 RTS
10 ; 20 ;SET UP THE DISPLAY LIST 30 ; 40 *=$2B00 50 60 ;BLANK THE TOP 16 SCAN LINES 70 LDA #$70 80 STA $600 90 STA $601 0100 ; 0110 ;SET UP 1 LINE OF IR MODE 6 (BASIC 0120 ;MODE 1), ENABLE DISPLAY LIST 0130 ;INTERRUPT AND LOAD THE MEMORY 0140 ;SCAN COUNTER WITH $3E00 0150 LDA #$C6 0160 STA $602 0170 LDA #$00 0180 STA $603 0190 LDA #$3E 0200 STA $604 0210 ; 0220 ;SET UP 1 LINE OF IR MODE 1 AND 0230 ;ENABLE 2ND DLI 0240 LDA #$86 0250 STA $605 0260 ; 0270 ;SET UP 5 LINES OF IR MODE 1 0280 LDA #$6 0290 STA $606 0300 STA $607 0310 STA $608 0320 STA $609 0330 STA $60A 0340 ; 0350 ;SET UP 1 LINE OF IR MODE 1 AND 0360 ;ENABLE 3RD DLI 0370 LDA #$86 0380 STA $60B 0390 ; 0400 ;SET UP 17 LINES OF IR MODE 1 0410 LDA #$6 0420 LDX #0 0430 MODE17 STA $60C,X 0440 INX 0450 CPX #17 0460 BNE MODE17 0470 ; 0480 ;WAIT FOR VERTICAL BLANK, THEN 0490 ;EXECUTE DISPLAY LIST AGAIN 0500 LDA #$41 0510 STA $61D 0520 LDA #$00 0530 STA $61E 0540 LDA #$6 0550 STA $61F 0560 DLISTL=$230 0570 DLISTH=$231 0580 DMACTL=$22F 0590 NMIEN=$D40E 0600 DLILOW=$200 0610 DLIHGH=$201 0620 ;DISABLE DMA 0630 LDA #0 0640 STA DMACTL 0650 ; 0660 ;INFORM ANTIC OF DISPLAY LIST 0670 ;LOCATION 0680 STA DLISTL 0690 LDA #$6 0700 STA DLISTH 0710 ; 0720 ;INFORM ANTIC OF DISPLAY LIST 0730 ;INTERRUPT LOCATION 0740 LDA #$40 0750 STA DLILOW 0760 LDA #$27 0770 STA DLIHGH 0780 ; 0790 ;ENABLE DISPLAY LIST INTERUPTS 0800 LDA #$C0 0810 STA NMIEN 0820 ; 0830 ;ENABLE DMA 0840 LDA #$22 0850 STA DMACTL 0860 RTS
10 ; 20 ;DISPLAY LIST INTERRUPTS 30 ; 40 DLILOW=$200 50 CHBASE=$D409 60 WSYNC=$D40A 70 COLPF0=$D016 80 COLPF1=$D017 90 COLPF2=$D018 0100 ; 0110 ;THIS DLI WILL AFFECT 0120 ;THE SECOND MODE LINE 0130 *=$2740 0140 ; 0150 ;SAVE REGISTERS 0160 PHA 0170 TXA 0180 PHA 0190 ; 0200 ;SET COLPF0 (SCORE) TO GREY 0210 ;AND COLPF1 (HIGH) TO RED 0220 LDA #$08 0230 LDX #$38 0240 STA WSYNC 0250 STA COLPF0 0260 STX COLPF1 0270 ; 0280 ;ENABLE STANDARD CHBASE 0290 LDA #$E0 0300 STA CHBASE 0310 ; 0320 ;ENABLE 2ND DLI 0330 LDA #$70 0340 STA DLILOW 0350 ; 0360 ;RESTORE REGISTERS 0370 PLA 0380 TAX 0390 PLA 0400 ; 0410 ;RETURN FROM INTERRUPT 0420 RTI 0430 ; 0440 ;THIS DLI WILL AFFECT 0450 ;MODE LINES 2-6 0460 *=$2770 0470 PHA 0480 TXA 0490 PHA 0500 TYA 0510 PHA 0520 ; 0530 ;SET COLPF0 (WALLS) TO LIGHT BLUE 0540 ;SET COLPF1 (BLOCK 1) TO BLUE 0550 ;SET COLPF2 (BLOCK 2) TO RED 0560 LDA #$98 0570 LDX #$78 0580 LDY #$38 0590 STA WSYNC 0600 STA COLPF0 0610 STX COLPF1 0620 STY COLPF2 0630 ; 0640 ;CHANGE CHARACTER BASE TO $3CE0 0650 LDA #$3C 0660 STA CHBASE 0670 ; 0680 ;ENABLE 3RD DLI 0690 LDA #$E0 0700 STA DLILOW 0710 PLA 0720 TAY 0730 PLA 0740 TAX 0750 PLA 0760 RTI 0770 ; 0780 ;THIS DLI WILL AFFECT 0790 ;MODE LINES 8-24 0800 *=$27E0 0810 PHA 0820 TXA 0830 PHA 0840 ; 0850 ;SET COLPF0 (BLOCK 3) TO VIOLET 0860 ;AND COLPF1 (BLOCK 4) TO YELLOW - 0870 ;GREEN 0880 LDA #$58 0890 LDX #$D8 0900 STA WSYNC 0910 STA COLPF1 0920 STX COLPF2 0930 ; 0940 ;ENABLE 1ST DLI 0950 LDA #$40 0960 STA DLILOW 0970 PLA 0980 TAX 0990 PLA 1000 RTI
10 ; 20 ;SET PLAYFIELD 30 ; 40 *=$2000 50 NEWCHB=$3C00 60 SCRNPL=$B0 70 SCRNPH=$B1 80 CHBSPL=$B2 90 CHBSPH=$B3 0100 FILRW1=$2200 0110 FILRW2=$2231 0120 FILRW3=$223C 0130 FILRW4=$2247 0140 HIGH1=$6C9 0150 ; 0160 ;SET CHAR TO A BLANK SPACE 0170 LDX #0 0180 LDA #$0 0190 SBLANK STA NEWCHB,X 0200 INX 0210 CPX #8 0220 BNE SBLANK 0230 ; 0240 ;SET CHAR 1 TO A SOLID SPACE 0250 LDA #$FF 0260 SSOLID STA NEWCHB,X 0270 INX 0280 CPX #16 0290 BNE SSOLID 0300 ; 0310 ;SCRNPL POINTS TO THE 0320 ;SCREEN MEMORY REGION 0330 LDA #$00 0340 STA SCRNPL 0350 LDA #$3E 0360 STA SCRNPH 0370 ; 0380 ;CLEAR SCREEN MEMORY REGION 0390 CLRSMR LDY #0 0400 LDA #0 0410 STRSMR STA (SCRNPL),Y 0420 INY 0430 BNE STRSMR 0440 LDX SCRNPH 0450 INX 0460 STX SCRNPH 0470 CPX #$3F ;SCREEN MEMORY 0480 BEQ CLRSMR 0490 ; 0500 ;PRINT "BALL - 0" ON TOP LINE 0510 LDA #$22 ;B 0520 STA $3E06 0530 LDA #$21 ;A 0540 STA $3E07 0550 LDA #$2C ;L 0560 STA $3E08 ;L 0570 STA $3E09 0580 LDA #$D ;- 0590 STA $3E0B 0600 LDA #$10 ;0 0610 ; 0620 ;DISPLAY SCORE (00000) 0630 STA $3E0D 0640 STA $3E17 0650 STA $3E18 0660 STA $3E19 0670 STA $3E1A 0680 STA $3E1B 0690 ; 0700 ;DISPLAY HIGH (XXXXX) 0710 LDX #0 0720 DSPHGH LDA HIGH1,X 0730 STA $3E21,X 0740 INX 0750 CPX #5 0760 BNE DSPHGH 0770 ; 0780 ;RESET SCREEN MEMORY POINTER 0790 LDA #$0 0800 STA SCRNPL 0810 LDA #$3E 0820 STA SCRNPH 0830 ; 0840 ;DRAW TOP WALL 0850 LDY #$2A 0860 LDA #1 0870 DRWTOP STA (SCRNPL),Y 0880 INY 0890 CPY #$3B 0900 BNE DRWTOP 0910 ; 0920 ;DRAW LEFT AND RIGHT WALLS 0930 DRWALS LDY #$3E 0940 DRWLFT LDA #1 0950 STA (SCRNPL),Y 0960 TYA 0970 CLC 0980 ADC #16 0990 TAY 1000 LDA #1 1010 DRWRGT STA (SCRNPL),Y 1020 TYA 1030 CLC 1040 ADC #4 1050 TAY 1060 SEC 1070 CMP #$F1 1080 BCC DRWLFT 1090 LDX SCRNPH 1100 INX 1110 STX SCRNPH 1120 CPX #$40 1130 BEQ TWOMOR 1140 LDY #6 1150 JMP DRWLFT 1160 ; 1170 ;PERFECT WALL 1180 TWOMOR LDA #$1 1190 STA $3EF2 1200 STA $3F02 1210 LDA #$0 1220 STA SCRNPL 1230 LDA #$3E 1240 STA SCRNPH 1250 ; 1260 ;LOAD EACH BRICK ROW WITH 1270 ;15 DISTINCT CHARACTERS 1280 ; 1290 ;ROW 1 GETS CHARS 4-12 1300 ;(#$40 IS ADDED FOR COLPF1) 1310 LDY #$67 1320 LDX #$44 1330 FIXRW1 TXA 1340 STA (SCRNPL),Y 1350 INX 1360 INY 1370 CPX #$53 1380 BNE FIXRW1 1390 ; 1400 ;ROW 2 GETS CHARS 13-21 1410 ;(#$80 IS ADDED FOR COLPF2) 1420 LDY #$A3 1430 LDX #$93 1440 FIXRW2 TXA 1450 STA (SCRNPL),Y 1460 INX 1470 INY 1480 CPX #$A2 1490 BNE FIXRW2 1500 ; 1510 ;ROW 3 USES CHARS 22-30 1520 ;(ADD #$40 FOR COLPF1) 1530 LDY #$DF 1540 LDX #$62 1550 FIXRW3 TXA 1560 STA (SCRNPL),Y 1570 INX 1580 INY 1590 CPX #$71 1600 BNE FIXRW3 1610 LDA #$3F 1620 STA SCRNPH 1630 ; 1640 ;ROW 4 USES CHARS 31-3F 1650 ;(ADD #$80 FOR COLPF2) 1660 LDY #$1B 1670 LDX #$B1 1680 FIXRW4 TXA 1690 STA (SCRNPL),Y 1700 INX 1710 INY 1720 CPX #$C0 1730 BNE FIXRW4 1740 ; 1750 ;CLEAR CHARACTER, BASE 1760 ;FROM $3C20-3DFF 1770 LDA #$20 1780 STA CHBSPL 1790 LDA #$3C 1800 STA CHBSPH 1810 LDY #0 1820 TYA 1830 CLRCHB STA (CHBSPL),Y 1840 INY 1850 BNE CLRCHB 1860 LDA #$3D 1870 STA CHBSPH 1880 LDA #0 1890 CHBTWO STA (CHBSPL),Y 1900 INY 1910 CPY #$E0 1920 BNE CHBTWO 1930 ; 1940 ;CHECK IF ANY ROWS HAVE BEEN 1950 ;CLEARED. IF THEY HAVE, THEN 1960 ;RESET THEM 1970 CHKRW1 LDA #$20 1980 STA CHBSPL 1990 LDA #$3C 2000 STA CHBSPH 2010 LDY #0 2020 GETRW1 LDA (CHBSPL),Y 2030 BNE CHKRW2 2040 INY 2050 CPY #120 ;CHECK 120 BRICKS 2060 BNE GETRW1 2070 JSR FILRW1 2080 CHKRW2 LDA #$98 2090 STA CHBSPL 2100 LDY #0 2110 GETRW2 LDA (CHBSPL),Y 2120 BNE CHKRW3 2130 INY 2140 CPY #120 2150 BNE GETRW2 2160 JSR FILRW2 2170 CHKRW3 LDA #$10 2180 STA CHBSPL 2190 LDA #$3D 2200 STA CHBSPH 2210 LDY #0 2220 GETRW3 LDA (CHBSPL),Y 2230 BNE CHKRW4 2240 INY 2250 CPY #120 2260 BNE GETRW3 2270 JSR FILRW3 2280 CHKRW4 LDA #$88 2290 STA CHBSPL 2300 LDY #0 2310 GETRW4 LDA (CHBSPL),Y 2320 BNE FINISH 2330 INY 2340 CPY #120 2350 BNE GETRW4 2360 JSR FILRW4 2370 FINISH RTS
10 ; 20 ;SHOULD BRICK ROWS BE RESET? 30 ; 40 *=$2200 50 CHBSPL=$B2 60 CHBSPH=$B3 70 BALSPD=$6D1 80 RSTFRQ=$6D2 90 ; 0100 ;MAKE CHARACTER BASE POINTER 0110 ;POINT TO BRICK ROW 1 0120 BRKROW LDA #$20 0130 STA CHBSPL 0140 LDA #$3C 0150 STA CHBSPH 0160 ; 0170 ;IS BRICK ROW CLEAR? 0180 SETY LDY #$0 0190 CHKROW LDA (CHBSPL),Y 0200 ; 0210 ;IF NOT THEN RETURN 0220 BNE NOTCLR 0230 INY 0240 CPY #$78 0250 BNE CHKROW 0260 ; 0270 ;IF SO, THEN REFILL BRICK ROW 0280 LDY #$0 0290 LDA #$FF 0300 FILROW STA (CHBSPL),Y 0310 INY 0320 CPY #$78 0330 BNE FILROW 0340 ; 0350 ;PRODUCE SOUND TO CORRESPOND 0360 ;WITH RESET 0370 LDA #$29 0380 STA RSTFRQ 0390 ; 0400 ;SPEED UP BALLS 0410 LDA BALSPD 0420 CMP #1 0430 BEQ NOTCLR 0440 SEC 0450 SBC #1 0460 STA BALSPD 0470 NOTCLR RTS 0480 ; 0490 ;MAKE CHARACTER BASE POINTER 0500 ;POINT TO BRICK ROW 2 0510 BRKRW2 LDA #$98 0520 STA CHBSPL 0530 LDA #$3C 0540 STA CHBSPH 0550 JMP SETY 0560 ; 0570 ;MAKE CHARACTER BASE POINTER 0580 ;POINT TO BRICK ROW 3 0590 BRKRW3 LDA #$10 0600 STA CHBSPL 0610 LDA #$3D 0620 STA CHBSPH 0630 JMP SETY 0640 ; 0650 ;MAKE CHARACTER BASE POINTER 0660 ;POINT TO BRICK ROW 4 0670 BRKRW4 LDA #$88 0680 STA CHBSPL 0690 LDA #$3D 0700 STA CHBSPH 0710 JMP SETY
10 ; 20 ;SET PLAYER/MISSILE GRAPHICS 30 ; 40 *=$2300 50 PMBASE=$D407 60 PMBSPL=$B4 70 PMBSPH=$B5 80 GRACTL=$D01D 90 DMACTL=$22F 0100 SIZEP0=$D008 0110 COLPM0=$2C0 0120 COLPM1=$2C1 0130 COLPM2=$2C2 0140 COLPM3=$2C3 0150 COLPF3=$2C7 0160 NMIEN=$D40E 0170 PADDL0=$270 0180 HPOSP0=$D000 0190 RANDOM=$D20A 0200 TEMP=$6A0 0210 PDLHPS=$6A3 0220 BALLS=$6AF 0230 NOMORE=$6C7 0240 LAUNCH=$6C3 0250 AVOID=$6AB 0260 BALIFE=$6A4 0270 BL1HPS=$6B0 0280 BL1VPS=$6B4 0290 BL1HDR=$6B8 0300 BL1VDR=$6BC 0310 ; 0320 ;ENABLE PLAYER/MISSILE DMA 0330 LDA #62 0340 STA DMACTL 0350 ; 0360 ;SET PLAYER (PADDLE) 0370 ;TO DOUBLE WIDTH 0380 LDA #1 0390 STA SIZEP0 0400 ; 0410 ;COLOR PADDLE ORANGE-GREEN 0420 LDA #$EF 0430 STA COLPM0 0440 ; 0450 ;COLOR BALLS WHITE 0460 LDA #$F 0470 STA COLPM1 0480 STA COLPM2 0490 STA COLPM3 0500 STA COLPF3 0510 ; 0520 ;SET P/M BASE TO $3000 0530 LDA #$30 0540 STA PMBASE 0550 ; 0560 ;ENABLE PLAYER/MISSILE GRAPHICS 0570 LDA #3 0580 STA GRACTL 0590 ; 0600 ;CLEAR P/M GRAPHICS TABLE 0610 LDA #$0 0620 STA PMBSPL 0630 LDA #$30 0640 STA PMBSPH 0650 LDY #0 0660 TYA 0670 CLRPMB STA (PMBSPL),Y 0680 INY 0690 BNE CLRPMB 0700 LDX PMBSPH 0710 INX 0720 STX PMBSPH 0730 CPX #$38 0740 BNE CLRPMB 0750 ; 0760 ;DRAW PADDLE 0770 LDA #$FF 0780 STA $34C4 0790 STA $34C5 0800 STA $34C6 0810 LDA #$FF 0820 STA $34DD 0830 STA $34DE 0840 STA $34DF 0850 ; 0860 ;MAKE SURE BALLS DON'T LAUNCH 0870 ;BEFORE THEIR TIME IS DUE 0880 LDA #0 0890 STA $6C4 ;LAUNCH+1 0900 STA $6C5 0910 STA $6C6 0920 ; 0930 ;WHEN NOMORE=1, NO MORE BALLS 0940 ;WILL BE LAUNCHED. NOMORE WILL 0950 ;BE SET TO 1 WHEN USER MISSES 0960 ;A BALL 0970 STA NOMORE 0980 ; 0990 ;BALLS HOLDS THE NUMBER OF BALLS 1000 ;ON THE FIELD AT ONE TIME 1010 ;THIS WILL BE INITIALIZED TO 1020 LDA #1 1030 STA BALLS 1040 ; 1050 ;SET EACH BALL TO A RANDOM 1060 ;HORIZONTAL POSITION 1070 ;BETWEEN #$4B AND #$BA 1080 LDX #0 1090 RNDHPS LDA RANDOM 1100 SEC 1110 CMP #$4B 1120 BCC RNDHPS 1130 CLC 1140 CMP #$BA 1150 BCS RNDHPS 1160 STA BL1HPS,X 1170 INX 1180 CPX #4 1190 BNE RNDHPS 1200 ; 1210 ;SET EACH BALL'S VERTICAL 1220 ;POSITION TO TOP OF FIELD 1230 LDX #0 1240 FIXVPS LDA #$2F 1250 STA BL1 VPS,X 1260 ; 1270 ;BALLS MUST AVOID BRICKS 1280 ;UNTIL THEY HIT THE PADDLE 1290 LDA #$70 1300 STA AVOID,X 1310 INX 1320 CPX #4 1330 BNE FIXVPS 1340 ; 1350 ;SET EACH BALL TO A RANDOM 1360 ;HORIZONTAL DIRECTION 1370 LDX #0 1380 RNDHDR LDA RANDOM 1390 AND #1 1400 STA BL1HDR,X 1410 INX 1420 CPX #4 1430 BNE RNDHDR 1440 ; 1450 ;ALL BALLS MUST MOVE DOWN 1460 ;WHEN THEY ARE LAUNCHED 1470 LDX #0 1480 FIXVDR LDA #1 1490 STA BL1VDR,X 1500 INX 1510 CPX #4 1520 BNE FIXVDR 1530 ; 1540 ;GIVE EACH BALL LIFE 1550 LDX #0 1560 ACTVTE LDA #1 1570 STA BALIFE,X 1580 INX 1590 CPX #4 1600 BNE ACTVTE 1610 ;HORIZONTAL PADDLE POSITION 1620 ;MUST CORRESPOND TO PADDLE 1630 PDLCNT LDA PADDL0 1640 LSR A 1650 CLC 1660 ADC #$46 1670 STA TEMP 1680 LDA #$FF 1690 SEC 1700 SBC TEMP 1710 SEC 1720 CMP #$B1 1730 BCC STRHPS 1740 LDA #$B1 1750 STRHPS STA HPOSP0 1760 ; 1770 ;THE POSITION OF THE PADDLE 1780 ;WILL BE NEEDED LATER 1790 STA PDLHPS 1800 RTS
“Closeout” is a fast action game which has been enjoyed by both children and adults.
This program just fits into a 16K Atari. Almost all lines contain multiple statements, so make no alterations unless you have a bigger machine.
There’s a huge sale going on at a local department store. You arrive at the multistory building hungry for bargains. Boldly you enter the store and look around — and see bargains galore. A real sale! You start gathering up sale items, but then become aware of a strange group of shoppers. Wherever you go, they follow you around. Soon you learn their true intentions — they are out to stop you at all costs, so they can have the store to themselves. What’s worse, they’re armed with ray guns from the Toy Department which are modified to work.
The object of “Closeout” is to snatch up as many sale items as possible while evading the hostile bargain hunters. Don’t let them get too close, because they’ll either capture you or shoot you. Some of them can shoot farther than others. You can shoot back with the slingshot you bought in the Sporting Goods Department (50 percent off), but since slingshots require two hands to shoot, you must drop 25 sale items each time you use it.
You have only one chance and about three minutes of play. Extra time is awarded for higher scores. The remaining time is indicated on the left, and colors change as time runs out (there can be up to nine different colors on the screen at a time). When your score surpasses 25 points, you can shoot your slingshot, but remember, it costs you 25 points. You can only shoot horizontally, by aiming the joystick and pressing the fire button. The best strategy is to shoot only when cornered.
After you have typed in the program, save it twice on a disk or tape, then type RUN. There will be a short initialization pause, and the screen will clear to GRAPHICS 7. The four players will appear, and the floors and stairways will be drawn. Short instructions will appear. Plug your joystick into port one. Press the fire button to start.
Your shopper is on the ground floor in the bottom left corner. Use the joystick to move left and right, or up and down stairs. You must be directly under the stairs to use them, and to exit onto a floor you must be standing exactly on it.
The program might run faster on U.S. Ataris than on my New Zealand model. American televisions use the NTSC standard, which allows 60 vertical blank interrupts per second, while New Zealand’s PAL standard allows only 50. On the other hand, the 6502 Central Processing Unit chip in our Ataris is clocked at three megahertz, as opposed to 1.8 MHz in U.S. Ataris, so the two factors might cancel each other out.
Good luck! I’d like to know who can better my score of 1200 points.
Since I omitted REM statements from the program to save space, here is a short explanation:
Line No. | Comments |
---|---|
10 | Initialize. Jump to line 209 to POKE in the P/M utility and player shapes, then to line 112 to wait for the trigger to be pressed to start the game. These jumps keep the lower numbered lines free for frequently accessed statements. |
20-23 | Check for your moves up the stairs. |
30-33 | Check for your moves down the stairs. |
37-44 | Check for enemy movement on the left stairs. |
55-59 | Check for enemy movement on the right stairs and also give the enemy some brainpower. |
60-65 | Check for enemy movement on the middle stairs. |
73-76 | Read joystick zero (leftmost slot) to determine your moves. Change this reading here and at two other locations if you want to use any other slot for the game. |
78 | Use BASIC LOCATE statement to determine points scored. |
79 | If the sale items run low, draw some more. |
80-82 | Determine movement of Player 2 — Enemy No. 1. |
84-86 | Determine movement of Player 3 — Enemy No. 2. |
87-89 | Determine movement of Player 4 — Enemy No. 3. |
90 | Check if you can shoot. |
93-95 | Check to see if you are in the enemy shooting range. Note: Some enemies can shoot farther than others. |
96 | Game timekeeper. |
97 | Go back to start of loop. |
100-101 | Draw dots — sale items. |
105-108 | Draw time bar graph and erase the portion of time that has run out; also award extra time for high scores. |
109-114 | You got shot! So these lines get you off the visible side of the screen, and wait for the trigger to be pressed to start a new game. |
209 | Only simple constants and variables are used in the program. These constants and variables are used all over the place to conserve RAM; they are also used for the line numbers. These make the program look very untidy, but this is the only way I can get this program to run on my 16K Atari. |
210-215 | POKE the P/M utility and players’ shapes and colors into RAM. |
216-225 | Constants and variables for the stairs and building levels; draw it out in Graphics 7. |
230 | Data for P/M graphics utility. |
236-237 | Last eight DATAs in line 236 and all of line 237 are for the P/M shapes. Change these if you like different shapes. |
“Ski!” is a fine-scrolling arcade-style game that lets you test your skill at electronic winter sports. It will run in 16K if you remove all REM statements. (Remove only the text; leave in the line number and REM.) Unfortunately, Ski! will not work on an XL-model computer, unless you plug in an Atari BASIC cartridge.
Ski down Pine Mountain and never leave the warmth of your home. That’s exactly what “Ski!” allows you to do.
The object of Ski! is to ski down the slalom course without running into any rocks, trees, or other obstacles while trying to go between the flags. Using a joystick plugged into the first port to control the skier, you “gobble up” bonus points planted in the snow. You can move the joystick left or right to turn. You can also position your player up or down to change difficulty, points, and maneuverability.
The higher you go, the faster the scene scrolls, and the more points you win. The higher speeds necessitate fast response. The novice will want to position himself a little below midway up the screen. That way, you have room to pull back if you need to duck. If you hit a rock, tree, or flag, you crash, and start over at the bottom of the screen. You lose fifty points for every crash.
Every time you play the game, a random ski course is generated. If you wish, you can see the screen scroll in reverse as the course is being laid out. Your computer will buzz when the game is ready to play. Press FIRE to begin.
Fine scrolling couples coarse scrolling (which moves the pointers to screen memory around) with a special feature of the ANTIC chip.
To fine scroll, you set a special bit in every line of the display list you wish to scroll. You then scroll one scan line at a time by storing numbers from 0-15 in VSCROL. When you reach the limit of ANTIC’s fine-scrolling resolution (8 scan lines in GRAPHICS 1), you reset VSCROL and then coarsely scroll a full eight scan lines. Coarse scrolling is described in COMPUTE!’s Second Book of Atari. Machine language is required for fine scrolling, since you must reset VSCROL and perform the coarse scroll almost simultaneously, or else you get a jumpy, unpleasant display.
The fine-scrolling routine could be written as a USR statement, but BASIC would have to call it every time a scroll was needed, and this would be too slow. We need to periodically update the screen in a way that’s not dependent on BASIC.
The Vertical Blank Interrupt (VBI) is perfect for this task. Every l/60th of a second, the scroll routine is called to update the screen. BASIC can control the speed with memory location zero. POKEing a number from 1-255 controls the speed from one (fastest) to 255. A zero will stop the scrolling, although the vertical blank routine will still be “hooked up.” BASIC sets up the VBLANK scrolling routine by passing the address of the Load Memory Scan counter to change in the display list (which can be found on a normal screen with LMS=PEEK(560)+256*PEEK(561)+4) and the number of lines to scroll. BASIC can PEEK location 1 to see how many full lines still need to be scrolled.
The VBLANK routine will stop scrolling when it runs out of lines, and memory location 1 will hold a zero. You could use the machine language routine in your own programs, but since it is not general-purpose, you will be limited to unidirectional scrolling in GRAPHICS 1. Be sure to use the “disable routine” (A=USR(1638)) to remove the VBI routine from the system.
It’s not mentioned anywhere as far as I know, but the address of the start of your screen memory for fine scrolling should start on a 4K boundary. ANTIC apparently cannot cross a 4K boundary, so if your screen buffer (that holds the rocks, trees, etc.) is too long, ANTIC can get confused and start displaying nonsense. Another thing to watch for: when using a vertical blank routine, be sure to include a CLD (Clear Decimal) at the start of the program. If you don’t, your arithmetic will be foiled every time BASIC calls the floating point routines (which use BCD math).
Strings are used extensively in the BASIC program, to prevent memory conflicts. A string is used to hold the display list, the screen memory area, the player/missile memory, and the shapes for the player. The screen memory area and the player/ missile address are insured to be on proper page boundaries by modification of the Variable Value Table. Because of this, line 100 must be typed first, in order for the program to work properly.
It is extremely important that you follow these typing instructions carefully. (It is a good idea to read all the directions first.)
“Thunderbird” offers a challenge for the experienced game player as well as the novice.
“Thunderbird” will demand your undivided attention and 16K of memory. The object of Thunderbird is to score as high as possible. Using a joystick you move the bird left and right, using it to bounce a ball into a wall of bricks. The object of the game is to clear out all the bricks, without letting the ball escape past you. A 1,000 point bonus is awarded when you break out the bottom of the wall (a “breakthrough”); and if you’re really good, you get 10,000 points for clearing out all the bricks (no mean feat).
The Thunderbird can unleash the most awesome power of nature — lightning — at the touch of a button (the fire button). Thunderbird will “beam down” several luminous “tiles” that serve to deflect the ball downward when hit. You can lay down tiles like a cap over a hole the ball has created, to force it to widen the hole. Every time the ball hits a tile, it swoops downward, but 25 points are subtracted from your score. That should discourage overuse of this miraculous feature.
Here’s a bit of information about the programming. The playing field is a mixed-mode display consisting of two rows of GRAPHICS 1 text and 21 rows of a multicolored character mode, IRG 4. This lets us have multicolored bricks.
Player/missile graphics are used to represent the bird, which can be any of three sizes, depending on the skill level. The bird is moved left and right by a small machine language routine that is executed every 1/60 second during the TV’s vertical blank (when the electron beam is traveling from the lower right-hand corner to the upper left-hand corner of the screen).
IRG mode 4, the multicolor mode, is quite interesting. A single character can be any of three colors. To design these colored characters, divide the character horizontally into four two-bit zones. Each two-bit block controls one pixel of color within the character (a multicolor character’s resolution is 4×8). No color would be 00, color one is 01, two 10, and three 11 (simple two-bit binary). For example, one of the bricks consists of several colored bands:
1110 2220 3330 1110 2220 3330 1110 0000
01010100 10101000 11111100 01010100 10101000 11111100 01010100 00000000
Such a “custom character” would look strange on a normal screen (although you would see some semblance of multicolors, due to artif acting). But when displayed on either an IRG 4 or IRG 5 mode screen, each character is like a tiny 4×8 block of GRAPHICS 7 pixels. Also, any character printed in inverse (with the Atari logo key) will look different. The COLOR 3 pixels in such a character will be displayed as COLOR 4 (normally available only in GRAPHICS 1 or 2).
To create an IRG 4 screen, you must replace the bytes for GRAPHICS 0 by modifying the display list. Luckily, the resolution of IRG 4 is identical to GRAPHICS 0, 40×24.
DL=PEEK(560)+256*PEEK(561)+4 POKE DL-1,4+64 FOR I=2 TO 24:POKE DL+I,4:NEXT I
See lines 160-180 of Thunderbird. You can also try out IRG 5, which displays these characters in double height (40×12).
“Shoot” is a machine language arcade-style game that must be initialized on a 16K or greater Atari with or without DOS, but will run on any Atari, even an Atari with 8K of RAM.
This game must be entered using the “Machine Language Editor: MLX” program found in Appendix C. Please refer to Appendix C before typing in this program.
Once you have typed in and SAVEd “Shoot,” LOADing the program is simple. With the MLX you have created a boot tape or a boot disk. What is a boot tape or disk? It is the name of a tape or disk that has a machine language program on it, along with information to tell the Atari how to load it into memory and where to jump to begin execution. You can think of a boot tape as a do-it-yourself ROM pack, since you need not have BASIC (or any other cartridge) installed in your Atari at the time you boot up the system.
If you have a boot disk, simply turn on your disk drive. When the busy light goes out, insert the boot disk of Shoot and turn on the Atari. A few seconds later the title screen will appear.
If you have a boot tape, simply place it in the program recorder and rewind to the beginning. Press the Play button on the recorder. Open the lid and remove the BASIC cartridge. Turn off all the peripherals (especially all 815s, 810s and 850s) except for the cassette recorder. Turn off the Atari, press down on the START button, and turn it back on. It should beep once, which is your signal to press the RETURN key and wait. The boot tape will load into the RAM of your Atari. Once there, the cassette will stop and the game will begin.
First you will see a copyright message which will last for about 8 to 12 seconds. Then the message will disappear and three zeros will appear. The left (green) one is your score. The middle (red) one is your high score. The right (yellow) one is time remaining. Plug a joystick into controller jack 1 (far left) and press the START button.
Shazam! Eight rows of assorted sizes and colors of airplanes, helicopters, and saucers will start flying hither and yon across the screen. Push the joystick left and right to aim the gun, press the button to fire the missile, then use the joystick to guide the missile into one of the planes. If you miss, try again. If you hit the plane, it will explode and you will score some points: Helicopter — 5 points, Plane — 10 points, Saucer — 25 points. Clearing a rack of planes within 30 seconds gives you a bonus of 50 points. If you take more than 30 seconds to clear a rack of planes, the game will give you another full rack of planes immediately. For every 15 points you score you get an additional second of play time. When the timer goes to zero, your game ends, the high score is adjusted, and the program waits for you to press on the console buttons: press START to restart the game.
Well, that’s Shoot in a nutshell. Enjoy the game.
The Machine Language Editor (MLX) was written to help you type in long machine language programs without making mistakes. MLX will not allow you to enter in the DATA incorrectly.
It may at first seem like a lot of extra typing, but in the long run it will save you a great deal of time. The MLX will ask you to enter in three numbers; the prompts should be answered this way: Starting Address? 4096; Ending Address? 5240; Run/Init Address? 4118. Then you will be prompted to start entering DATA. Just enter the DATA for the correct line from the listing that follows. MLX will not let you enter an incorrect number. It will not even let you enter the correct DATA for a different line.
4096:000,009,000,016,008,016,049 4102:024,096,169,060,141,002,242 4108:211,169,022,133,010,169,214 4114:016,133,011,096,076,078,172 4120:018,112,112,112,070,000,192 4126:024,240,112,240,112,240,230 4132:112,240,112,240,112,240,068 4138:112,240,112,240,112,240,074 4144:112,240,112,240,112,065,161 4150:025,016,040,067,041,049,036 4156:057,056,049,032,074,032,104 4162:072,032,080,065,076,069,204 4168:086,073,067,072,128,144,130 4174:130,146,132,148,134,150,150 4180:136,152,200,008,024,040,132 4186:056,072,088,104,120,128,146 4192:056,056,216,000,144,144,200 4198:216,072,040,112,108,124,006 4204:124,253,000,254,254,253,222 4210:255,003,002,254,000,000,116 4216:025,010,010,010,025,005,205 4222:025,010,009,010,011,000,191 4228:001,001,001,000,000,000,135 4234:001,000,001,001,000,001,142 4240:255,000,000,003,006,012,164 4246:028,060,126,255,000,192,043 4252:096,048,056,060,126,255,029 4258:000,024,024,024,024,060,062 4264:126,255,000,000,248,032,061 4270:242,158,144,240,000,000,190 4276:031,004,079,121,009,015,183 4282:000,000,001,013,063,127,134 4288:024,000,000,000,128,176,008 4294:252,254,024,000,000,024,240 4300:036,126,129,126,000,000,109 4306:001,005,000,008,255,005,228 4312:000,000,002,010,001,024,253 4318:254,010,001,016,003,025,019 4324:000,032,253,025,000,032,058 4330:072,138,072,166,176,232,066 4336:189,076,016,141,010,212,116 4342:141,026,208,166,176,173,112 4348:008,208,041,001,240,019,001 4354:169,000,157,098,016,157,087 4360:109,016,189,120,016,024,226 4366:101,177,133,177,141,030,005 4372:208,232,134,176,189,098,033 4378:016,024,125,109,016,157,217 4384:098,016,141,000,208,189,172 4390:087,016,141,018,208,189,185 4396:131,016,141,008,208,104,140 4402:170,104,064,165,177,208,170 4408:008,169,128,141,003,210,203 4414:076,144,017,056,233,001,077 4420:133,177,169,138,141,003,061 4426:210,162,005,189,000,024,152 4432:024,105,001,009,016,157,136 4438:000,024,201,026,208,009,042 4444:169,016,157,000,024,202,148 4450:076,077,017,165,183,208,056 4456:039,166,181,232,134,181,013 4462:224,015,208,030,162,000,237 4468:134,181,162,005,189,014,033 4474:024,024,105,001,009,144,173 4480:157,014,024,201,154,144,054 4486:009,169,144,157,014,024,139 4492:202,076,120,017,166,182,135 4498:232,134,182,224,060,208,162 4504:034,162,000,134,182,165,061 4510:183,208,046,162,005,189,183 4516:014,024,056,233,001,009,245 4522:144,157,014,024,201,159,101 4528:208,009,169,153,157,014,118 4534:024,202,076,163,017,169,065 4540:000,162,006,029,013,024,166 4546:202,208,250,041,015,201,087 4552:000,208,004,169,001,133,203 4558:183,169,000,133,077,173,173 4564:120,002,074,074,170,189,073 4570:142,016,133,179,202,138,004 4576:010,010,010,170,160,000,072 4582:189,146,016,153,096,026,088 4588:200,153,096,026,232,200,119 4594:192,016,208,240,165,178,217 4600:024,101,179,133,178,141,236 4606:004,208,165,180,240,038,065 4612:170,169,000,157,128,025,141 4618:202,240,017,165,177,208,251 4624:018,134,180,169,255,157,161 4630:128,025,142,000,210,076,091 4636:042,018,134,180,076,042,008 4642:018,162,000,142,000,210,054 4648:134,180,165,183,208,022,164 4654:173,132,002,208,017,165,231 4660:180,208,013,169,098,133,085 4666:180,165,179,010,010,024,114 4672:105,132,133,178,169,255,012 4678:133,176,141,030,208,076,066 4684:095,228,169,168,141,001,110 4690:210,169,128,141,003,210,175 4696:169,000,141,000,210,169,009 4702:048,141,002,210,162,128,017 4708:169,000,157,255,025,157,095 4714:127,025,202,208,247,169,060 4720:000,162,008,157,255,207,133 4726:202,208,250,169,046,141,110 4732:047,002,169,024,141,007,002 4738:212,169,003,141,029,208,124 4744:169,016,013,111,002,141,076 4750:111,002,141,027,208,169,032 4756:000,133,180,169,001,133,252 4762:183,169,064,141,014,212,169 4768:169,016,141,049,002,169,194 4774:025,141,048,002,169,016,055 4780:141,001,002,169,234,141,092 4786:000,002,162,017,160,053,060 4792:169,006,032,092,228,169,112 4798:192,141,014,212,169,198,092 4804:141,196,002,169,054,141,131 4810:197,002,169,024,141,198,165 4816:002,169,010,141,199,002,219 4822:162,020,189,055,016,032,176 4828:014,020,009,192,157,255,099 4834:023,202,208,242,165,019,061 4840:024,105,003,197,019,208,020 4846:252,162,020,169,000,157,230 4852:255,023,202,208,250,169,071 4858:016,141,005,024,169,080,173 4864:141,012,024,169,144,141,119 4870:019,024,169,001,133,183,023 4876:169,008,141,031,208,173,230 4882:031,208,201,001,208,006,161 4888:032,042,020,076,078,018,034 4894:201,006,208,239,169,000,085 4900:162,006,157,013,024,157,043 4906:255,023,202,208,247,169,122 4912:145,141,017,024,169,146,178 4918:141,018,024,169,144,141,179 4924:019,024,169,016,141,005,178 4930:024,169,000,133,183,133,196 4936:177,133,182,133,181,162,016 4942:024,160,000,032,197,019,254 4948:200,192,008,208,248,162,078 4954:007,160,208,169,003,141,010 4960:042,002,032,092,228,169,149 4966:192,141,014,212,173,042,108 4972:002,208,003,076,077,019,237 4978:160,008,169,000,025,108,072 4984:016,136,208,250,201,000,163 4990:208,010,169,050,024,101,176 4996:177,133,177,076,077,019,023 5002:165,183,240,220,165,019,106 5008:024,105,002,197,019,208,187 5014:252,162,000,189,007,024,016 5020:041,031,221,000,024,240,201 5026:005,176,008,076,176,019,110 5032:232,224,006,208,236,076,126 5038:008,019,162,006,189,255,045 5044:023,041,031,009,064,157,249 5050:006,024,202,208,243,076,177 5056:008,019,080,007,000,142,192 5062:194,019,140,195,019,173,170 5068:010,210,041,007,201,006,167 5074:176,247,010,010,170,189,244 5080:210,016,153,109,016,189,141 5086:211,016,153,120,016,189,159 5092:212,016,153,131,016,169,157 5098:000,153,098,016,189,213,135 5104:016,170,172,194,019,169,212 5110:008,141,196,019,189,170,201 5116:016,153,000,026,232,200,111 5122:206,196,019,208,243,152,002 5128:170,172,195,019,096,053,201 5134:140,013,020,168,138,072,053 5140:152,042,042,042,042,041,125 5146:003,170,152,041,159,029,068 5152:246,254,168,104,170,152,102 5158:172,013,020,096,162,032,021 5164:169,012,157,066,003,032,227 5170:086,228,169,020,157,069,011 5176:003,169,117,157,068,003,061 5182:169,003,157,066,003,169,117 5188:008,157,074,003,169,128,095 5194:157,075,003,032,086,228,143 5200:169,000,157,068,003,169,134 5206:016,157,069,003,169,120,108 5212:157,072,003,169,004,157,142 5218:073,003,169,011,157,066,065 5224:003,032,086,228,169,012,122 5230:157,066,003,032,086,228,170 5236:096,067,058,155,000,224,204
By now you’ve probably typed in, played, and admired some of the games in this book. In time, perhaps some of them will be counted among your favorites. If so, then COMPUTE!’s First Book of Atari Games has succeeded. Our main goal was simply to provide more than a dozen fun games for about a third of the cost of one commercial computer game. You can stop right here and have your money’s worth.
But this book could be something more. Once you realize that these games were written not by professional programmers, but rather by ordinary hobbyists who probably had never touched a computer in their lives until they bought one, it’s not so hard to picture yourself writing games, too.
Unfortunately, too many people dismiss this idea, besieged by self-doubts. “I’ll never be able to program like that,” they complain. “I don’t know anything about computers. And math was my worst subject in school.”
Almost always you will hear this kind of statement from adults. Meanwhile, grade school children and teenagers are developing into crack programmers. Two years ago most of them knew nothing about computers either, but they learned. And some of them are flunking math, too. It should be common knowledge by now that mathematics and technical genius have very little to do with computer programming.
Instead, good programmers tend to be people who are creative, have a willingness to learn new things in an exploratory way, and can think logically.
We’re not saying that everyone can be a good computer programmer. But many more can than you might suspect. Don’t be afraid to see if this includes you.
One reason people are reluctant to attempt game programming — admittedly one of the most difficult types of programming — is their fear of machine language. Virtually all commercial games these days are programmed in machine language because BASIC is just too slow. But the fact is, many good games have been written in BASIC. There are clever ways to get around machine language if you want.
The games in this book are perfect examples. They cover a very wide range of styles and techniques. A few, such as “Blockade,” are written entirely in straightforward BASIC — easily within reach of the beginning-to-intermediate home programmer. Blockade has been in my personal program library since I first typed it in from COMPUTE! more than two years ago. It’s been played as many hours as some commercial games for which I paid $35.
On the other hand, there are games such as “Chiseler” and “Shoot” which are written completely in machine language. They are the work of advanced programmers, and are as fast and as fun as any games on the commercial software market.
Between these two extremes are games such as “Ski!,” “Thunderbird,” and “Closeout,” hybrids of BASIC and machine language. Closeout is a particularly good example, because the author was not a machine language programmer. He used a machine language routine published in COMPUTE!, a routine easily used by BASIC programmers who know little or nothing about machine language. If you decide to try your hand at game programming, one of your first goals should be to acquire a “subroutine library” stocked with routines of this type. You’ll also need to start collecting magazines and books with important information about your computer.
A couple of years ago the information cupboard for Atari computers was very bare. The machines were new, the idea of home computers was new, and hardware prices were very high. This meant the Atari market was very small. At first it was difficult to find out even the simplest facts about the computers. Some of the Atari’s most powerful features — such as player/missile graphics and programmable characters — were not even mentioned in the standard manuals (and still aren’t). Home programmers were wandering in the dark.
Today, though, the market abounds with good software, books, and magazines. If you really want to learn, almost all the information is out there, somewhere. Not all of it is explained as clearly as it could be, but usually it’s decipherable. At least, for the most part, it’s available.
But now aspiring programmers are faced with a new problem — with so much information available; it’s hard to choose. Which books are clearly written, and which are jusl plain confusing? Which material is suitable for beginners, or intermediates, or advanced programmers? Which books should be read first? Which of the additional manuals sold by Atari are really worth buying?
We can’t tackle all of these questions here, but we can recommend sources for further reading and experimenting if you want to start programming your own games. This list includes material which covers a range of skills, from beginning to advanced. Naturally, some of these items are from COMPUTE! Publications. But some are sold by our competitors, too. This shouldn’t be construed as an endorsement, but rather as a list of reliable sources, a starting point for your own explorations.
*Atari, Inc. Atari Personal Computer Operating System. Sunnyvale, CA: Atari, Inc., 1980.
*__________. Atari Personal Computer System Hardware Manual. Sunnyvale, CA: Atari, Inc., 1980.
Carris, Bill. Inside Atari BASIC. Reston, VA: Reston Publishing Co., Inc., 1983.
Chadwick, Ian. Mapping the Atari. Greensboro, NC: COMPUTE! Books, 1983.
*Chen, Amy and others. De Re Atari. Sunnyvale, CA: Atari, Inc., 1981.
Editors of COMPUTE!. COMPUTE!’s First Book of Atari. Greensboro, NC: COMPUTE! Books, 1981.
*_______. COMPUTE!’s First Book of Atari Graphics. Greensboro, NC: COMPUTE! Books, 1982.
*_______. COMPUTE!’S Second Book of Atari. Greensboro, NC: COMPUTE! Books, 1982.
Inman, Don and Kurt Inman. The Atari Assembler. Reston, VA: Reston Publishing Co., Inc., 1981.
*Leventhal, Lance A. 6502 Assembly Language Programming. Berkeley, CA: Osborne/McGraw-Hill, 1979.
Mansfield, Richard. Machine Language for Beginners. Greensboro, NC: COMPUTE! Books, 1983.
Moore, Herb, Judy Lower, and Bob Albrecht. Atari Sound and Graphics, A Self-teaching Guide. New York: John Wiley & Sons, Inc., 1982.
Poole, Lon, Martin McNiff, and Steven Cook. Your Atari Computer. Berkeley, CA: Osborne/McGraw-Hill, 1982.
Sherer, Robin. Tricky Tutorial #1: Display Lists. Soquel, CA: Educational Software, Inc., 1981.
*_______. Tricky Tutorial #2: Horizontal and Vertical Scrolling. Soquel, CA: Educational Software, Inc., 1981.
Sherer, Robin Alan, Bill Bryner. Tricky Tutorial #5: Player Missile Graphics. Soquel, CA: Educational Software, Inc., 1982.
*Wilkinson, Bill. The Atari BASIC Sourcebook. Greensboro, NC: COMPUTE! Books, 1983.
*Zaks, Rodnay. Programming the 6502. Berkeley, CA: Sybex, Inc., 1980.
A computer cannot perform any task by itself. Like a car without gas, a computer has potential, but without a program, it isn’t going anywhere. Most of the programs published in COMPUTE!’s First Book of Atari Games are written in a computer language called BASIC. Atari 8K BASIC is easy to learn.
Computers can be picky. Unlike the English language, which is full of ambiguities, BASIC usually has only one “right way” of stating something. Every letter, character, or number is significant. A common mistake is substituting a letter such as “O” for the numeral “0”, a lowercase “l” for the numeral “1”, or an uppercase “B” for the numeral “8”. Also, you must enter all punctuation such as colons and commas just as they appear in the book. Spacing can be important. To be safe, type in the listings exactly as they appear.
The exception to this typing rule is when you see the braces, such as “{DOWN}”. Anything within a set of braces is a special character or characters that cannot easily be listed on a printer. When you come across such a special statement, refer to the section of this book entitled “Listing Conventions.”
Some programs contain a section or sections of DATA statements. These lines provide information needed by the program. Some DATA statements contain actual programs (called machine language); others contain graphics codes. These lines are expecially sensitive to errors.
If a single number in any one DATA statement is mistyped, your machine could “lock up,” or “crash.” The keyboard, break key, and RESET keys may all seem “dead,” and the screen may go blank. Don’t panic — no damage is done. To regain control, you have to turn off your computer, then turn it back on. This will erase whatever program was in memory, so always SAVE a copy of your program before you RUN it. If your computer crashes, you can LOAD the program and look for your mistake.
Sometimes a mistyped DATA statement will cause an error message when the program is RUN. The error message may refer to the program line that READs the data. This error is still in the DATA statements, though.
You should familiarize yourself with your computer before attempting to type in a program. Learn the statements you use to store and retrieve programs from tape or disk. You’ll want to save a copy of your program, so that you won’t have to type it in every time you want to use it. Learn to use the machine’s editing functions. How do you change a line if you made a mistake? You can always retype the line, but you at least need to know how to backspace. Do you know how to enter inverse video, lowercase, and control characters? It’s all explained in your computer’s manuals.
Remember the last time you typed in a long machine language program? You typed in hundreds of DATA statements, numbers, and commas. Even then, you couldn’t be sure if you’d typed it in right. So you went back, proofread, tried to run the program, crashed, went back and proofread again, corrected a few typing errors, ran again, crashed, rechecked your typing … Frustrating, wasn’t it?
Until now, though, that has been the best way to enter machine language into your machine. Unless you happen to own the Assembler Editor cartridge and are willing to wrangle with machine language on the assembly level, it is much easier to enter a BASIC program that reads the DATA statements and POKEs the numbers into memory.
Some of these “BASIC loaders” will use a checksum to see if you’ve typed the numbers correctly. The simplest checksum is just the sum of all the numbers in the DATA statements. If you make an error, your checksum will not match up. Some programmers have made your task easier by creating checksums every ten lines, so you can zero in on your errors. There is a problem with BASIC loaders, however.
Sometimes a program should reside in low memory, which is where BASIC stores its BASIC programs (including the loader). If the loader was RUN, it would destroy itself as it POKEd the machine language into memory. Sometimes a cassette user will create a program that resides in the same area of memory ($0700-$1EFF, approximately) as the Disk Operating System on disk-based machines.
To get around the low memory problem, some BASIC loaders will directly create the loadable object file (binary file). You can then go to DOS and load the file with menu selection L, or name the file AUTORUN.SYS and have it boot up with the DOS. But this excludes the cassette-based Atari users.
Both of the high-quality machine language programs in this book have this problem. “Shoot” got around it by creating a “boot tape” that cassette users could load as conveniently as CLOAD. Unfortunately, many disk owners don’t have a tape drive. “Chiseler” was meant to be entered by assembling it with the Assembler Editor cartridge and run from that environment. For the novice, this is too difficult, and since Chiseler resides in low memory, your average BASIC loader can’t cope with it.
MLX was designed to solve these problems. It is a great way to enter all those long machine language programs with a minimum of fuss. MLX lets you enter the numbers from a special list that looks similar to BASIC DATA statements. It checks your typing on a line-by-line basis. It won’t let you enter illegal characters when you should be typing numbers. It won’t let you enter numbers greater than 255. It will prevent you from entering the wrong numbers on the wrong line. In short, MLX will make proofreading obsolete!
In addition, MLX will generate a ready-to-use boot tape or boot disk. It also has an option to create binary files for DOS users. A boot disk is like those commercial games you buy. You just insert the disk, remove any cartridges, and turn on your computer. The game will then automatically load.
Using a boot tape is almost as simple. Just insert it into your player, rewind, press PLAY. Hold down the START key while turning on your computer until you hear a beep (like the one you hear with CLOAD). Then press a key on the keyboard, and the program will automatically load and run.
Incidentally, the binary file option is more useful for utilities than games. Binary files are loaded from the DOS menu (selection L) or automatically if the file is named “AUTORUN.SYS”. If you can’t stand the thought of putting only one game on each disk (as with boot disks), you can place several binary file machine language games on one disk. This option is not workable with Shoot, since the program would overwrite DOS.
Type in and SAVE MLX (you’ll want to use it in the future). When you’re ready to key in the ML program, RUN it. The program will ask you for three addresses: the start address, the ending address, and the run address. These numbers should be: 4096, 5240, 4118, respectively, for Shoot, and 8192, 11136, 10240 for Chiseler. If you get stuck, refer to the screen dumps below.
Starting Address?4656 Ending Address?5248 Run/Init Address?4118 Tape or Disk:
Starting Address?8192 Ending Address?11136 Run/Init Address?l9240 Tape or Disk:
After you enter the addresses, you’ll be asked to press either T for boot tape, or D for disk. If you press D, you’ll be asked if you want to generate a boot disk (press D) or a binary file (press F).
You’ll then get the prompt:
4096: (for Shoot) or
8192: (for Chiseler)
The prompt is the current line you are entering from the listing. Each line is six numbers plus a checksum. If you enter any of the six numbers wrong, or enter the checksum wrong, the Atari will ring the buzzer and prompt you to re-enter the line. If you enter it correctly a pleasant bell tone will sound and you can enter the next line.
You are not using the normal Atari editor with MLX. For example, it will only accept numbers as input. If you need to make a correction, press the <DELETE/BACK S> key; the entire number is deleted. You can press it as many times as necessary back to the start of the line. If you enter three-digit numbers as listed, the computer will automatically print the comma and go on to accept the next number. If you enter less than three digits, you can press either the comma, SPACE bar, or RETURN key to advance to the next number. When you get to the checksum value, the Atari will emit a low drone to remind you to be careful. The checksum will automatically appear in inverse video; don’t worry, and don’t press the logo key to un-reverse it. It’s highlighted for emphasis.
When testing MLX, I’ve found it to be extremely easy to enter long listings. With the audio cues provided, you don’t even have to look at the screen if you’re a touch-typist. And if you have the Atari CX85 Numerical Keypad, you’re really on easy street!
When you get through typing, assuming you type it all in one session, you can then save the completed and bug-free program to tape or disk. Follow the screen instructions. With a boot disk, the program will offer to format the disk. If you press Y (yes), be sure you have a blank disk in drive one — not your program disk! After the file is written, the program will end, and you can proceed to boot up your tape or disk (you may need to remove the BASIC cartridge). Now if you get any errors while writing, you probably have a bad tape or disk, or the disk was full (binary file), or you’ve made a typo somewhere in the MLX itself.
What if you don’t want to enter the whole program in one sitting? MLX lets you enter as much as you want, save the whole schmeer, and then reload the boot tape, boot disk, or binary file when you want to continue. MLX recognizes these few commands:
CTRL-S: Save
CTRL-L: Load
CTRL-N: New Address
CTRL-D: Display
Hold down CTRL while your press the appropriate key. You will jump out of the line you’ve been typing, so I recommend you do it at a new prompt. Use the Save command to save what you’ve been working on. MLX will write the boot tape or disk file as if you’ve finished, but the boot tape or disk won’t run, of course, until you finish the typing. Remember what address you stop on. The next time you RUN MLX, answer all the prompts as you did before, then insert the disk or tape. When you get to the entry prompt (4096: or 8192:), press CTRL-L to reload the file into memory. You’ll then use the New Address command to resume typing.
After you press CTRL-N, enter the address where you previously stopped. The prompt will change, and you can then continue typing. Always enter a New Address that matches up with one of the line numbers in the special listing, or else the checksum won’t match up. You can use the Display command to display a section of your typing. After you press CTRL-D, enter two addresses within the line number range of the listing. You can abort the listing by pressing any key.
4096: Display :From?4096 To?4118 4096:000,009,009,016,008,016 4102:024,096,169,060,141,002 4108:211,169,022,133,010,169 4114:016,133,011,696,076,078 4096:000,009,000,016,008,016,052 Incorrect 4096:000,009,000,016,008,016,049 4102: 4102: 4102: New Address?4114 4114:016,133,011,096,
The special commands may seem a little confusing, but as you work with MLX, they will become valuable. For example, what if you forgot where you stopped typing? Use the Display command to scan memory from the beginning to the end of the program. When you see a bunch of zeros, stop the listing (press a key) and continue typing where the zeros start. Chiseler contains many sections of zeros. To avoid typing them, you can use the New Address command to skip over the blocks of zeros. Be careful, though; you don’t want to skip over anything you should type.
You can use the SAVE and LOAD commands to make copies of the completed game. Use the LOAD command to reLOAD the boot tape or disk, then insert a new tape or disk and use the Save command to create a new copy.
Programmers will find MLX interesting. It contains many useful input/output subroutines such as high-speed save/recall of a huge string (BUFFER$), a sector input/output subroutine, and a sector control routine. Be careful, though; you could accidentally wipe out a disk with the sector routines if you don’t use them correctly.
I hope you will find MLX to be a true labor-saving program. Since it has been tested by entering actual programs, you can count on it as an aid for generating bug-free machine language. Be sure to save MLX; it will be used for future applications in both COMPUTE! Magazine and COMPUTE! Books.
100 GRAPHICS 0:DL=PEEK(560)+256*PEEK(561)+4:POKE DL-1,71:POKE DL+2,6 110 POSITION 8,0:? "MLX":POSITION 23,0:? "failsafe entry":POKE 710,N:? 120 ? "Starting Address";:INPUT BEG:? " Ending Address";:INPUT FIN:? "Run/Init ADDRESS";:INPUT STARTADR 130 DIM A(6),BUFFER$(FIN-BEG+127),T$(20),F$(20),CIO$(7),SECTOR$(128),DSKINV$(6) 140 OPEN #1,4,0,"K:":? :? ,"Tape or Disk:"; 150 BUFFER$=CHR$(0):BUFFER$(FIN-BEG+30)=BUFFER$:BUFFER$(2)=BUFFER$:SECTOR$=BUFFER$ 160 ADDR=BEG:CIO$="hhh*LVd" 170 GET #1,MEDIA:IF MEDIA<>84 AND MEDIA<>68 THEN 170 180 ? CHR$(MEDIA):? :IF MEDIA<>ASC("T") THEN BUFFER$="":GOTO 250 190 BEG=BEG-24:BUFFER$=CHR$(0):BUFFER$(2)=CHR$(INT((FIN-BEG+127)/128)) 200 H=INT(BEG/256):L=BEG-H*256:BUFFER$(3)=CHR$(L):BUFFER$(4)=CHR$(H) 210 PINIT=BEG+8:H=INT(PINIT/256):L=PINIT-H*256:BUFFER$(5)=CHR$(L):BUFFER$(6)=CHR$(H) 220 FOR I=7 TO 24:READ A:BUFFER$(I)=CHR$(A):NEXT I:DATA 24,96,169,60,141,2,211,169,0,133,10,169,0,133,11,76,0,0 230 H=INT(STARTADR/256):L=STARTADR-H*256:BUFFER$(15)=CHR$(L):BUFFER$(19)=CHR$(H) 240 BUFFER$(23)=CHR$(L):BUFFER$(24)=CHR$(H) 250 IF MEDIA<>ASC("D") THEN 360 260 ? :? "Boot Disk or Binary File:"; 270 GET #1,DTYPE:IF DTYPE<>68 AND DTYPE<>70 THEN 270 280 ? CHR$(DTYPE):IF DTYPE=70 THEN 360 290 BEG=BEG-30:BUFFER$=CHR$(0):BUFFER$(2)=CHR$(INT((FIN-BEG+127)/128)) 300 H=INT(BEG/256):L=BEG-H*256:BUFFER$(3)=CHR$(L):BUFFER$(4)=CHR$(H) 310 PINIT=STARTADR:H=INT(PINIT/256):L=PINIT-H*256:BUFFER$(5)=CHR$(L):BUFFER$(6)=CHR$(H) 320 RESTORE 330:FOR I=7 TO 30:READ A:BUFFER$(I)=CHR$(A):NEXT I 330 DATA 169,0,141,231,2,133,14,169,0,141,232,2,133,15,169,0,133,10,169,0,133,11,24,96 340 H=INT(BEG/256):L=BEG-H*256:BUFFER$(8)=CHR$(L):BUFFER$(15)=CHR$(H) 350 H=INT(STARTADR/256):L=STARTADR-H*256:BUFFER$(22)=CHR$(L):BUFFER$(26)=CHR$(H) 360 GRAPHICS 0:POKE 712,10:POKE 710,10:POKE 709,2 370 ? ADDR;":";:FOR J=1 TO 6 380 GOSUB 570:IF N=-1 THEN J=J-1:GOTO 380 390 IF N=-19 THEN 720 400 IF N=-12 THEN LET READ=1:GOTO 720 410 TRAP 410:IF N=-14 THEN ? :? "New Address";:INPUT ADDR:? :GOTO 370 420 TRAP 32767:IF N<>-4 THEN 480 430 TRAP 430:? :? "Display:From";:INPUT F:? ,"To";:INPUT T:TRAP 32767 440 IF F<BEG OR F>FIN OR T<BEG OR T>FIN OR T<F THEN ? CHR$(253);"At least ";BEG;", Not More Than ";FIN:GOTO 430 450 FOR I=F TO T STEP 6:? :? I;":";:FOR K=0 TO 5:N=PEEK(ADR(BUFFER$)+I+K-BEG):T$="000":T$(4-LEN(STR$(N)))=STR$(N) 460 IF PEEK(764)<255 THEN GET #1,A:POP :POP :? :GOTO 370 470 ? T$;",";:NEXT K:? CHR$(126);:NEXT I:? :? :GOTO 370 480 IF N<0 THEN ? :GOTO 370 490 A(J)=N:NEXT J 500 CKSUM=ADDR-INT(ADDR/256)*256:FOR I=1 TO 6:CKSUM=CKSUM+A(I):CKSUM=CKSUM-256*(CKSUM>255):NEXT I 510 RF=128:SOUND 0,200,12,8:GOSUB 570:SOUND 0,0,0,0:RF=0:? CHR$(126) 520 IF N<>CKSUM THEN ? :? "Incorrect":GOTO 370 530 FOR W=15 TO 0 STEP -1:SOUND 0,50,10,W:NEXT W 540 FOR I=1 TO 6:POKE ADR(BUFFER$)+ADDR-BEG+I-1,A(I):NEXT I 550 ADDR=ADDR+6:IF ADDR<=FIN THEN 370 560 GOTO 710 570 N=0:Z=0 580 GET #1,A:IF A=155 OR A=44 OR A=32 THEN 670 590 IF A<32 THEN N=-A:RETURN 600 IF A<>126 THEN 630 610 GOSUB 690:IF I=1 AND T=44 THEN N=-1:? CHR$(126);:GOTO 690 620 GOTO 570 630 IF A<48 OR A>57 THEN 580 640 ? CHR$(A+RF);:N=N*10+A-48 650 IF N>255 THEN ? CHR$(253);:A=126:GOTO 600 660 Z=Z+1:IF Z<3 THEN 580 670 IF Z=0 THEN ? CHR$(253);:GOTO 570 680 ? ",";:RETURN 690 POKE 752,1:FOR I=1 TO 3:? CHR$(30);:GET #6,T:IF T<>44 AND T<>58 THEN ? CHR$(A);:NEXT I 700 POKE 752,0:? " ";CHR$(126);:RETURN 710 GRAPHICS 0:POKE 710,26:POKE 712,26:POKE 709,2 720 IF MEDIA=ASC("T") THEN 890 730 REM DISK 740 IF READ THEN ? :? "Load File":? 750 IF DTYPE<>ASC("F") THEN 1040 760 ? :? "Enter AUTORUN.SYS for automatic use":? :? "Enter filename":INPUT T$ 770 F$=T$:IF LEN(T$)>2 THEN IF T$(1,2)<>"D:" THEN F$="D:":F$(3)=T$ 780 TRAP 870:CLOSE #2:OPEN #2,8-4*READ,0,F$:? :? "Working..." 790 IF READ THEN FOR I=1 TO 6:GET #2,A:NEXT I:GOTO 820 800 PUT #2,255:PUT #2,255 810 H=INT(BEG/256):L=BEG-H*256:PUT #2,L:PUT #2,H:H=INT(FIN/256):L=FIN-H*256:PUT #2,L:PUT #2,H 820 GOSUB 970:IF PEEK(195)>1 THEN 870 830 IF STARTADR=0 OR READ THEN 850 840 PUT #2,224:PUT #2,2:PUT #2,225:PUT #2,2:H=INT(STARTADR/256):L=STARTADR-H*256:PUT #2,L:PUT #2,H 850 TRAP 32767:CLOSE #2:? "Finished.":IF READ THEN ? :? :LET READ=0:GOTO 360 860 END 870 ? "Error ";PEEK(195);" trying to access":? F$:CLOSE #2:? :GOTO 760 880 REM BOOT TAPE 890 IF READ THEN ? :? "Read Tape" 900 ? :? :? "Insert, Rewind Tape.":? "Press PLAY ";:IF NOT READ THEN ? "& RECORD" 910 ? :? "Press RETURN when ready:"; 920 TRAP 960:CLOSE #2:OPEN #2,8-4*READ,128,"C:":? :? "Working..." 930 GOSUB 970:IF PEEK(195)>1 THEN 960 940 CLOSE #2:TRAP 32767:? "Finished.":? :? :IF READ THEN LET READ=0:GOTO 360 950 END 960 ? :? "Error ";PEEK(195);" when reading/writing boot tape":? :CLOSE #2:GOTO 890 970 REM CIO Load/Save File#2 opened read=0 for write, read=1 for read 980 X=32:REM File#2,$20 990 ICCOM=834:ICBADR=836:ICBLEN=840:ICSTAT=835 1000 H=INT(ADR(BUFFER$)/256):L=ADR(BUFFER$)-H*256:POKE ICBADR+X,L:POKE ICBADR+X+1,H 1010 L=FIN-BEG+1:H=INT(L/256):L=L-H*256:POKE ICBLEN+X,L:POKE ICBLEN+X+1,H 1020 POKE ICCOM+X,11-4*READ:A=USR(ADR(CIO$),X) 1030 POKE 195,PEEK(ICSTAT):RETURN 1040 REM SECTOR I/O 1050 IF READ THEN 1100 1060 ? :? "Format Disk In Drive 1? (Y/N):"; 1070 GET #1,A:IF A<>78 AND A<>89 THEN 1070 1080 ? CHR$(A):IF A=78 THEN 1100 1090 ? :? "Formatting...":XIO 254,#2,0,0,"D:":? "Format Complete":? 1100 NR=INT((FIN-BEG+127)/128):BUFFER$(FIN-BEG+2)=CHR$(0):IF READ THEN ? "Reading...":GOTO 1120 1110 ? "Writing..." 1120 FOR I=1 TO NR:S=I 1130 IF READ THEN GOSUB 1220:BUFFER$(I*128-127)=SECTOR$:GOTO 1160 1140 SECTOR$=BUFFER$(I*128-127) 1150 GOSUB 1220 1160 IF PEEK(DSTATS)<>1 THEN 1200 1170 NEXT I 1180 IF NOT READ THEN END 1190 ? :? :LET READ=0:GOTO 360 1200 ? "Error on disk access.":? "May need formatting.":GOTO 1040 1210 REM 1220 REM SECTOR ACCESS SUBROUTINE 1230 REM Drive ONE 1240 REM Pass buffer in SECTOR$ 1250 REM sector #in variable S 1260 REM READ=1 for read, 1270 REM READ=0 for write 1280 BASE=3*256 1290 DUNIT=BASE+1:DCOMND=BASE+2:DSTATS=BASE+3 1300 DBUFLO=BASE+4:DBUFHI=BASE+5 1310 DBYTLO=BASE+8:DBYTHI=BASE+9 1320 DAUX1=BASE+10:DAUX2=BASE+11 1330 REM DIM DSKINV$(4) 1340 DSKINV$="hLS":DSKINV$(4)=CHR$(228) 1350 POKE DUNIT,1:A=ADR(SECTOR$):H=INT(A/256):L=A-256*H 1360 POKE DBUFHI,H 1370 POKE DBUFLO,L 1380 POKE DCOMND,87-5*READ 1390 POKE DAUX2,INT(S/256):POKE DAUX1,S-PEEK(DAUX2)*256 1400 A=USR(ADR(DSKINV$)) 1410 RETURN
In order to make special characters, inverse video, and cursor characters easy to type in, COMPUTE! Magazine’s Atari listing conventions are used in all the program listings in this book.
Please refer to the following tables and explanations if you come across an unusual symbol in a program listing.
Characters in inverse video will appear like: INVERSE VIDEO. Enter these characters with the Atari logo key, (/|\).
When you see Type See {CLEAR}
ESC SHIFT <
↰ Clear Screen
{UP}
ESC CTRL -
↑ Cursor Up
{DOWN}
ESC CTRL =
↓ Cursor Down
{LEFT}
ESC CTRL +
← Cursor Left
{RIGHT}
ESC CTRL *
→ Cursor Right
{BACK S}
ESC DELETE
◄ Backspace
{DELETE}
ESC CTRL DELETE
◄ Delete Character
{INSERT}
ESC CTRL INSERT
► Insert Character
{DEL LINE}
ESC SHIFT DELETE
↑ Delete Line
{INS LINE}
ESC SHIFT INSERT
↓ Insert Line
{TAB}
ESC TAB
► TAB key
{CLR TAB}
ESC CTRL TAB
← Clear TAB
{SET TAB}
ESC SHIFT TAB
→ Set TAB stop
{BELL}
ESC CTRL 2
↰ Ring Buzzer
{ESC}
ESC ESC
␛ ESCape Key
A series of identical control characters, such as 10 spaces, 3 cursor-lefts, or 20 CTRL-Rs, will appear as {10 SPACES}, {3 LEFT}, {20 R}, etc. If the character in braces is in inverse video, that character or characters should be entered with the Atari logo key. For example, {,} means to enter a reverse-field heart with CTRL-comma, {5U} means to enter five inverse-video CTRL-Us.