Zaxxon Measures Your Height With Your Shadow
Zaxxon looks like nothing else from 1982. The fortress is drawn at an angle and scrolls past diagonally, and your ship flies over it, through gaps in its walls and under its electric barriers. It is also famous for being hard to read. On a flat screen, is the ship high above that wall or just in front of it? Players learned to watch two things: the dark shadow under the ship, and the altimeter bar down the left edge.
Inside the original arcade program, those two are more closely tied than they look. The game does not keep the ship's height and then draw a shadow to match. It keeps the position of the shadow, and the height is simply how far the ship is from it. This article follows that one number through the 1982 code, from the shadow to the altimeter to the walls.
The height is a gap on the screen
Everything in Zaxxon is a picture placed at a position on the screen. For the ship, the game keeps how far across the playfield it is, and how far down the screen it is drawn. It also keeps a second point: the spot on the floor directly under the ship. The shadow is drawn there.
The altitude is the distance between the two, straight up the screen:
The game counts those positions in pixels down the screen. A new ship is at 94, with its ground point at 162, so it starts 68 pixels up. Push the stick forward and the ship dives: it moves down the screen toward its shadow, which stays put, and the gap shrinks. Pull back and it climbs away from it.
In the code it is a single subtraction:
ld a,($67A8) ; where the ground point is drawn, down the screen
sub (hl) ; minus where the ship is drawn
ld ($6417),a ; that difference is the altitude
Moving sideways is where the isometric view shows. The floor runs at an angle, so sliding across it also moves the ship and its ground point down or up the screen together, about half a pixel for every pixel across. Both move, the gap between them does not, and the height stays the same.
The shadow is simply placed on the ground point, so on screen the space between ship and shadow is exactly the number the game is using. Usually. The game hides the shadow in space, and at the start of each life until the ship nears the fortress. It also hides it for a moment whenever the ship passes a wall, and over some ground objects it draws the shadow 8 or 10 pixels higher, as if it fell on top of them.
The altimeter reads the same number
The bar on the left is drawn from that same altitude byte and nothing else. Every 16 pixels of height fill two character cells of the bar, and the last few pixels pick a part-filled end piece. It is not a separate instrument: it is the gap between you and your shadow, turned on its side.
Four floors in the sky
The altitude can be anything from about 7 to 73 pixels, but most of the game does not use it directly. It sorts the ship into one of four height bands:
The band is what the game actually plays with. Before the ship gets inside the fortress walls, and in space, where the shadow is often missing, it even changes the ship's picture: each band has its own drawing of the ship, a little smaller each step down, so a high ship looks bigger. The level picture is about 14 by 23 pixels in the top band and 10 by 16 in the lowest. Once the ship is inside the fortress, where the shadow does that job, the picture stays at full size. (The switch between the two follows a flag whose low bits change as the ship clears the outer wall; reading it as "inside the fortress" fits every run but is not proven.)
Shots use the band too. A shot remembers the band the ship was in when it was fired, and keeps it even if the ship climbs or dives afterwards.
What a wall really is
Here is where the four bands matter most. To the player a fortress wall is a solid 3D block of bricks with a notch or a doorway in it. To the collision check, it is a grid: five columns across the playfield and four bands up.
Each wall carries three numbers: the band of its top row, and the first and last columns of the opening in that row. The test goes like this:
- If your band is below the wall's top row, you hit solid wall.
- If your band is above it, you fly over.
- If you are in the top row itself, you get through only if your sideways position is inside the opening's columns.
The tall wall at the entrance to the fortress, the first one in a game, has its top row at band 0, the highest, with columns 2 to 4 open. So you must be at least 56 pixels up and in the middle three fifths of the playfield. At 55 pixels, one pixel lower and so in band 1, it is a crash, however clear the ship looks on screen.
The check is not a single moment. When a wall reaches the ship, the game tests it on every frame for 30 frames, half a second, so climbing or sliding into the brick halfway through still counts. While that happens the shadow vanishes, for longer behind taller walls: 96 frames for a wall four bands high, down to 48 for a wall one band high.
Electric barriers use the same numbers in a different way. A barrier is deadly only in its own band, all the way across, and harmless above or below it. So you can fly under a high barrier or over a low one, but not through.
Watching the gap
All of this was read from the original program, then confirmed by running the unmodified 1982 code under a test script that recorded the game's memory every frame through the attract demo and a game. In every frame the ship was flying, the altitude equalled the gap between ship and ground point, or, in about one frame in nine, was one pixel off. The band always matched the 24, 40 and 56 pixel cut-offs, the altimeter bar in video memory always matched what the altitude byte predicts, and the shadow sat exactly on the ground point except when it was raised onto an object.
For the walls, a breakpoint logged every wall test: the wall's three numbers, the band and sideways position of the ship or shot, and whether it crashed. A simple autopilot flew the game, steering for each opening, and in a second run deliberately missing it. Across 3254 logged tests by the ship and its shots (some are repeats, since every run ends in the same attract demo), the rule above predicted every crash and every clean pass, including barriers passed underneath and overhead and one crash into a barrier in its own band.
The full detail, with addresses, is in the height and walls notes.
Credits and further reading
- The MAME project's Zaxxon driver,
src/mame/sega/zaxxon.cppandzaxxon_v.cppat themame0289tag, by Nicola Salmoria, Stephane Humbert and the MAME team: the source for the hardware, the memory map and how sprites and the scrolling background are drawn. - The Z80 disassembler is Lawrence Kesteloot's z80-disasm.
- No published disassembly of Zaxxon was used; every address here comes from the lab's own reading of the ROM.