(back to project list)

Phantoms Five Disassembly

Phantoms Five is a vertically-scrolling game for the Apple II in which the player bombs targets on the ground. Occasionally it switches to a first-person view of incoming fighter planes that must be shot down. According to Nasir Gebelli's wikipedia page, it was the third game he wrote and published through Sirius Software.

The game features a terrain map that extends nearly 4x the height of the screen. This is done by taking a 345-line bitmap and doubling it so its drawn on every other line. The player's plane and anti-aircraft fire are drawn on the unused lines, so the different elements can be animated without interfering with each other.

Phantoms Five is copyright 1980 Sirius Software.

Extracting the load file from the disk image is a little tricky. The cracked game uses a common trick where BRUNing the file just loads a small loader from the start of the file. The loader uses DOS RWTS directly, which allows it to overwrite other parts of DOS while reading the remainder of the game. Extracting an image suitable for disassembly is explained here.

title bombing dogfight

How to Play

The game is divided into bombing and dogfighting phases, which alternate. You start in the bombing phase, with a top-down view of the plane with terrain scrolling past at a fixed speed. The plane's horizontal position is controlled with a paddle or joystick, and you drop bombs by hitting the button. The plane's vertical position drifts up and down; this is not under your control.

Only one bomb may be in the air at a time, but you can hold the button down to drop them continuously. Different regions of the map are marked as low-value (10 pts), medium-value (20 pts), or high-value (30 pts). There are four special targets: the HQ (+100 points), fuel dump (+100 points), POW camp (lose half your score), and hospital (reset score to zero).

Unseen enemy anti-aircraft batteries counter-attack frequently, shown as a brief flicker. Sometimes these turn into flak bursts that will destroy the plane if they make contact.

A crashing plane is treated like a bomb, and will update your score on impact. Try not to crash into the hospital.

