The code

Getting started · The game · The tape · Findings · Open questions

The memory map, once loaded

When the seven chunks have finished moving, the MSX's memory looks like this. That is 50,712 bytes occupied out of 65,536, 77.4% of the map:

addressbyteswhat is therefrom which chunk
0x0000-0x1F317,986first sprite bank: 242 records of 33 byteschunk 4
0x1F32-0x3AC77,062second bank: 214 recordschunk 5
0x4000-0x54675,224the 26 compressed screen mapschunk 3
0x6000-0x6FFF4,096the scenery: 2,048 of pattern and 2,048 of colourchunk 6
0x7900-0x7FE71,768the musicchunk 7
0x8000-0xDFFF24,576the whole gamethe big BIN

The first four rows and the fifth are underneath the BASIC ROM: they are pages 0 and 1, which on a normally booted MSX are not RAM at all. Only the block at 0x8000 lives where you can see it.

And 0x5480, immediately after the compressed maps, is where the decompressor leaves the current screen's map: 640 uncompressed tiles.

The three tables that run the game

They sit together at the end of the game block:

addresssizewhat it is
0xD00024 × 2pointer to each screen's compressed map
0xD03024 × 4 pointerseach screen's behaviour
0xD0C024 × 88 byteseach screen's record

The behaviour table is this game's nearest thing to a script: every screen declares up to four routines, and the ones it does not use are not left at zero but point at 0xFD9A, the sound vector. It is a cheap way of saying "nothing to do here" without having to test for anything.

The records were delimited by a marker they all carry at byte 84: FF <screen number in ASCII> FF. The first lands at 0xD114 and the last at 0xD8FC, always 88 bytes apart; that made it possible to separate them one by one without assuming anything.

Code that writes over itself

This game modifies itself in several places, and it is worth knowing before reading the listing:

Operands double as variables: the tape loader keeps the pointer to the entry it is reading in 0x81F8 and the chunk's execution address in 0x81FA, and it writes both before reading them, so the values shipped on the tape do not matter.

How the listing was made

It is not a linear disassembly. The real control flow is traced from the entry points and only what is reached gets marked as code; the rest stays as data and has to be explained.

The trace was also validated against the emulator: the program counter was sampled over 200 seconds of real play on a Philips VG-8020 and 1,357 distinct addresses turned up. All 1,357 fall inside what the tracer marks as code, not one outside.

(The reverse does not hold: that sampling takes the PC every 0.5 ms and sees a tiny fraction of what runs, so it says nothing about which code is dead. That is measured a different way, in Findings.)

The comments, measured

A complete listing is not much use if it says nothing. The series applies a double yardstick:

make densidad

TOTAL             9790    3230     33.0%     1308       0

Nine thousand seven hundred and ninety instructions, three thousand two hundred and thirty of them carrying a line comment: 33.0% density. And the second figure, which is the expensive one: zero routines below 10%, out of 1,308.

The series bar is 22% density and no weak routine. This is one of the densest of the published disassemblies.