01 · The city in lines
Let's fly: the city of Targ, one building at a time
To keep rendering under control, the game keeps only one building in memory at a time. The square you're in dictates which building is live.
Click the view, then ← → turn, ↓ ↑ nose up and down, W S forward and back, R F climb and descend, Q E roll.
160 × 136 multicolour pixels, drawn by the page with the game's view code, ported routine by routine. Exhaustively verified as byte accurate.
The square's building is loaded only when the high byte of your X or Y changes ($94FE-$952F), and drawn only while you are low enough (height is under 65536). So buildings 'pop in' only when you enter their square.
From higher up, you see the roads: they are drawn from height 2048 up, as lines between the centres of the squares they join. At height $200000 a fixed picture of 13 roads replaces them ($902A).
02 · Bug
Bug: stand on one patch of grass at the start and E takes you into the Colony Craft
You crash-land at 08-08, and the Colony Craft hangs straight above you at altitude 64,997. There is no lift on the ground here. But one invisible patch of grass – 1,024 units a side and about 14 seconds' walk from where you land – answers the E key as if it were the lift on the Colony Craft's deck. The ride 'down' goes into the Colony Craft's hangar; and pressing E again brings you up on its deck!
Click anywhere to stand there and press E.
Square 08-08 from above: runway marks, the spinning pyramid, the Dominion Dart. One grid step is 256 units, 1/256 of the whole square.
The Colony Craft sits over 08-08, so its deck and the grass underneath share one X and one Y. Only the height tells them apart. Its lift is entry 8 in the table of lift squares at $B4B6/$B4BE, and the E key's test checks the square and the middle bytes of X and Y. It never reads the height. So the patch under the deck's lift works exactly like the lift.
| Test | On the deck | On the ground |
|---|
The E key's test, one instruction group at a time, with the values it reads on the Colony Craft's deck and on the grass under it.
The ride 'down' ends in room 8, the Colony Craft's hangar. Taking the elevator up again from room 8 works as expected: it starts in the room, and once it reaches the surface side, $A312 adds $40FF00 to your height, so it ends on the deck. The underground has no height of its own: a room is a separate box, and no room lies below any point of the city.

E on the grass: down into room 8, the Colony Craft's hangar.

E again: up on the deck, ALT 64997.

Walk off the pad: you tumble all the way down.
It doesn't break the game as much as you'd expect! Hangar 8's three doors are all locked, with object 23 – so at game start, the hangar and deck are as far as you get. Pretty much your only option is to leave by the 'express elevator' – that is, walk off the roof of the Colony Craft.
Try it yourself
- Let the opening play to the end. Touch nothing until you stand at LOC 08-08 and Benson has finished "CRASH LANDED ON TARG". You face south.
- Turn right three-eighths of a turn, to face north-west. The COMP dial turns red as you pass west; north-west is the middle of the red quarter.
- Walk forward for about 14 seconds, about 100 steps, and stop.
- Press E. If nothing happens you are off the patch, which is about 2.5 seconds of walking across.

