Reverse Engineering
The Great Escape
BY DAVID THOMAS
Never Heard of It
-
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
Specify Sinclair Spectrum Specifications
-
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.
SHOW THEM THE GAME DAVE
DAVE SHOW THEM THE GAME
SHOW THEM DAVE THE GAME
Rippity Doo-Dah: Pull the Game Apart
How do we get started?
-
Dump 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
-
Commence Disassemblifications
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
-
START REVERSING
-
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"
-
Fog O' War
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
SkoolKit
-
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
-
SkoolKit WORKFLOW
REVERSING FUNCTIONS
- Discoveries about one function usually impact elsewhere
- Expect to move around the disassembly a lot
- Function boundaries can be unclear in hand crafted code:
- Multiple entry points
- Fallthrough (no RET...)
- Funcs buried in other funcs
- Even late in the process I was changing my mind about what constituted a complete function
Semantic Hoisting (Explaining Stuff)
-
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
-
-
Register de-allocation
-
Initially our vars are just regs
-
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
-
A Portable TGE Emerges
-
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
IT BE DEMO TIME
IT BE DEMO TIME
IT BE DEMO TIME
IT BE DEMO TIME
IT BE DEMO TIME
#DEMOTIME
Game DISCOVERIES
-
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!
-
TECH DISCOVERIES
-
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
-
Have you never bribed a boiler?
-
-
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
U Wot U Wot Star Dot
-
So... how about a Beeb port?
-
C64 version is already in 6502
-
#jobdone
-
It's already been converted to Atari 8-bit
-
It's also been sped up 15% by a C64 demo crew
-
Thanks For Listening To My Crazed Rantings
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
Stardot thread where RISC OS beta builds are pooed: https://stardot.org.uk/forums/viewtopic.php?f=53&t=18826
The Great Escape (for Stardot talk)
By David Thomas
The Great Escape (for Stardot talk)
Reverse engineering the classic isometric 1986 ZX Spectrum game "The Great Escape".
- 2,842