1987 · Cascade Games

ACE 2

This minisite was contributed by air. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c64/ace-2 with me to Gold.

A hamster's name that makes plane one immortal, a cockpit message nobody ever sees, and what the code does when a pilot runs out of chaff.

01 · The hamster

Secret: entering DUSTY BUG on the high-score table makes plane one immortal for good

The programmer left a message in the code: enter the name of the programmer's hamster on the high-score table and player one becomes immortal. The name is in the code too, scrambled. Press Next letter to unscramble it.

The nine bytes at $6A30, from the listing, each looked up in the game's letter table at $6F7F as $56DA and the other text printers do: the stored byte plus $6F7F gives the real letter. The text COMMENCE CONFLICT follows at once, with no end mark between.

The message, in plain ASCII (the usual codes for letters) at $51B4-$53D3, is never printed. It ends: "IF YOU ENTER THE NAME OF MY HAMSTER ON THE HIGH SCORE TABLE, PLAYER ONE WILL BE IMMORTAL. A REAL HACKER WILL FIND HER NAME FROM THE CODE". The hamster is DUSTY BUG.

After every game, $5634 compares the first eight letters of the name buffer ($6933) with the hamster's name, so DUSTY BU is enough. It makes the comparison whether or not anyone qualified for the table, and whichever pilot typed the name, so a name entered by pilot two makes plane one immortal. A match sets the flag at $0975, and nothing in the game ever clears it. The flag is the last byte of the high-score table, so it is written to the disk with the scores ($1F30) and read back the next time the game loads ($09E5).

With the flag set, plane one burns no fuel ($43FC) and the side panel shows IMMORTAL where it counted the planes left ($1C44). In the kit's machine, from a recorded flight, plane one's fuel stayed at 247 for 300 frames with the flag set and fell to 245 without it. A crash or a kill still marks the plane as lost, but the check that would take it away passes over plane one while the flag is set ($0D93). The other pilot still scores 200 points for each kill ($282F), so an immortal plane one can be shot down again and again for points.

02 · YOU TRAITOR

Secret: the game has a YOU TRAITOR message that it never shows

Message 12 in each pilot's list reads YOU TRAITOR. No instruction in the game raises it.

Every call of the message routine $34F8 in the game, 31 of them, with the message number each one loads into X just before it. Numbers 12 and 19 never appear, and nothing else writes their timers at $0350 and $0370. The texts are from the listing, through pilot one's list at $7432.

The message routine takes the message's number in the processor's X register and a time in its Y register. Every caller loads X with a number written into the instruction itself, so the list above is the whole of what the cockpits can show. Message 19 is a first copy of TARGET LOCKED, pointing at the same text as message 20, which the lock uses. Message 12 has its own text, YOU TRAITOR, at $6CEC. It is also in the older copy of the game's text that the game loads at $C000 and never reads (below), so it was in the game's message list in an earlier build too, and nothing in this build says what it was for.

03 · Out of chaff

Bug: pressing for chaff with none left nudges plane two

With an enemy radar missile in the air and no chaff left, the decoy key shows NO CHAFF. The code then carries on into the lines meant for a pilot who has chaff, with the wrong number in the X register, which those lines use to find the pilot's count.

ByteWhat it isBeforeAfter
$0293the low byte of plane two's missile's position across0255
$0297the middle byte of plane two's position across2528
$0288pilot one's chaff left00
$028Cpilot one's chaff timer00

The decoy routine $2531 run in the kit's simulator from a recorded flight, for pilot one with no chaff and a radar missile in flight: it reached $25EF with X = 11, the message number of NO CHAFF.

The decoy routine shows NO CHAFF through the message routine with X = 11, the message's number. There is no jump past the next lines, which take a chaff from this pilot's count and start its timer, both indexed by X. With 11 in X they hit the object table instead: one is taken from $0293, and 8 is written into $0297, the middle byte of plane two's position across. Plane two moves by less than an eighth of a square of the map, whichever pilot pressed the key, every pass the key is held.

04 · Weight

Bug: plane two's weight comes from plane one's fuel tank

Each pass the game weighs the plane it is working on: its missiles, plus its fuel. The fuel it reads is always plane one's.

AddressInstructionWhat it does
$2837LDA $0344,X ... ADC $0342,Xthe current plane's missiles: X is 0 for plane one and 8 for plane two
$2846LDA $0284plane one's fuel, with no index, for both planes
$2849LSR × 6the fuel over 64, added to the missiles' weight
$2855STA $69the weight, which the flight routine multiplies into the drag

From $282F, the per-pass warnings and weight, and $4252, the flight routine. Plane two's own fuel is at $0285.

Fuel is 0-255, so after the division it adds 0 to 3 to the weight. Plane two's drag follows plane one's fuel gauge: while plane one is full, plane two flies as if full, and once plane one has burnt its fuel, or refuelled, plane two's drag changes with it.

05 · The repair

The game breaks two of its own bytes twice a frame and a timer mends them

Both of the game's raster interrupts call $6066, which writes two wrong bytes into the game and starts a timer that, a few cycles later, makes the chip interrupt the processor with an NMI that puts them back.

ByteCorrectBrokenWhere
$43FC$85 (STA)$86 (STX)the first instruction of the play interrupt
$16E9$EA (NOP)$60 (RTS)inside the routine that draws objects into the view

In the kit's machine, from a recorded flight: 600 NMIs in 300 frames, two a frame, with both bytes correct afterwards. With the NMI vector pointed at an RTI instead, both bytes stayed broken.

$6066 starts timer A of the second CIA chip with a count of 5 and its interrupt on, reaching the chip's registers through an index ($DCF0 + X) so that the CIA 2 addresses never appear in the code. The NMI handler, $2AA6, acknowledges the chip and writes the two correct bytes back. The game sets the NMI vector itself, and the reset vector too, through a pointer built at run time ($0A07). Anything that points the NMI vector elsewhere leaves the play interrupt starting with the wrong instruction and the object drawer returning early.

06 · The alphabet

The game's letters have no Z

All the game's screen text is stored scrambled, one byte per letter, and read back through a table of 26 entries for the codes $41-$5A. Twenty-five of them give a letter. The last gives 0.

The table at $6F7F + $41 to $5A, from the listing: the stored code, and the letter it stands for. Every letter but Z appears once.

The scrambling keeps the text from showing in a memory dump. With no code for Z, no word with a Z in it can be written, and the colour code's grid shows the gap: its column names run A to Y, then AA to FF, and the 26th name in the table at $675E, where Z belongs, is the code $5A, which reads back as a 0 byte. None of the 40 squares the game asks about is in that column.

07 · Leftovers

A plain copy of the scrambled text loads beside it

The loader brings in 2,560 bytes from track 17 to $C000 that no instruction reads: an older build's copy of the game's text and tables, with the text in plain letters.

WhereWhatRead by
$C000-$C9FFthe block now at $6730-$712F, from a build where it sat at $2000: its text pointers point there. The words are the same, in plain ASCII, including YOU TRAITORnothing
$7880-$7FFDa byte-for-byte copy of the code at $3000-$377Dnothing
$51B4-$53D3the programmer's message, in plain ASCIInothing
$7556"S0:QZ", a disk drive's command to delete a file called QZ, then "QZ"nothing

Each found with the references search over the whole game and the access records of runs in the kit's machine: no instruction names these bytes, by address, by pointer or through an index.

The game goes to the trouble of scrambling every word it prints, then loads a plain copy of most of them into memory, where any memory dump shows them. The programmer's message, with its dedication "TO THE VERY WONDERFUL TERESA" and its hint about the hamster, is plain ASCII too, among the code.