The foolproof way is to manually place yourself there. Open the VICE monitor and enter > 73 72 then > 79 72 to set your X, Y coordinates, then x to resume – placing you exactly in the middle of the patch at 08-08. Then press E.
03 · Outside the city
Exotic destinations: all the places outside the city
The city of Targ is 16 squares a side, in a world of 256. The game puts four things out in the wasteland: two lifts down to hangars, a pyramid and a mast.
The whole world from above, north up, to scale: 256 squares a side, each 65,536 units. Squares are numbered as the LOC readout numbers them, from −128 to 127, X growing east and Y south. Inside the dashed line LOC shows the square, negatives in reversed figures; beyond it LOC prints ** and no roads are drawn ($B64C). Click a place to find it in the table.
| Place | LOC | X, Y | From where you land | What is there |
|---|
Walking times are at the walk's measured pace, about 100 steps of 80 units in 14 seconds, in a straight line from where you land at 08-08.
No building is ever drawn outside the city: the game loads a model only for squares 0 to 15 on both axes ($952B). So the two lifts out here are objects instead, 61 and 62, each a cage of four stacked squares 1,024 units across, standing on the patch where the E key works, the middle bytes $70 to $73 of X and Y ($B40C). Below them are two hangar complexes of their own. Hangar 6 has three rooms. Hangar 7 has seven, and object 3, the jet, starts there.
The three models from their bytes ($2800/$2840), seen from the side, each to its own scale: a model's coordinates are signed bytes in steps of 16 units. All three objects are fixed (bit 4 of $29C0), so T takes one only while the Kitchen Sink is carried ($980B).
The pyramid is object 56. When carried, the D key can drop an object in mid-air, where the object stays at your height ($98FE).
The mast is object 50. It has no name to print, and nothing in the code refers to it by address. What it is for is unknown.
04 · The other craft
Secret: the brother-in-law's new ship laps the city at ALT 500, for ever
One craft flies on its own from the moment the game starts. It belongs to the Palyar commander's brother-in-law, it has the Dart's shape, and it flies south down the west edge of the city, 32,769 units up, wrapping from the south edge back to the north. Two more craft come only when something calls them: the attack ship and the ship you hire.
Time since you landed
0.0 min
Spent
The ship's step ($85C5): one surface pass adds 256 to its Y, 1/256 of a square southward, and the square number is ANDed with 15, so after row 15 comes row 0. A lap is 4,096 passes. How long that takes depends on how long each pass takes to draw, which depends on where you are: the frames a pass are the game's own, measured in the simulator over a whole lap from each place. Underground the step does not run, and the ship waits.
The ship is object 0, with the Dart's model ($3B25). Its X is always $006F41, 4,287 units west of column 00's centre line, and its height is always 32,769 units, which the panel would show as ALT 00500. Only the Y moves. When you land it is over 00-09.
You can see it from anywhere in the city. The object routine ($9728) draws a whole model only within 65,536 units on every axis; farther away it plots one pixel, and it does that at any distance for an object above you ($9787). On foot, turned to face column 00, look for a pixel above the horizon. On the Play tab, just after the landing, turn left a little less than a quarter of a turn: it is in the middle of the view, just above the horizon. The map above shows where it has got to since.
Nobody can fly it. B boards a craft only when you are on foot within 512 units of it ($985D), and nowhere 32,769 units up can you stand. Yet it has a motion record of its own, record 0, and it is the fastest in the game: a top speed of 11,475, which the SPEED readout would print as **75. The fastest craft you can fly, the CHEESE and the Dart with the Poweramp, reach 9,900.
Shooting it starts script 27 ($8797): YOU HAVE JUST DESTROYED, THE PALYAR COMMANDER'S BROTHER-IN-LAWS NEW SHIP, then PALYAR SHIP ATTACKING. The script also sets bit 5 of $BEC0, the brother-in-law's anger, the same bit that script 1 sets when you take the Dart on the pad without paying: THIS CRAFT BELONGED TO THE PALYAR COMMANDER'S BROTHER-IN-LAW, HE IS NOT TOO PLEASED. The Dart you are offered is his old one. Nothing puts the new ship back once it is shot, and its step still runs, so it goes on flying its line, unseen. His house is the cottage at 07-09.
The attack ship aims, overshoots and aims again
An attack is one ship, object 15, with the Palyar diamond's model whichever side sent it. It aims at you, flies for 46 passes and aims again. Each aim sets its velocity to a 32nd of the distance to you a pass ($8998), so after 46 passes it has gone 46/32 of the way: it overshoots, and each leg leaves it at 0.44 of the distance of the leg before, on the other side of you. It looks at you only when a leg ends: if it is then within 12,288 units on every axis, it stays where it is and fires ($893E). Flying past you on the way does not count.
Its missile, object 14, leaves with a 16th of the distance to you a pass and is not steered afterwards. A hit flashes the view white, prints SHIP DESTROYED if you were in a craft and Benson was not busy, and drops you into the falling mode; the craft you were in is lost, and only CTRL+Q brings the Dart back. The ship itself starts every attack from wherever the last one left it, and the first from under the landing site, 19,738 units below the ground.
A craft holding a straight course at more than about 383 units a pass is never caught. The ship's velocity comes to equal yours, 32 passes' travel behind you, and it fires only from within 12,288 units: in the run above, the Dart cruising at about 4,465 units a pass leads it by 142,851 units for as long as it keeps going.
The hired ship takes 779 passes to come down
Hire the interstellar ship (the radio in room $10, which works with the Antenna, and a million credits) and Benson tells you it will be there in 2 MINS. The next pass puts object 7 over 08-08 at a height of 8,323,072 units, nearly twice the Colony Craft's, and each pass after that takes a 128th of the height's top two bytes off, and one more ($863B).
The height pass by pass, from the step's own arithmetic; the simulator gives the same heights to the unit. It passes the Colony Craft's height after 86 passes and is down after 779. Standing at the landing site that took 7,893 frames, 2 minutes 38 seconds; in a room underground, where the step goes on, 1 minute 29. It lands 4,352 units east and 768 south of the wreck.
Three Darts that never fly
Objects 8 to 15 are the moving ones: move_objects ($8690) moves each of them by its velocity while its lifetime at $BDA3 runs. Only three are ever given a lifetime.
| Object | Model | What it does |
|---|---|---|
| 8 | missile | your missile: 15 moves of 4,096 units |
| 9 | Dart | never moves; can be put on the ground (below) |
| 10 | the wreck | your crashed ship at 08-08; never moves |
| 11 | Dart | never moves, never seen |
| 12 | the Mechanoid | lies in room $66; never moves |
| 13 | Dart | never moves, never seen |
| 14 | missile | the attack ship's missile |
| 15 | Palyar diamond | the attack ship |
One of the three Darts can still turn up. CTRL+Q puts the craft you are in down in a random square of the city ($85F5), and it takes the craft's number from your mode, $A9, which is 9 while you are falling. Press CTRL+Q while you fall, after a hit or off the Colony Craft's deck, and object 9 appears on the ground somewhere in the city. It is a Dart you cannot board, since B takes only objects 0 to 7, and it never moves. In the simulator, from a fall, it landed at 12-15.
05 · Secret
Secret: shoot a building from the next square and nobody notices
A building shot from outside its square is destroyed, but unless you get into that square within 16 passes, the game never counts it, never names it, and nobody comes after you for it.
Where the player is while the building falls:

