(back to project list)

Disassembly of ABM for the Apple II

ABM, which stands for Anti-Ballistic Missile, is an arcade game inspired by Atari's Missile Command. Written by Silas Warner, it was the seventh game published by Muse Software.

The game is much simpler than Missile Command, allowing only a single missile to be fired at a time. It was released at a time when many Apple IIs had a pair of paddles rather than a joystick, which made controlling the crosshairs something of a dexterity test.

ABM is copyright 1980 Muse Software.

title action1 action2


Playing the Game

The rules are simple: fire ABMs at the incoming missiles to destroy them before they destroy your cities and launchers. When all 6 cities are gone, the game is over.

Some incoming missiles are MIRVs (Multiple Independent Re-entry Vehicle), which can split into as many as 6 independent missiles, targeting all of your cities.

The target cursor is controlled with the paddles or joystick. You can assign separate buttons for the outer/center launchers, which fire a low-yield warhead, and the two inner launchers, which fire a high-yield warhead. The high-yield warheads cover a larger area but take longer to dissipate, which can be a disadvantage since you can only fire one ABM at a time.

Before playing for the first time, be sure to run the control adjustment program. In particular, make sure to select different buttons for the inner and outer launchers. If you assign both to the same button, the game will always use the outer/center launchers unless it has no other choice. The program determines which paddle is associated with each axis, and whether the axis is flipped, but does not constrain the range of movement.

ABMs come from the closest launcher. The game won't launch an ABM if the angle is at or below 45 degrees, which limits your ability to fire across the length of the screen.

The blast radius and detonation height for missiles is random. There is a 10% chance that an intercepted missile will detonate, yielding a large mid-air explosion that may catch other inbound missiles.

Damage to cities and launchers is determined by the contents of the screen at row 155 (5 up from the text window). If the center byte is zero (all 7 pixels are black), the city or launcher is considered to have been destroyed. If there are lit pixels but the value is different from what it was when the game started, the city or launcher is considered damaged, and city identifiers will be shown in inverse text.

The interval between missile generation is random. Every time a missile is launched, a counter is reduced, so as the game progresses the missiles come more frequently and split more often. The game reaches maximum intensity after 110 missiles have been launched.

Your score is based on the number of missiles destroyed and the number of ABMs fired.

Bugs & Quirks

The state of the launcher is checked after an ABM explodes. If you sit quietly while one of your launchers is destroyed, the launcher will be able to fire one last ABM before being marked unavailable.

The collision detection for missiles and ABMs works by testing the current screen contents when drawing the head of the missile. If the screen pixel isn't black, something has been hit. This test is only done when the missile moves, so for inbound missiles the test will be done every 11 frames. The low-yield ABMs have an explosion size of 80 and a explosion rate of 8, which means it takes 10 frames to draw the white portion, and 10 frames to draw the black portion. If you get the timing just right, you can draw the white part of the ABM explosion on top of the missile, then clear it with black right before the missile moves. This is why the low-yield ABMs sometimes fail to destroy the incoming missiles, even on a direct hit.

(The collision-detection problem was noted in Byte Magazine's review, noting on page 88, "Some incoming missiles seem to outrun the expanding fireballs, while others survive what looks like a solid hit." The nature of the bug means it only happens for low-yield ABMs from the outer/center launchers.)

When a missile splits, you end up with 6 warheads, assuming there were no other MIRV warheads already present. (There are 6 slots for "top-launched" missiles, and 5 slots for MIRV warheads.) The 3rd warhead from the left is in the original missile slot (targeting PHL), and still has the "can split" flag set. If you destroy the warheads on the right, the slots are freed, and the original missile will split again, which can be disastrous. It's important to kill the original missile first. (Alternatively, you can "milk it" for points if it's sufficiently far from your remaining cities.)

If all of the MIRV slots are full, the split code will bail out after redirecting the incoming missile. It looks like the missile is dodging.


About the Code

The game uses quite a lot of inline data and self-modifying code. The disassembly project uses a SourceGen extension script that formats three different kinds of inline data for calls to 12 different functions. Without this the code is much harder to wade through.

The game relies heavily on Applesoft ROM routines. Cities and launchers are drawn with the shape table renderer, and the hi-res positioning and plotting functions are invoked directly. All of the math is done with floating-point numbers, which is unusual for an arcade game on the 6502. The use of mixed-mode graphics allows the game to display text without the overhead of a hi-res character generator. Overall the game has less than 5KB of code and data.

The program is configured to run on a system with 32KB of RAM, running DOS 3.2. The high scores are written directly to disk (track 2, sector 9).

Circles

One of the things that caught my attention many years ago was the way circles were drawn. This led me, 35 or so years later, to write some fast code for drawing filled hi-res circles. But I always wondered how ABM did it.

It turns out ABM doesn't draw filled circles, nor does it draw a series of outline circles with increasing radii. Instead, it has a 256-entry table with X/Y coordinates for pixels in an expanding circular pattern. This allows the explosions to be drawn incrementally over several game frames in a flexible way.

You can think of it like drawing a spiral: you start at the center, and draw in a circular motion, expanding gradually outward. On every frame, you pass in the start index and the number of pixels you want to draw. Subsequent frames start at the point where the previous frame ended. The total pixel count determines how big the circle gets, and the per-frame pixel count determines how quickly the circle forms.

It's not literally a spiral, and the X/Y coordinates are defined for one quadrant and repeated to fill out the circle, but you get the idea. Here's what the data looks like for an explosion with 112 pixels, with the index shown in hex and color changes every 16 pixels:

circle

(High-yield ABMs have 112 pixels and are drawn 8 per frame, but changing colors that often made the visualization too busy. You can play with the visualization parameters in SourceGen, at address $1643.)


Copyright 2020 by Andy McFadden