After a certain amount of time has elapsed, the second phase begins, and the overhead view is replaced with a first-person view out the cockpit window. Incoming planes will approach and try to shoot you down. You can return fire by aiming with the paddle and pressing the button. (The range of movement on the paddle is very small, at the left end of the range, and difficult to manage with a joystick. If you can only seem to fire straight ahead, you're out of the zone.) Hostile planes are worth 40 points, and the dogfight phase ends after you shoot 7 of them down. Not all planes are actively hostile, however.

If you survive an air attack, the difficulty level increases. It starts at 1 and goes up to 5. The difficulty level determines how frequently flak bursts are fired, and how quickly the planes move during dogfights. If your plane is destroyed in either phase, the difficulty level decreases by one. There is no change in scoring at higher difficulties.

In addition to score, the game tracks the number of targets destroyed (defined as bombs hitting something worth more than 10 points) and hostile planes shot down.

Press the space bar to toggle the top-down view between the plane and a bomb sight.

On a personal note, this was one of the first games I ever owned -- a birthday present when I was young. I remember seeing the demo running in a computer store and being blown away by the graphics.

How Stuff Works

During the bombing phase, Phantoms Five manages to animate the entire screen at a high frame rate. Despite using a single graphics page, it's nearly artifact-free. How does it do this?

First and foremost, the game divides the screen in half, using odd-numbered lines for the terrain, and even-numbered lines for the player's plane and falling bombs. This allows these things to move without interfering with each other, so you can move the plane without having an instant where the terrain has a hole in it.

The terrain is scrolled with a large unrolled loop that takes about 1/30th of a second to copy 83 lines from one part of the hi-res screen to another part, and then copy in one new line of terrain data at the top. You will see some tearing, e.g. the left and right sides of the screen will seem temporarily out of phase, but it's minimal.

The player's plane is drawn without first erasing it. There's a line of black pixels on the top, bottom, and right edge (the latter because the image is bit-shifted for sub-byte positioning). In cases where the graphic is drawn at a new byte position, the left edge of the plane must be cleared explicitly. This approach is more efficient than a full erase+draw, and avoids the flickering that doing so would cause.

This approach of minimal erasing is applied through much of the game, e.g. flak bursts only erase their tail as they move down the screen. It works because the background is black (for bombing) or blue (for dogfighting), so the background color can be baked into the shapes themselves.

The player's plane only shares the even rows with two other things: falling bombs, which start below the plane and move away, and the deadly flak bursts. (The quick flak pops are drawn on the terrain lines with exclusive-OR, and removed a couple frames later by re-drawing them.) The only time you'll see a graphical glitch is when a flak burst passes near the plane.

While falling bombs are on even rows, exploding bombs are on odd rows. This is because we want the explosion to interact with the terrain. Areas that are completely black in the image (i.e. zero bytes) are not copied to the screen, but the images are not otherwise blended. If the bitmaps were ORed or XORed it would look like a big white blob or a colorful mess, respectively. Skipping the zero bytes avoids rectangular explosions without needing a secondary mask bitmap.

Some graphics, like the player's plane, have 7 shifted forms so they can slide smoothly across the screen. Others, like bombs and flak bursts, are always aligned on byte boundaries. This avoids the need to store shifted shapes or shift graphics while drawing them, but means that your bombs won't always quite line up with the plane.

Bombing Phase

When a bomb hits the ground, the effects are mostly determined by the color of the pixels where the bomb hit. One byte at the center of the bomb is examined. If it's fully white, or has blue or orange, it's a high-value target. If it's fully black, it's a low-value target. Anything else is a medium-value target. The size of the detonation tells you how the target was scored. Medium- and high-value targets increase the "targets bombed" counter.

The position of the four special targets is determined partially by a stripe down the side of the screen. For example, this image shows a purple line for the bomb dump, blue for the hospital, and orange for the HQ. The POW camp has a green line on the right side.

special target

(Click to see full size.) The horizontal position is specified by hard-coded values.

You can put all this together to create an annotated terrain map, with medium-value targets highlighted in teal, high-value targets highlighted in gold, and special targets in red and green.

terrain terrain-anno

If you look closely you'll see a couple of oddities. The buildings with letters on them are colored high-value, but the letters themselves were drawn with white/black that had bit 7 clear. So if you drop a bomb right on the letter it's a medium-value target.

If you've ever bombed the fuel dump and wondered why it didn't count, it's because the horizontal position is off by one. You need to bomb the right side of the target for it to count.

With regard to enemy fire, there are "flak pops" and "flak bursts". The flak pops happen periodically, and are just harmless flashes. Flak bursts will knock your plane out of the sky. The flak bursts are preceded by a flak pop in the same column, giving you a little bit of warning.

There's no "safe zone" on the map, but if you position your plane above or slightly to the left of the long green road on the right side (column 30), you will rarely be shot at. While there's no safe zone, there is very definitely a "death zone": move any farther to the right (column 32+), and the code will target you 100% of the time. You can use this to your advantage: slide right to draw the attack, move left when you hear the pop.

Bombing continues for 512 frames. The game enters a "quiet period" of 112 frames where no deadly flak bursts will fire, and at higher difficulties you will get an "air attack warning" message. It's unclear whether the message was meant to be suppressed at level 1, as this is not determined explicitly. The timing of the message's appearance depends on the intersection of two timers, one of which is difficulty-dependent. This is also why the message is on screen for longer at some difficulties than others.

Dogfighting Phase

In this phase, two planes will approach, fire, and veer away if they don't manage to kill you. The implementation is a little convoluted. The way the code is written suggests that having two planes instead of one was a late addition.

Pressing the button fires a bullet. Holding the button fires up to four bullets, after which you must release the button to fire again. The enemy plane collision detection appears to be designed to cause some percentage of bullets to miss, so you may have to fire repeatedly to score a kill.

The first plane is created in the primary slot. It flies toward you over several frames, drifting up and down. At about the halfway point it starts firing. If it manages to animate all the way forward, and is inside the "strike zone", your plane will be shot down. If it's outside the strike zone, they will miss, and fly off.

strike zone

At higher difficulty levels, the planes move more quickly. (It's best to enter the phase with the button held down to have a chance at killing the first plane or two. If you start with your paddle set to position your bomber in the "almost safe zone" above the green road on the right side, your guns will be near center when the dogfight starts.)

The second plane to appear is in the secondary slot. It moves the same way as the primary plane, but does not shoot.

If you destroy a plane, a new one is created in that slot. If you destroy a plane in the primary slot, you get 40 points, your hostile plane kill counter is incremented, and you make progress toward ending the dogfight. If you destroy a plane in the secondary slot, it doesn't count for anything. However, there's a bug in the code that essentially swaps slots when you destroy a plane in the secondary slot, so the plane that was shooting at you is now secondary... and can't shoot. Which is why shooting down a secondary plane immediately stops the primary plane from firing.

The initial positions and movement of the planes is pre-determined, from a table with 32 entries that the game cycles through.

Paddles and Joysticks

The game was clearly designed to be played with a game paddle. During the bombing phase, the paddle read stops at 60 (out of 255), so the plane is controlled with a fraction of the range. During the dogfight phase it stops at 128, giving a bit more range, but if you go too far to the right or left it centers the guns, which is not at all helpful.

While difficult to control with a joystick, it works very well with mouse-as-joystick in an emulator.


Simple cheats if you can drop into a debugger (e.g. F7 in AppleWin):

Copyright 2020 by Andy McFadden