Prison break game for the 48K ZX Spectrum
Created in my home town of Liverpool by Denton Designs
Released in 1986 by Ocean
One of the best-regarded Spectrum games
Later ported to the PC, Amstrad CPC & Commodore C64
Sequel: Where Time Stood Still
8-bit Z80A CPU at 3.5MHz
16K of ROM
16- or 48K of RAM
Single fixed screen resolution of 256x192 with up to 15 colours
Built-in beeper for music and sound effects
Cassette tape storage
≈ 1400 baud, taking around five minutes to load a game
As with most systems of this generation, games with any sort of performance expectations had to be written in Z80 assembly language.
So how do we get started?
Dump all game memory out
Use .SNA format: Header + Straight dump of RAM
Use graphics ripper to locate any graphics
Sprites: pairs of bitmaps & masks
Font glyphs: usually 8x8 bitmaps
Use hex dump to find non-graphic data
ASCII strings
Lookup tables (tables of flipped bytes etc.)
Rule of thumb when looking at game memory:
Patterns are probably data, noise is probably code
Start disassembling the game
IDA Pro
An interactive disassembler
Handles Z80 assembly language (among many)
Analyses the binary to find funcs
Call graphs
Magic decompilation to C
Eye wateringly expensive (work had a copy)
In practice it kept crashing
No undo (!)
Wrote a script to automate the marking up
Ideally: Pick a func and pull it apart, then repeat
Look for hardware access (keyboard, joystick, sound)
Follow those funcs upwards to find the main game loop
Expect:
"Get player input"
"Move hero"
"Move enemies"
"Play a sound"
"Wipe last frame"
"Draw new frame"
"Wait"
Which locations are genuine instructions?
Run RZX recording of complete play-through of the game with profiling enabled through FUSE
The profile spat out must be real instrs
Capture this profile in IDA Pro as comments
Richard Dymond had pulled apart Speccy classics
Skool Daze, Back To Skool & Contact Sam Cruise
...and built a toolkit called SkoolKit to help out
From a single '.skool' file SkoolKit can output
assembly listings
game snapshots
entire cross-referenced HTML disassemblies
Written in Python and scriptable:
Generate images of game assets, e.g.
Dumps of the game map and the rooms
Even animations from within the game
Game-specific macros
Point of the project is to explain the game's workings
Binary > Raw asm > Commented asm > What?
My approach: Write C-style pseudocode of game logic
Recover variables from register use
Initially our vars are just CPU registers
Analyse vars' lifetimes
Create new vars from regs to explain the intent
Return types
Must survey all callers of a func and decide if values left in regs really are used
Good old self modifying code
Replace with vars in a (pretend) state structure
Wah 😭
You can't get up on the battlements
The secret doors don't go anywhere
There are no secret rooms
The radio has no use
A cast of 27:
Our hero and six active prisoners
vs.
Fifteen guards, four dogs and the commandant
There's nothing really higher up on the map (it's blank)
BUT
You can escape through the main gate!
The game screen is double buffered for scrolling
Can cause lumpy performance due to byte rolls
The exterior map encoding is pretty cunning
Map defn > 32x32 Supertiles > 8x8 Tiles
Fits in <10K
Movable objects are 'people' too
Bug: You can bribe a stove and it goes walking...
A max of eight characters on-screen simultaneously
From a cast of 27
Various bugs spotted just by reading the code
Sprite glitches too
Entire game never uses the Z80's IX register
With suitable pummeling my C-style pseudocode eventually becomes compilable
Marshalled it into C files in a macOS Xcode project and added a virtual ZX Spectrum: screen, keyboard, etc.
The resultant code becomes The Great Escape in C
Work carries on in parallel with the disassembly project
The C version forces questions to be answered!
Feed back those discoveries in to the disassembly
C version has since been ported to macOS, Windows, SDL and recently RISC OS
Eventually delete all of the C-style pseudocode and rewrite the whole disassembly in plain ish English
The Great Escape game entry on World of Spectrum:
http://www.worldofspectrum.org/infoseekid.cgi?id=0002125
Write-up on my site:
http://www.davespace.co.uk/the.great.escape/
Reverse engineering project on github:
https://github.com/dpt/The-Great-Escape
The cross-referenced disassembly output from above: http://dpt.github.io/The-Great-Escape/
Rebuild in C project on github:
https://github.com/dpt/The-Great-Escape-in-C