| Pass | $F4 | $B7 = $F5? | What runs |
|---|
The hit and the sixteen passes after it ($871B, $879B), for a missile that reaches 13-04's Commodore sign. The table follows the code's tests pass by pass; the pictures are the emulator's, from the two live runs: the shot from inside the square, and the shot from next door.
When a missile gets within 4096 units of a square's centre below height 2048, $871B marks the square destroyed in $2B00 at once and starts a countdown of 16 passes in $F4 for square $F5. Everything else waits for the countdown: sinking the building, adding it to the count of Palyar or Mechanoid sites, and starting its script, which names it and sends the owner's ship after you. The routine that does all that returns straight away unless you are standing in that square ($87A4), so flying into it before the countdown ends still gets it counted. Otherwise the countdown runs out anyway, and a later hit finds the square already destroyed and does nothing ($87C1). In the emulator, a missile fired east from 12-04, 1024 units up, destroyed 13-04's sign: $2B4D went from $51 to $D1, the Mechanoid count stayed 0, and Benson said nothing, then or later.
Firing from the ground does not work: level flight still points the nose down by a sine of −0.003, so a missile launched 63 units up hits the ground within five passes, before it reaches the next square's centre. From a little higher it does.
06 · The war of signs
Shooting the Commodore sign makes you a TRAITOR
Ten squares of the city hold billboards: five with the Commodore logo, five with Atari's. Destroying either kind gets a verdict.

13-04: model $C82E, the Commodore logo on two posts. Also at 03-13, 09-13, 04-15 and 09-15.

14-05: model $C7B2, the Atari logo. Also at 14-08, 12-11, 06-15 and 11-15.


