Casio World Open

An eighteen-hole course in 32 KB, built from only ten layouts: eight are played twice, and in every pair one runs mirrored, with the drawing loop itself flipping the pattern bit by bit. And what the cartridge compresses are not pictures — they are differences between tile codes.

Casio · © Casio 1985 · A 32 KB cartridge · MSX1 · pages 1 and 2 · Dump 7b03fd41…

There is not one illustration or capture here. The wordmark and all eighteen hole plans are drawn from the bytes of the ROM, running in Python the same chain the Z80 runs. And it is checked against the emulator's VRAM: the wordmark's 304 bytes and its 32 of colour, identical; a hole plan with 186 of its 190 cells the same, pattern and colour; and 718 of the 768 cells of an in-game frame drawn with the cartridge's own pattern table.

The cartridge in numbers

100%of the binary explained
435routines identified
18holes, par 72, 10 layouts
8,185bytes of code
24,583bytes of data
0bytes unidentified

What turned up when we took it apart

Eighteen holes from ten layouts, and half of them played backwards

The table at 0x6299 holds eighteen pointers, but they point at ten distinct lists. Eight of those serve two holes each, and only holes 1 and 18 have a layout of their own.

What tells the two holes of a pair apart is one bit: bit 7 of the first byte of its record at 0x45A8. With it set, the drawing loop advances the pointer nine places and then walks the data backwards, and 0x5E7C flips the pattern bit by bit with rlc and rra. Across all eight pairs, without one exception, one carries the bit and the other does not.

The perspective is never computed: it comes pre-drawn, stretch by stretch

The view of the course looks 3D and there is not one projection calculation behind it. The table at 0x6A2B holds eighty maps of 21×19 cells, four to six per hole, and moving up the hole means switching map: (0xE0B5) says which stretch the ball is in.

Each map is assembled from two pieces that end up flush in RAM: 105 bytes of sky, shared by the whole hole, and 294 of the stretch's ground. That is 21×5 and 21×14, and 0xEA00+105 lands exactly on 0xEA69, where the code decompresses the second. And getting closer is no zoom: it is painting one fresh row of twenty-one cells and stepping the pointer twenty-one at a time.

The golfer is nine interlocking sprites, and there are three of him

There is no drawing of a golfer in the cartridge: there are pieces. 0x4F8A composes every pose from up to nine overlapping 16×16 sprites, each in its own colour — the only way to get a multi-coloured figure on an MSX1 — reading a list of pieces and a three-byte table: how far up, how far across, what colour. The pattern number is not even stored: it falls out of index×4 + 0x60.

And there are three golfers, chosen by the club: 22, 29 and 35 pieces, six swing frames each. He grows with the club because the camera does. The listing had them filed as “hole plans 15, 16 and 17”.

What gets compressed are not pictures, they are differences between tiles

0xA8CB does not decompress an image. It decompresses, puts a zero after every byte — turning the run into sixteen-bit values — and takes the running total of them all. What ends up in RAM is a list of tile codes.

And sixteen bits are needed for a concrete reason: the pattern table has 570 entries, so one byte will not reach. That is why 0x5B61 does add hl,bc twice, which is sixteen-bit indexing.

And on top of that, everything else is indices

The hole plans, the terrain views and the golfer's frames do not store tiles: they store positions inside that accumulated list. One byte per cell, and the tile comes out of the indirection.

So the same index map draws different things depending on which list was accumulated first, which is what lets the terrain change without touching the maps.

Each hole's par fits in half a byte

The low nibble of the first byte of the record at 0x45A8 is the par: 3, 4 or 5. Bit 7 of that same byte is the mirror. One byte carries both.

Added up, the eighteen give par 72, with two par 3s and two par 5s.

There are only ten sprites, and half are the same ball

Of everything the cartridge compresses, the only thing that ends up in the VDP's sprite pattern table is the 320 bytes 0x60A2 leaves at VRAM 0x3800: ten 16×16 sprites.

