There is no source code
Let’s get the awkward part out of the way: the original source to Exile does not exist in any form I have access to. Whatever Peter Irvin and Jeremy Smith’s development setup produced in 1988 — assembler listings, notes, graph paper — is not something you can download.
What you can download is, in some ways, better. At level7.org.uk lives a complete reverse-engineered disassembly of the game, produced without any access to source code, and it is a genuinely heroic piece of work. Every routine named, every table identified, nearly every instruction carrying a comment explaining what it’s doing — around sixteen thousand lines of annotated 6502. The author released it as a tribute to the original developers with no restrictions beyond the game’s own, “in the good faith it was intended”. This project simply would not exist without it.
I worked from the disassembly of the enhanced version — the release
that uses sideways RAM to double the screen size and add sampled speech.
It’s the version with the famous digitised “Welcome to the land of the
exile”, and its listing is the one this whole series refers to when it
quotes addresses like &19da. It’s the version I played back in 1988 on my Master 128.
Reading it
A few lines give the flavour:
; main_game_loop
&19da 46 27 LSR &27 ; whistle_one_active # Clear top bit to indicate
# whistle one not being played
&19dc e6 c0 INC &c0 ; frame_counter
Address, raw bytes, instruction, a label for anything referenced, and the
annotator’s commentary. The labels are the real gift: &0be8 is
meaningless, but consider_promoting_secondary_objects tells you what the
authors were thinking - or at least what the disassembler thought the authors were thinking.
The listing also flags the game’s habits — (nop) where a BIT instruction exists only to skip over the next one, ***
where the enhanced version differs from the standard release, and notes
wherever code rewrites its own opcodes, which in Exile is not a rare
event.
Reading it is still work. A disassembly tells you what each instruction does; it can’t tell you why, and Exile’s why is often three subroutines away, riding in a carry flag. The investigate step I described in the previous article is mostly the process of turning this listing’s what into a why you could re-express in another language.
Executing it
Here’s the part of the method I’m most pleased with. The disassembly isn’t just documentation for this project — it is the executable ground truth.
Every line of the listing carries its raw bytes, so a small loader parses the document back into a 64K memory image: the actual game, byte for byte, reassembled from the same text I read at my desk. A tiny 6502 interpreter — a couple of hundred lines of JavaScript, no video, no sound chip, just the instruction set and a byte array — executes it. That pair is the oracle every reconstructed system is validated against, and it has a property I came to rely on completely: the document I read and the program I test against cannot drift apart, because they are the same file.
When a validator says my TypeScript physics diverged from the 6502 on frame 83, it means it diverged from this listing, executed for real. No second copy of the truth, no “well, my notes said…”.
When the listing is wrong
Almost never — and the exceptions are the best stories in the series. Trusting the disassembly absolutely, and testing against it absolutely, eventually put me in a position to catch it out.
Two examples, both covered properly in later articles. At one address the listing mis-decodes its own instruction stream — two annotated instructions overlap by a byte, and executing it faithfully crashes on an opcode that doesn’t exist. And, more subtly, the game-state data block printed in the listing turns out to be a snapshot taken from a played game rather than the pristine boot image: five map entries near the crashed ship — its airlock doors among them — are in a state the real game’s boot could never produce. I spent a long time convinced my reconstruction was wrong about those doors. It was agreeing with the listing perfectly; the listing was wrong about 1988.
I mean none of this as criticism. A sixteen-thousand-line hand-made disassembly with a handful of byte-level defects is an astonishing hit rate — and it says something nice about the method that the same discipline that catches my bugs eventually caught those too. The working copy of the listing in this project’s repository now carries annotations flowing the other way: notes above the key routines recording what the reconstruction learned, each cross-referencing the TypeScript that implements it.
I don’t know the name of the person who did this - but they deserve a lot of credit. And their work just sort of sits there, quietly, in a text file. Hopefully my work here can bring more attention to it. It’s an amazing piece of work.
The TypeScript source
My intention is to release it in its entirety on GitHub. I just want to do a bit more work scrubbing it up first. Perhaps decouple it from the monorepo that it lives in with this website.