TRAITOR!
Shot from inside its square in the Dart: the Commodore sign sinks into the ground and Benson prints TRAITOR! (live). Its square's byte in $2B00 says Mechanoid, script 17 + 32 = 49; the Atari squares run script 50, GOOD SHOW!
Each square's byte in the table at $2B00 holds its owner (bit 6 Mechanoid, bit 5 nobody's, neither Palyar) and, in its low five bits, a script number n. When the square is destroyed, script 32 + n runs once. Scripts 36 to 48 name the landmarks ("YOU HAVE JUST DESTROYED", then BOSHER STADIUM, say), and all but Novabill's then set off an attack by the square's owner; scripts 49 and 50 print their one word and leave you alone.
07 · The screen
The double buffer gives 4 or 5 fps
The view is a bitmap of 160 by 136 wide pixels, and there are two of them: the game draws into one while you look at the other.
One frame of the opening descent, high over the city, drawn by the site's C64 renderer from the memory and video-chip writes recorded in the emulator: all 104,448 pixels match the emulator's own picture of that frame. The button points the view at the other bitmap, which is half drawn.
Above the panel the screen is in multicolour bitmap mode: each byte holds four pixels of two bits, and each pixel is twice as wide as it is tall. Two bitmaps sit in the video chip's second bank, at $4000 and $6000. On every pass the main loop swaps them ($AF84): the counter $24 picks which one the game draws into ($25), and $C7 holds the value the view's raster interrupt writes into $D018 to show the other. At line 186 a second interrupt switches the screen to text for the panel ($BA1E).
Seen from above the whole city, a view takes 13 frames to draw, so the picture changes about four times a second. On the ground, with one building to draw, the main loop runs five passes a second.
08 · Flying
The flight model, pass by pass
Every craft but the interstellar ship runs the same flying step once a pass, with its handling read from a 16-byte record: take-off needs speed, the climb fades above the craft's ceiling, and a touchdown crashes only on a steep drop or a steep nose.
The throttle keys set a target, and the speed chases it: each pass the speed becomes (speed + throttle × thrust) × kept. On the ground a craft slower than 128 has its nose held level. Faster, it takes the level pitch's sine, -0.003, sinks below height 64 and lands again, every pass, until the stick lifts the nose. In the air the height changes by speed × sine of the pitch × the record's climb factor; climbing above the ceiling byte, that factor's power of two is replaced by the ceiling minus the height's top byte. A touchdown crashes when that pass's height step is 256 or more, or the nose is more than 45 degrees down.
Two things follow from the arithmetic. Every craft has a hard ceiling: above its ceiling byte the climb shrinks until the truncated step is zero. Flat out with the nose straight up, the Dart stops at ALT 24000, well short of the Colony Craft's 64997; with the Poweramp, as in the jet or the CHEESE, the top is ALT 105000, which the panel prints **000. And the sine table is sampled half a step off, so the level pitch's sine is −0.003, not 0. Level flight sinks slowly, a fast craft on the ground lands again every pass, and in reverse a craft climbs: SHIFT + 0 lifts the Dart off the ground with its nose level, 9 units a pass. The emulator shows the same heights, 67, 74, 82 and on.
09 · The craft
Eleven motion records
Each craft's handling is sixteen bytes at $9DAD, copied to $BEA0 when you board and after every airborne pass.
| Record | Craft | Routine | Turn kept | Turn step | Pitch step | Bank | Climb | Speed kept | Ceiling | Thrust |
|---|---|---|---|---|---|---|---|---|---|---|
| The table is read from the game's bytes in listing.json, which the built site serves. | ||||||||||
Decoded from the bytes at $9DAD by the loader $9D99: each float is a mantissa byte m and an exponent byte, worth (1 + m/256) × 2^e, e being the exponent byte's top six bits (signed) and bit 0 the sign. Byte 12 ($10 in records 0-7) is read by nothing. The Dart and CHEESE are named by the game's own messages and the new ship by the script that runs when it is shot; the car, jet, Palyar diamond and land Dart are matched to Zzap!64 13's table by where the objects start and by their top speeds.
10 · Top speeds
Top speeds: Zzap!64's table, to the digit
With key 0 and then + held until the game refuses it, the port's top speeds are the figures Zzap!64 printed in May 1986.
| Craft | Starts at | Air, the port | Zzap!64 | Ground, the port | Zzap!64 |
|---|---|---|---|---|---|
| The speeds are computed by the port, which reads the game's bytes from listing.json, served by the built site. | |||||
SPEED as the panel prints it ($B5A8): the speed's whole part, high byte as two digits and low byte × 25/64 as two more. Zzap!64's figures are green where the port gives the same. Holding + multiplies the throttle by 1.03 a pass and stops after 23 passes at 32512, where the next step would reach 2^15 ($B4A7). On the ground every craft lands each pass and takes record 8's speed kept, 0.25. Zzap!64 13 (May 1986), pages 61-62.
11 · The underground
The underground: 174 rooms, each a box with doors drawn on its walls
Below the city every room is a record of a few bytes: three sizes, two colours and four bytes for each door, drawn as a wire box with the doors' outlines on its walls.
This viewer reads the game from listing.json, so it needs the built site.
Room 8, the Colony Craft's hangar, where the lift from 08-08 arrives, looking east at two of its three doors, drawn from the room's record at $30A6 and the door outlines at $928A by a port of the game's projection ($A979) and line drawing ($99DD). The buttons or the arrow keys walk and turn; walking into a doorway, clicking a door or its button goes through it. The port reproduces the game's own drawing byte for byte in 2,942 views of all 174 rooms, run in a 6502 simulator, and room 8's picture in the saved game pixel for pixel.
A room's record starts with its X size, its height and its Y size, in units of 256 (a city square is 65,536 across). Then come two colours: the view is filled with the first and the lines are drawn in the second. Each door is four bytes: its kind, which wall it is in and which door of the next room you come out of, then the room it leads to and its position on the wall. The list ends with a 0, or with $80 for a dark room.
12 · Objects
All 64 objects: every craft, key, crate and sofa
Everything the game draws apart from the city and the rooms is one of 64 objects: the craft you fly, the things you carry, the furniture, the signs on the walls, even the Colony Craft.
This catalogue reads the game from listing.json, so it needs the built site.
Every model drawn from its bytes, through the pointers at $2800/$2840: the last vertex number, then three signed bytes a vertex (X, height, Y) in steps of 16 units, then the edges ($97AB-$97F9). There are no faces, so every edge shows. Where each object starts, its room and its flags are the game's tables at the start ($2480-$25FF, $2880-$29FF). Drag the large view to turn it.
An object is a position, a room, a model and a byte of flags. Room 0 is the surface and $FF is carried or out of play. The flags decide what T can do with it: a fixed object needs the Kitchen Sink carried and a heavy one needs the Antigrav or the Sink ($980B, $9817). Objects 0 to 7 are the craft B can board, and 8 to 15 are the ones the game moves itself, among them your missile, the attack ship and its missile. Twenty-two of them have names, which Benson prints when you take them.
13 · Benson
Benson prints a character a frame, and every character is a note
Benson, the craft's computer, speaks through a strip of 23 cells at the bottom of the panel. Under his words runs a tick: one square wave that sounds for the whole game, retuned every frame from the character he has just printed. A blank sets its pitch to zero, and the note falls silent.
The window and its frame are rows 21-23 of the screen matrix at $5C00, drawn with the character set at $7800 in the colours the code sets: ink from $BBC2, paper from $BA3D. The player is a port of the printer $8DC3. A test runs the game's own code in a 6502 simulator beside it and gets the same window, tick and state on every frame of all 219 messages; the finished "DO YOU WANT TO BUY?" matches the play snapshot byte for byte and the reference screenshot pixel for pixel. The sound is the site's model of the SID playing the printer's writes to $D40F, one a frame, and the window, the roll and the registers follow it. Typed text goes to the same port as a literal, as a script's print would feed it: letters, digits, spaces and * + , - . / ? ! ' only, since the game's character set has nothing else.
Each character moves the window one cell left and enters at the right. After 25 characters the printer stops for 99 frames, so a line lasts 124 frames, about 2.5 seconds, and the next line pushes it out. The window is 23 cells wide, so the first two characters of every line scroll off before the pause: the author pads each line with blanks to centre it.
At start-up $B910 copies 25 bytes from $B921 into the SID, $D400 to $D418, then sets voice 3's control to $41: the pulse wave, gate on. Voice 3's pulse width is $800, half of 4096, so its wave is square. Attack is 0 and sustain 15, so the note reaches full volume at once and stays there. Nothing turns the gate off again. The only other code that touches voice 3 is the printer, and it writes one register: $D40F, the high byte of the frequency.
; $8DC3, once a frame while a message prints 8DC7 CMP #$1A ; 26 frames into the line? 8DCB LDX #$00 8DCD STX $D40F ; then silence, for the 99-frame pause ... 8DE9 LDA $FC ; the character just printed 8DEE AND #$3F ; keep its low six bits 8DF0 CMP #$20 ; a blank? 8DF2 BNE $8DF6 8DF4 LDA #$D0 ; $D0 + $30 carries out to $00 8DF6 CLC 8DF7 ADC #$30 8DF9 STA $D40F ; the pitch for this frame
The low byte of the frequency stays at 0, so the only pitches Benson has are multiples of 256 in the register. On a PAL machine one step of the register is 985,248 / 224 Hz, so each step of $D40F is 15.03 Hz. The letters run from A, $31 at 737 Hz, to Z, $4A at 1,112 Hz, about seven semitones. A blank gives $D0 + $30, which carries out of the byte and leaves 0: at frequency 0 the oscillator stops, and the SID's output stage filters the frozen level to silence.
$D40F | Hz | Nearest note | Characters |
|---|
Only the low six bits of a character count, so the digits land on the same pitches as the first nine letters: 1 sounds like A, and 9 like I. The punctuation sits at the top, and ?, ! and the apostrophe are Benson's highest notes. A line takes 25 frames at 50 a second, half a second of chatter, then 99 frames of silence while it can be read.
14 · Sound
Sound: thirteen sound effects of four bytes each, and an engine tuned by the speed
The game has no music. Its sound effects are thirteen entries of four bytes in one table, each started on voice 1 or voice 2 by the same routine; only the doors' hum and Benson's tick come from elsewhere. The lift and the engine rewrite a register while they play.
Each button plays the game's own register writes, frame by frame, through the site's model of the SID: the four bytes from the table at $B987, then whatever the game writes while the sound runs (the lift's pitch every frame, the wipes' two blocks, the opening's gate). The bytes are read from listing.json. A test runs the game's code in the kit's 6502 simulator and gets the same registers and the same gate changes on every frame, for every button. Voice 3 is Benson's (section 13) and stays silent here.
$B958 (voice 1) and $B93A (voice 2) share a tail at $B961 that closes the voice's gate, then writes the frequency's high byte, the attack and decay, the sustain and release, and the control byte, which opens the gate again with a pulse or noise wave. The frequency's low byte is $80 and the pulse width $800, as $B910 sets them from $B921, so every pulse is square; only the doors' hum changes the low byte, until $B910 runs again. Whatever the voice was playing is cut off.
Nearly every entry has sustain level 0, and nothing closes the gate afterwards. The note rises at the attack rate and dies away at the decay rate: 750 ms for the key beep, 15 seconds for a building. The next sound on the same voice cuts it off. Voice 1 carries the beeps, the missiles and the hits, voice 2 the engine, the lift and the opening. The transporter chime uses both.
The lift's hum, sound $30, holds a steady level: sustain 4 of 15, a quarter of full volume, on a square wave whose own frequency byte is 0. The panel's interrupt supplies the pitch every frame ($BA87 going down, $BAE9 going up) from $BBA5, at the index that also picks the ride's step from $BB89. The pitch is lowest at the two ends of the shaft and highest in the middle, $0280 to $0580, 38 to 83 Hz. The steps are smallest at the ends too, so the lift speeds up and slows down. Most laptop and phone speakers play little that low, and the hum is easier to hear in headphones. At the end of the ride $BB2F closes the gate.
The doors hum on voice 2 with the triangle wave, ring-modulated by voice 1. $AF3E and $AF3A write thirteen registers, $D40D down to $D401, from one of two blocks, $AF53 and $AF61, then $15 into voice 2's control: the triangle, the ring modulation and the gate. The blocks differ in one byte, the low byte of voice 2's frequency: $0550 (80 Hz) or $05E4 (89 Hz). Walking through a door, the lower hum plays while the band rises and the higher one for the 22 frames after; backing through, the lower one holds for 30 frames and the higher one plays while the band comes down. Voice 1 sits at $0980 (143 Hz) with no wave of its own, heard only through the ring modulation. At the end $B910 reloads the whole SID, which stops the hum. In a transporter booth the chime follows: square waves at $0E80 and $0F80, 218 and 233 Hz, which beat against each other 15 times a second as they swell for a second and fade.
The opening plays the Novadrive on voice 2. Sound $28 sets up noise with a three-second attack and leaves the gate closed. NOVADRIVE ENGAGED sets the mode that opens it on every pass ($741C), and the slow-down closes it ($7439, a three-second release). Sound $2C then retunes the noise lower and stretches its fade to 24 seconds. At UNABLE TO CORRECT the opening's script pokes $81 into $D40B itself (operation 25 at $7194), and the rumble of the fall fades until the landing, where the engine's code sets its pitch to zero.
The engine
The slider sets the speed as the game holds it, a two-byte float: $27, the exponent with the sign in bit 0, and $26, the mantissa. The page computes the engine's two registers the way $B5D8 does, and a test that runs the game's own code in the simulator on every value of the two bytes, from eight different last levels, gets the same writes. The bars are the sustain level at each speed; the red band is the one where reversing is silent.
On the surface, and not during the opening's descent, the panel's routine sets the engine note once a pass ($B5D8-$B61C). Voice 2 plays noise. The sustain level is the speed's power of two less 3, and at least 1, so from 32 units a pass the engine gets one step louder each time the speed doubles. The frequency's high byte takes the level in its top four bits and the top four bits of the speed's mantissa below them: the pitch climbs in 16 steps through each doubling and then jumps. When the level rises the game starts sound $24 again, since the SID's envelope only falls to a new sustain level by itself. When the level falls, a write to $D40D is enough.
Below a speed of 1 the sustain and release byte is 0 and the engine is silent. The other silence comes from the arithmetic. The level is the speed's exponent byte less $0C, and bit 0 of that byte is the sign. Going forward at 8 to 16 units a pass the byte is $0C, the difference is 0, and the code replaces it with the minimum, level 1. Reversing at the same speeds the byte is $0D and the difference is 1, which the code keeps: shifted into place it becomes $0C, sustain 0 and a three-second release. The engine falls silent between −8 and −16, SPEED −3 to −5 on the panel, and comes back at −16.
15 · How a message is stored
How a message is stored
A message is a list of one-byte tokens, most of them numbers of words in a dictionary.
All 64 canned messages (pointers $20A0/$20E0, tokens $151F-$16D2) and the 155 messages inside the scripts, decoded as the printer reads them ($8E1E), with words from the dictionary at $1249-$151B through $2120/$2210. The lines under the table are the printer port's output, which matches the game's code frame by frame.
A token of 8 or more is a word with a blank before it; 1 to 7 are endings such as S and ED, glued to the word before. $EF is a blank, $F8-$FE print a counter in decimal, $FF starts literal text that runs to the byte with bit 7 set, and 0 ends the message. Words 230 to 238 are nothing but spaces, nine down to one. They centre a line, and word 230 at the end of a message pushes it into a second, empty line that clears the window.
16 · The event scripts
The event scripts
What Benson says, and when, comes from 51 scripts in a small byte code, run one operation per pass of the main loop.
Every operation reachable from the 51 entries of the table at $0800 and from the opening's script at $7001, 527 in all, decoded as the interpreter $8AB2 reads them, plus two pieces nothing reaches. Triggers come from the room records, the object flags $29C0, the square table $2B00 and the code that starts a script ($8A8C). Headings are the labels of the Source tab.
An operation byte holds the operation in its low six bits; bit 7 turns a test round. A test is followed by its operands and a two-byte target, where the script goes if the test holds. The interpreter waits while a message is printing, so every script moves at the pace of Benson's window.
17 · Money in BCD
Money in BCD, and a purchase without subtraction
The credits are eight decimal digits in four bytes, and the scripts have no way to subtract: a purchase adds the price's ten's complement.
Canned message 21 with those credits, as the window shows it:
What the rooms pay
The addition is a port of operation 14 ($8C73): four decimal-mode additions from the least significant byte up, the carry out of the top byte dropped. It gives the same bytes as the game's code in a 6502 simulator on 10,000 random purchases and on the live test, 9000 + 99995000 = 4000. The prices are read from the sale rooms' scripts; a price in the table adds to the credits as operation 21 does at $1041.
Credits start at 9000 ($710C). The Dart's script adds 99995000 ($0A29), which is 5000 short of 100000000; the carry out of the top digit is thrown away, leaving 4000. The Hertz ship costs 999,999 (99000001 at $0E90), but the check before it ($0E6F) only asks whether the top byte is above zero, so it wants 1,000,000.
18 · Numbers
Two-byte numbers, multiplied by adding logarithms
The 3D view works in two-byte floats, a mantissa and a power of two, and multiplies two of them by adding their logarithms from a 256-byte table.
A and B as the game stores them, and the working of $82FA (multiply), $8334 (divide) and $838B (add), with the logarithms at $5800 and the antilogarithms at $5900 read from the game. Typed numbers are cut to nine significant bits, as $8510 does with the game's positions. Checked: the ports give the same bytes as the game's own routines, run in a 6502 simulator, for 2,000,000 random pairs each and every mantissa pair at 56 exponent pairs.
Error of the product, every pair of mantissas
B's mantissa $00 → $FF
A's mantissa $00 → $FF
−0.44 %+0.44 %
Point at the map to read a pair; click to load it above.
Each dot is one pair of mantissas: red where the game's result is too big, blue where it is too small, against the exact product (or quotient) of the two stored values. Away from the ends of the range the exponents do not change the error. Computed with the ported routines from the tables in the game.
19 · Lines
Drawing a line: eight routines, one per octant
Each edge in the view is drawn by one of eight short routines that step along the longer axis, add a slope byte to an 8-bit counter (or subtract it), and step sideways whenever the counter wraps.
The octants as the view shows them (click one)
Close up
The counter $08 at each pixel of the last line
The view's 160 × 136 pixels, each twice as wide as it is tall, over a sky and ground in the surface's colours from $B27D. Drag to draw; the end may leave the view. Each end is a whole pixel whose offset from the centre becomes a float; from there the port does what $9A94–$9D95 do (the slope by logarithms, the octant through $BBD0, the routine through $BC38/$BC40, the corner from $BBD8/$BBE0 for an end off the view) and runs the routine. Checked: every byte of the bitmap, and the slope, octant and end, match the game's code run in a 6502 simulator for 3,000 random drags and every row and column of the view, in both forms, and 6,000 direct calls of the eight routines.
20 · Controls
The keys, as the game reads them
The game scans the keyboard itself and turns each key into a number, row × 8 + column, with 64 added for SHIFT and 128 for CTRL. The joystick goes in port 2.
| Key | Number | Does | Where |
|---|---|---|---|
| Stick | walk or fly; on foot, up and down step 80 units, left and right turn 1/64 of a turn a pass | $B2FE, $A165 | |
| Fire | a missile, from a craft on the surface | $886A | |
| 1 to 9, 0 | throttle 2n+4; 0 is 214, the fastest | $B47E, $BC50 | |
| SHIFT + digit | the same, in reverse | $B47E | |
| + and − | $28, $2B | throttle × 1.03 or × 0.98 every pass while held | $B499 |
| SPACE, ← | $3C, $39 | throttle 2−31: stop | $BC50 |
| T | $16 | take an object within 256 units | $970A |
| B | $1C | board a craft within 512 units | $970E |
| D | $12 | drop the last object taken | $98FE |
| L | $2A | leave the craft, when landed | $98C8 |
| E | $0E | the lift | $B3FD |
| Y | $19 | yes, when Benson asks | script op 11 |
| CTRL + RETURN | $81 | pause, until the next key | $B335 |
| CTRL + Q | $BE | scatter what you carry over the city and start again in the Dart at 08-08 | $80E8 |
| CTRL + S, CTRL + L | $8D, $AA | save or load position 0-9 on disk | $B382, $819E |
The dispatch is at $B2FE-$B47E. Stick input skips the keyboard for that pass, and any input at all sets bit 7 of $BEC0, which is how Benson knows you have not been doing anything.
21 · The opening
The opening: a countdown, then a crash
The game opens in space, runs its own event script through a failing Novadrive, and drops you in the middle of the city with 9000 credits.

The countdown, over a starfield of 21 stars.

MAXIMUM REVERSE THRUST, with Targ growing.

The descent: the city's roads from above.

CRASH IMMINENT! Then manual control.
From the emulator, about 75 seconds from the start of the game to standing at 08-08. The opening's messages were logged from the message window as they played.
The opening is written in the same byte code as the rest of the game's events, at $7001, and it lives in memory that the second bitmap overwrites once play begins: after the opening it is gone. Its starfield speeds up (−32 a frame, then × 4.05 once, then × 1.012 a frame) and slows down again, and the planet grows as a disc of radius 1024 over the distance, from 1023 to 0 ($74CA). The descent starts at height $7F0088, looking straight down. Script 0 then takes over: CRASH IMMINENT!, one of four landing remarks picked at random ("WHERE AM I", "YOU CRASHED", "GOOD LANDING!", "OUCH!"), the status report ("CRASH LANDED ON TARG", "STATE OF WAR BETWEEN PALYARS AND MECHANOIDS") and the offer of the Dominion Dart for 5000.
The first message on the original disk is NOVADRIVE COUNTDOWN. The copy this page was made from reads ABC UNLIMITED in its place, the cracking group's name, typed over the same bytes at $7009: it is the only change to the game's text.
22 · Protection
The reset button hangs the original
Novagen's disk makes the game look like a cartridge, so that pressing reset runs one of the game's own loops instead of handing the machine back.
$8000 $2170 ; cold start $8004 C3 C2 CD 38 30 ; CBM80 (crack: 0s) $2170 SEI $2171 LDX #$00 $2173 STA $2180,X $2176 DEX $2177 BNE $2171 ; back to LDX $2179 INC $2175 ; never reached $217C JMP $2170

Original: stuck in $2171-$2177.

Crack: BASIC's READY.
Both were reset in the emulator during play. The original is the contributor's own disk, booted to the same point as the crack.
On reset the KERNAL checks $8004 for the letters CBM80, and if they are there it jumps through $8000 as if a cartridge were plugged in. The original holds them, so reset runs $2170, inside the dictionary's pointer table. The code after the loop would wipe memory a page at a time: it steps the page byte of its own STA and goes round again. But the loop's branch goes back one instruction too far, to LDX #$00, so X is 0 at every store: the machine writes to $2180 for ever and never gets to the wipe. Either way, after a reset nothing runs but the loop. The cracked copy clears the signature and changes the branch to land on the $00 of LDX #$00, which is a BRK.
23 · Odds and ends
Things a pilot would not know
Small things found in the code and checked in the emulator.
The bytes at $BCB8-$BCFF, drawn with the game's own panel font (the Atari's space, $00, left blank): a piece of Atari DOS 2's menu, in 40-column lines with the Atari's two-column left margin. Nothing reads them.
- An Atari screen in a Commodore game. The bytes above are in the Atari's internal screen code, which is also how the game stores its panel labels (A is
$21). They are a slice of an Atari's screen memory with the DOS menu on it, carried along in a block of the game's memory. - Benson notices when you do nothing. When the offer of the Dart goes unanswered, he asks IS ANYBODY THERE, AM I TALKING TO MYSELF, ARE YOU STILL ALIVE and WHERE ARE YOU, 18 seconds apart; at the first key or stick movement he says AH! YOU ARE BACK, NOW YOU ARE HERE... I WILL START AGAIN, and starts the briefing over. Any key or stick movement sets bit 7 of
$BEC0($B31B), and script 0 tests it. - RESTORE does nothing. The NMI vector points at
$8009, a bareRTI. - It will not run on an American machine, and crashes trying.
$5024reads the KERNAL's PAL flag and, on NTSC, jumps back to the copy loop at$5000, whose self-modified addresses have already moved on: the second pass copies memory over zero page and then over itself.
- A save file holds the whole world. CTRL + S writes 1904 bytes gathered from 14 blocks (
$8260): every square's state, every object's position, the scripts' state, the credits and the whole zero page. One of the blocks is$8000-$803F, so a position saved from the original disk carries its CBM80 signature into any copy that loads it. - The escape waits for the author. With the billboard at 02-03 destroyed, the author's advert for his earlier game Encounter, your ship refuses to leave: THE AUTHOR WON'T LET YOU LEAVE UNTIL YOU FIX HIS ADVERT (script 7 tests
$2B00+$32). The Anti Time Bomb repairs it. - GAME OVER, for ever. After the escape the script machine's busy flag (bit 6 of
$BEC0) is never cleared, so no other event runs again, and GAME OVER comes round every 18 seconds or so: a 15-second wait, then the line. - The attacking ship's missile is not homing. The ship itself closes in by 1/32 of the distance each pass, but its missile is aimed once, at launch, and flies straight.
- 00-00 has a building nobody has seen. Square number 0 also means "outside the city", so the model the table gives it (
$E424) is never loaded. - You can never have exactly 999,999 credits. Hertz's ship costs 999,999, but the test at
$0E6Fwants the top byte of the credits above zero: 1,000,000. It makes no difference: you start with 9000 and every price is a multiple of 5000, so your credits always end in 4000 or 9000.