And half of them are the same thing at different sizes: the ball, from a dot to a fat blob, so you can watch it go away. Everything else that moves on screen — the golfer, the trees, the terrain — is painted into the bitmap, not a sprite at all.

The title screen is SCREEN 1 and the game screen SCREEN 2

The title uses the 32-column text mode, with the machine's own font and just 32 bytes of colour for the whole screen: one per eight patterns. The wordmark is 304 bytes copied straight from 0x4301.

And on the way into the game, 0x44F3 does something neat: it enters SCREEN 1 only to keep the character set the BIOS loads, copies it to RAM, and then in SCREEN 2 dumps it back as the course's patterns. The machine's own font ends up being part of the scenery.

What the cartridge draws

Under each picture is where it comes from and what is on it.

<b>The eighteen hole plans</b>, the panel the game keeps down the right of the screen. 0x5DEC paints them: nineteen rows of ten cells from column 22, with the indices of <code>plano_hoyo_NN</code> over the code list accumulated from 0xB349. The mirrored ones come out of the loop itself, not from flipping them afterwards
The eighteen hole plans, the panel the game keeps down the right of the screen. 0x5DEC paints them: nineteen rows of ten cells from column 22, with the indices of plano_hoyo_NN over the code list accumulated from 0xB349. The mirrored ones come out of the loop itself, not from flipping them afterwards
The wordmark up close, palm tree and all. It is the 304 bytes at 0x4301 laid out in two blocks of the name table; against the emulator's VRAM they come out <b>identical, byte for byte</b>
The wordmark up close, palm tree and all. It is the 304 bytes at 0x4301 laid out in two blocks of the name table; against the emulator's VRAM they come out identical, byte for byte
The ten 16×16 sprites 0x60A2 decompresses and copies to VRAM 0x3800. Five of them are the ball at five sizes, which is how you watch it fly away. They are not the cartridge's only ones: the golfer's pieces go right behind them, at 0x3B00
The ten 16×16 sprites 0x60A2 decompresses and copies to VRAM 0x3800. Five of them are the ball at five sizes, which is how you watch it fly away. They are not the cartridge's only ones: the golfer's pieces go right behind them, at 0x3B00
<b>The three golfers</b>, with their six swing frames each. There is no picture of a golfer anywhere in the cartridge: every pose is up to <b>nine overlapping 16×16 sprites</b>, each in its own colour, placed by 0x4F8A from a list of pieces and a three-byte table. The club picks which of the three, which is why the size changes: that is how far away the camera is
The three golfers, with their six swing frames each. There is no picture of a golfer anywhere in the cartridge: every pose is up to nine overlapping 16×16 sprites, each in its own colour, placed by 0x4F8A from a list of pieces and a three-byte table. The club picks which of the three, which is why the size changes: that is how far away the camera is
<b>The eighteen holes seen from the tee</b>, their two white markers in the foreground. Each is its hole's first stretch, resolved cell by cell the way the cartridge does it: the index map against the accumulated code list, and from there to the 8×8 patterns
The eighteen holes seen from the tee, their two white markers in the foreground. Each is its hole's first stretch, resolved cell by cell the way the cartridge does it: the index map against the accumulated code list, and from there to the 8×8 patterns
<b>The five stretches of hole 1</b>, tee to green, drawn from the ROM. Each is a 19×21 map of indices assembled from two pieces: the five sky rows, shared by the whole hole, and the stretch's fourteen ground rows. The perspective is never computed anywhere: <b>it comes pre-drawn</b>
The five stretches of hole 1, tee to green, drawn from the ROM. Each is a 19×21 map of indices assembled from two pieces: the five sky rows, shared by the whole hole, and the stretch's fourteen ground rows. The perspective is never computed anywhere: it comes pre-drawn
The 570 uncompressed 8×8 patterns at 0x8B5E, which draw everything that is not a sprite. That these really are the game's is not an impression: <b>718 of the 768 cells</b> of a real in-game frame come from here
The 570 uncompressed 8×8 patterns at 0x8B5E, which draw everything that is not a sprite. That these really are the game's is not an impression: 718 of the 768 cells of a real in-game frame come from here