Atari Starshot
Matthias M Giwer
You are flying down a trench bisecting an artificial world. A disembodied voice whispers in your ear, "Turn off your computer — BASIC is too slow." As this game will demonstrate, Atari BASIC can be fast enough if you know how to speed it up.
The features in the Atari computer give it a graphics potential that approaches that available in dedicated graphics-oriented computers. And, features of Atari BASIC allow very fast manipulation of strings, Direct Memory Access for the Player/Missile Graphics, and the direct call of machine language from BASIC. This game combines all of these features and a few others.
Let's start the discussion of this program with the subroutine at line 30000. The first thing to do is to enable the Player/Missile Graphics.
Appendix A of the Atari Hardware Manual gives a detailed example of how to do this. This method only works when there is nothing on the screen. As soon as you write to the screen, this method fails. The usual approach is to reserve enough pages for the screen RAM, the Player/Missile graphics pages, etc. All in all, to use Player/Missile Graphics with GRAPHICS 7, you wind up reserving 32 pages and, in the process, taking care of the computer rather than letting the Operating System (OS) take care of you. Here is how to do it right.
RAMTOP
Contained in register 106 is the number of pages of RAM available to you for your use after everything needed for the system has been accounted for. What we want to do is to change this number so that RAM is protected for the Player/Missile Graphics pages. This is accomplished by POKE 106, PEEK(106)-16. This puts a number into that register that is 16 pages less than the number the
Operating System determines upon powering up the computer or upon system reset. But just POKEing a new number does nothing until the computer makes use of it.
The second GRAPHICS 7 call causes the Operating System to make use of this new RAM-TOP to relocate the screen RAM and the display list below RAMTOP. If you do not make this graphics call, you will find that the screen memory is above the new, lower protected memory limit, and the system will crash at the first attempt to scroll the screen. In other words, your system registers that point to the first screen byte, and the display list will be above RAMTOP. The Operating System cannot handle this.
You proceed as normal but much more cleanly now that you have lowered the effective top of your RAM and made the Operating System reorganize itself around that new maximum RAM with the second graphics call. Lines 30204 and 30206 are the enabling POKEs for Player/Missile Graphics as described in many articles and in De Re Atari. Line 30208 is the POKE to tell the Operating System where to find the start of the Player-Missile data. The start of this data is now simply RAMTOP.
With Player/Missile Graphics set up this way, you can forget about what the rest of the system is doing and treat it just as though Player/Missile Graphics were not in use. The Operating System will take care of you.
Player Definition
The next routine of interest is at line 30236. (This is the machine language routine published in the February 1982 issue of COMPUTE!.) It provides relocation of the four players at machine language speeds by means of two POKEs and, since the routine is executed during the vertical blanking time, the motion appears to be continuous. The rest of the 30000 lines define the players. Note that the RESTORE in line 30310 makes Player 3 the same as Player 2, although it is defined as a different color in line 30230.
Now let's jump to lines 100-120 – we will get to the earlier lines later. These lines are the definitions that will be used for named subroutines later. The use of named subroutines is a desirable feature that greatly aids program development.
Lines 1890-1930 are both the one-time calls and those such as DISPLAY that are needed to set up the game at the start.
The subroutine at line 10000 draws the background in the way that makes this illusion of motion possible. Note that each set of lines is drawn with a different COLOR and that the COLOR numbers rotate 1, 2, 3, 1, 2, 3, and so forth. I will get back to this in a minute.
Color Rotation Simulates Motion
The START subroutine at line 5000 POKEs numbers into the color registers so that you can see the screen and draws the eight attackers. You will note also that COLOR J also rotates the COLOR assigned to the attacker graphic although in a more complex manner than in BACKGROUND.
The DISPLAY subroutine at line 6300 controls the scoring and number of lives information that will be shown in the bottom alphanumeric window.
ASELECT at line 6500 picks the order in which the attackers will attack from among the predefined ATTACK1-4$ in lines 54 and 60.
Within the infinite loop at line 2100 you'll find the reason why I used different COLORs to draw the background. The four statements in line 2110 rotate the colors used in the background through the registers in a "bucket brigade" manner; the colors seem to be moving toward you. Given the drawn background, it appears as though you are moving forward through the trench. This illusion of motion requires the use of three different colors as a minimum. If there were only two colors, they would appear to flicker back and forth rather than move. The instructions in this line will be used in almost every subroutine so that this illusion of motion is maintained.
This technique is useful in many applications – you can simulate many kinds of motion. If you were to reverse the order of the instructions, you would have the illusion of going backwards. Line 2120 is simply a short delay.
Another line that you will find throughout the program is first used at line 5017. A = 74 + PADDLE(0)/ 2.92 is the equation that limits the motion of Player 0 on the screen. 74 is the farthest left X location that Player 0 can move to. The range of values for the PADDLE(O) is 0 to 228. Dividing this range of values by 2.92 converts the largest value of 228 to the rightmost location of Player 0 and makes the full left-to-right motion of the Player a full turn of the PADDLE. This equation is also put into every subroutine where the program execution takes a noticeable amount of time in order to simulate continuous motion.
The subroutine MOVE at line 5100 is a loitering loop that waits a random number of loops until the first attack begins. When the number 50 is reached, program execution jumps to SELECT at line 5200.
The SELECT subroutine picks the sequence of the attackers from ATTACK1$ through ATTACK4$. ATTACK$ for the first wave was initially called in line 1930. This routine randomly picks one of the four attack sequences defined in lines 54 and 60. An attempt to read the ninth element in this string is TRAPped to line 5211 which redraws the attackers and starts over.
Note this use of the TRAP instruction. It is not meant simply to avoid a program crash, but rather to perform an integral program function. Rather than a RAM and time-consuming test or loop, one simple statement is used.
Lines 5215-5240 erase the chosen attacker, position Player 1 over the erased attacker, and give some warning sounds. Line 5241 calls the subroutine JOIN at line 5800. This routine adds together the strings which are used to define the X and Y positions of Player 1 as it moves from its initial position to its attack position.
Special TRAPs
The strings are the AX1$ and AY1$ through AX8$ and AY8$ that were defined back in the beginning of the program. These are the X and Y coordinates to be POKEd into PLX + 1 and PLY +1. They are stored as groups of three numbers. These values are read in lines 5260-5270. Note that by using TRAP here I do not have to keep track of the number of elements in the string. And again instead of some test or loop, a simple statement is used. These strings are merely added together. No matter what the sequence of the attack, the last pattern is always the same, and the last set of numbers in the string is always the same.
The ATTACK subroutine at line 5300 is where the shooting occurs. The first call is for the subroutine PATTERN at line 5600. This subroutine chooses among five possible X position patterns and five possible Y position patterns. These are the rest of the strings defined in the beginning of the program. This independent choice of X and Y patterns permits a total of 25 different attack patterns.
In line 5315, the X and Y values for this attack motion are read out in groups of three. In this case, the TRAP is used to jump back to the PATTERN subroutine call to pick another pair of strings when the end of the STRING is reached. This gives continuously varying motion to the attacker.
Lines 5324 and 5325 change the size of the attacker as it comes "closer" or goes "farther away." F and G are flags that control the firing and motion of the missiles. It is worth examining how these flags function.
F controls the attacker's missile firing. Other than its housekeeping function, the primary purpose of the IF F = 0 is to fix the X and Y location at the moment of firing so that the motion is calculated only from this point. After F is set to 1, these statements are no longer executed. If they were, the missile would weave back and forth in X and Y in unison with the attacker. Behind the F = 1 flag are the calculations that determine whether the missile passes to the left or to the right. The G flag performs a similar program function.
Lines 5350 and 5352 check for missile-to-player collisions and direct action to the appropriate subroutine. Line 5355 clears the collision registers.
HITYOU, HITME, HITUS
The HITYOU, HITME, and HITUS subroutines introduce Players 2 and 3 as the explosions. In HITYOU and HITME, these two players are sequentially put in the same location as the hit player. This sequence is controlled by the TT variable. Note that the two explosion shapes are the same but of different colors. Also, when they are called, they are placed one Y position different. The purpose is to give some illusion of a dynamic explosion.
Lines 5440 and 5540 move the hit player and explosions off the screen. The logical truth statements determine whether the hit player was to the left or right of center when hit and then move it off the screen to the left or right as appropriate. Lines 5545 and 5547 cause the attacker and the explosions to grow larger as they go by.
The significant difference in the two sub routines is that in HITYOU there is an additional collision test in line 5560. This requires you to get out of the way of the hit player as it rolls off the screen. If you don't, you are also destroyed, and both players roll off the screen. This is controlled by the HITUS subroutine. Being hit by the attacker's missile and by the damaged attacker causes you to lose one life.
Good Practice
This is a quick review of a fairly complex program. It exploits many of the Atari's features. The method of reserving the Player/Missile Graphics pages by moving RAMTOP lets the machine take care of you and perhaps completes the official Atari version of how to turn on the function.
Flowing colors create the illusion of 3-D movement in "Starshot."