Task: Learn How to Make a Game in BASIC XE
Needed: BASIC XE and extensions
Time: 30-60 minutes
My previous posts have demonstrated many of the programming techniques needed to make a game in Atari BASIC. A common theme is how slow BASIC is for executing some of the key algorithms needed to make a game. Posts on redefining characters sets for drawing playfields and player-missile graphics focused on machine language routines that had to be loaded into memory and executed from within BASIC to achieve reasonable performance. Combining lots of different machine learning routines can be challenging as explored in this post on combining redefined character sets with player-missile graphics. Fortunately, some of the later version of BASIC included machine language libraries called from simple BASIC commands that make tasks such as moving character sets from ROM to RAM for editing and moving players on the screen super easy.
A company that provided several of these advanced BASIC programming languages was Optimized Systems Software or OSS. These included BASIC A+ (1983), BASIC XL (1984), and BASIC XE (1985). BASIC A+ was first and fixed a number of bugs in Atari BASIC. BASIC XL was next and included pre-compiled line numbers that greatly sped up GOTO and GOSUB commands. BASIC XE added faster mathematics operations and access to the increased memory that came with the XE machines. All included machine language routines for a number of otherwise slow routines. As a side note, BASIC XL and XE never took off because Turbo BASIC XL came out in 1985 as open-source with an included compiler that the OSS tools didn’t have. As a result, sales of the OSS products were much lower than they should have been.
I decided to see how far I could get making a game with BASIC XE and all of its wonderful built-in machine language routines (e.g. MOVE & PMMOVE). I list below each of the special BASIC XE commands that I took advantage of. More details can be found in the BASIC XE reference manual.
BUMP – Checks for collisions between missiles, players, and the playfield.
FAST – This command is the one that pre-compiles the line numbers to memory addresses. I noticed a significant speedup when using this as the first command of the program. Otherwise, BASIC has to search the whole list of line numbers to find the one the GOTO or GOSUB points to. Highly recommended and takes no time to execute.
MISSILE – Initializes a missile at a certain Y coordinate and height. This replaces the manual process of writing specific bits to the missile memory area.
MOVE – Move calls a machine language routine for moving a block of data from one memory location to another. Used here to move the character set from ROM to RAM in a few seconds. Love this!
PMADR – This returns the address of the player and missiles. Important because invoking PMGRAPHICS (see below) automatically set up the PM memory map.
PMCLR – Erases the player or missile memory area. Replaces the manual process of writing 0s to these memory locations. Much faster!
PMCOLOR – This sets the color of the players and missiles just as we would use POKE to do.
PMGRAPHICS – This enables player-missile graphics with single or double line resolution. Also, this automatically sets up the memory map for PMG.
PMMOVE – This draws the player or missile on the screen. For the player, an X coordinate is given along with a Y increment (e.g. -1, 0, or +1) usually read from the joystick. This is a machine language routine that replaces the manual moving of missiles and players in memory for positioning on the Y axis. Much faster!
PMWIDTH – This sets the width of the players and missiles.
VSTICK & HSTICK – These return -1, 0, or 1 depending on whether the joystick was moved up or down or left of right. Helpful for moving players and/or missiles. VSTICK can be given directly as the last argument of PMMOVE. HSTICK is used to set the X coordinate that is given to PMMOVE.
The MOVE and PMMOVE commands are particularly useful because they replace the machine learning code we had to previously load in and call. This greatly simplifies game development because you don’t have to manually place the code in memory and keep track of it.
I illustrate here how BASIC XE, with it special commands, can be used to make a relatively fast game in BASIC. I was impressed with its performance. I will list some of the caveats I encountered in the comments. The game I came up with is pretty simple and is based on the idea I presented previously when introducing how to combine redefined character set with player-missile graphics. The fantasy is that you are Darth Vader and the rebel alliance is closing in on you. They have set up a force field you can’t escape from and are firing at you from their X-wings. They are also dropping in mines. How long can you survive? I love this as an educational example because we were all mesmerized by Atari graphics just a few years after we saw Star Wars for the first time in 1977. This is one of the reasons that Star Raiders was so popular and why many of use tried our hand at programming back in the day.
The code is pretty straightforward and should be easy to follow if you have read my previous posts on BASIC programming. We first set up the graphics and title screen (GOSUB 4000). We then move the character set from ROM to RAM using the MOVE command followed by systematically redefining non-letter and non-number characters such as +, =, and ” (GOSUB 5000). There are then a few lines to define game variables (GOSUB 6000). We then draw the playfield using our redefined characters with a series of PRINT statements (GOSUB 7000). Finally, we set up the player-missile graphics (GOSUB 8000). Once these initialization are complete, we then run the main loop that places the player and missiles on the screen, adjusts the difficulty to be progressive with the score, and checks for collisions. A collision sends control to the end of game code that executes the explosion and prints the game end text with the final score and the option to start again. If the start button is pressed, we execute the RUN command that starts the whole program over.
The following instructions are for running the game in the Altirra emulator. You can of course run it on original hardware (64KB required) with BASIC XE by booting the ATR file using SIO2PC. You could also load it from a flash device. Here is the text file with the BASIC XE code that could be loaded by copying and pasting into Altirra once BASIC XE and its extensions have booted (see below). Here is a zip with the ATR file. Here is a heavily commented version of the BASIC code so you can see how the game was created.
Open Altirra and attach the BASIC XE extensions disk into Drive 1. You can do this by selecting Attach Disk from the File menu and then clicking on Disk 1.
Next attach the Vader’s Last Stand ATR file to Drive 2 just as you did in Step 1.
Boot the BASIC XE cartridge by choosing Attach Cartridge from the File menu. You will see the extensions disk boot and load followed by the BASIC XE cartridge ending with the ready prompt.
Now load the game with LOAD “D2:VLS.BXE”. Type RUN. The game should load to the title screen and then automatically launch within a few seconds. You are ready to play!
Also try booting the ATR file on your Atari hardware from your PC using SIO2PC. You must have the BASIC XE cartridge and its extensions loaded. BASIC XE cartridges are hard to find and quite expensive. One way to do this is to put the ROM on an flash device such as the Atarimax Maxflash cartridge. You could then boot the extensions disk from your PC via SIO2PC or something like the SDrive-Max. You could create a floppy disk with the ATR image and boot the extensions directly from your disk drive.
This was a fun project. It was very rewarding to put all the pieces together into a fun little game that highlights many of the features of Atari graphics and arcade programming. I very much hope you find it useful as you learn or relearn how to make a game in BASIC. A few comments.
First, I discovered that the order in which I initialized all the different component mattered. I assume this is due to how BASIC XE manages the memory map. The key was to initialize the player-missile graphics last. I assumed this needed to be done earlier in the memory mapping process but I was wrong. Keep that in mind if you modify the code to make your own game.
Second, even with the convenient and fast BASIC XE commands such as PMMOVE I still had performance issues when putting too much additional code in the main loop. This made it difficult to add some additional features such as shooting and asteroid (player 1) across the screen randomly as an additional object to avoid. They key to making this work would be to write the additional game logic in machine language and calling it during the vertical blank. I will try to cover this in a future post. I didn’t want to take the extra time to add this feature now.
Third, I only implemented horizontal missiles for simplicity. Vertical missiles are a bit more difficult but certainly doable. The challenge I had was keeping track of where they were and when they ran off the screen. This is easier with horizontal motion. I simply didn’t have the cycles to add this code. Again, adding this to a machine language routine would make this fast enough to add.
Fourth, I wanted to add some power ups such as shields. As explained above, this would have taken too many cycles to implement in BASIC during the main loop. Something to add in a future more optimized version.
Fifth, I didn’t do anything with the display list interrupt. This would have made it possible to add more colors to the playfield. Something to think about for future versions.
Sixth, I added the dangerous border or force field so I didn’t have to keep track of where the player was in vertical space. This saved me some cycles as described above. Once I implemented the border I actually liked it better than wrapping the player around the screen. Makes it more challenging!
I hope you find this exercise educational. Please feel free to take the code and modify it however you wish. Feel free to send me coding suggestions. Keep me posted on your creations!