King's Valley

The house's secret bonus -5730 points, which read go-na-mi in Japanese-, an attract mode that is not AI but a recorded game of 77 keypresses, and a game that keeps no collision map at all: it reads the screen to find out where you can walk.

Konami - (c) Konami 1985 - An RC-728 16 KB cartridge - MSX1 - page 1 - Dump 89ae5bdd...

Not one capture here. Every picture is drawn from the bytes of the ROM, by running in Python the same two script interpreters the Z80 runs. The listing and the numbers are reproducible with make, and reassembling gives back the ROM byte for byte.

The cartridge in numbers

100%of the binary explained
512named routines
53.0%of the listing commented
7,789bytes of code
8,595bytes of data
0bytes unidentified

What turned up when we took it apart

5730 points spell KONAMI in Japanese

On a bonus stage, if you stand on the exact square X=0x90, Y=0x39, the game prints KONAMI 5730 PTS and awards those 5730 points. The two figures agree on their own: the caption says so and the ld de,05730h at 0x4931 adds it.

The number is not arbitrary. Japanese numbers can be read by their sound too: 5 = go, 7 = na, 3 = mi, that is go-na-mi. It is an easter egg the company reused across many of its games, arcade ones included.

The attract mode is not AI: it is a recorded game

When nobody is playing, the character moves by itself. No routine decides anything: there are 77 recorded keypresses, compressed at 0x5D82, unpacked to 0xE342, which the routine at 0x468F feeds in where the joystick input would go, one every two frames, until it hits an 0xFF.

The values are the joystick masks themselves, so the rest of the game cannot tell whether a person or the script is playing.

The collision map is the screen itself

This cartridge keeps no walkability map in memory. To find out, it reads the screen: it calls RDVRM and looks at which pattern is drawn on the square. Anything below 0x80 counts as wall, from 0x90 on you can walk.

That explains a detail that would otherwise look odd: whenever an object is placed, the game notes down what was underneath. Otherwise picking it up would punch a walkable hole in the wall.

Fifty zones over twenty-five maps

The game announces fifty zones, and there are only twenty-five distinct maps: at 0x498E, once the zone number reaches 25, it subtracts 25 and starts over from the first map.

And of those twenty-five, four are the same one: entries 4, 9, 14, 19 and 24 all point at the block at 0x6E87. One zone in five is a bonus stage, and they all share a screen.

The proof that the maps are read correctly is not that they look right: it is that all twenty-five, compressed with the house RLE and carrying their length nowhere, unpack to exactly 120 bytes.

Colours sit below patterns, the other way round

In SCREEN 2 you normally put patterns at 0x0000 and colours at 0x2000. Here it is reversed, and the eight bytes the cartridge loads into the VDP registers say so (the table at 0x45F7, 02 E2 0E 7F 07 76 03 E0): R3=0x7F puts colours at 0x0000 and R4=0x07 patterns at 0x2000.

Reading it the wrong way round does not fail loudly: it gives correct shapes and striped colours. It is the classic trap of this mode.

Five enemies, five different ways of chasing

The dispatch at 0x569F sends each type to its own routine:

The sprite table is rotated every single frame

The MSX1 can only show four sprites per line, and the ones that win are always the first in the table: the rest simply vanish.

The routine at 0x459A fixes that by dumping the table starting sixteen bytes further along each frame, wrapping at the end. Since the order keeps shifting, the sprite that loses is never the same one, and what you see is shared flicker instead of an invisible character.

The flowing scenery stores not one frame

The background animations have no alternative artwork in the ROM. The pattern already sitting in video memory is taken and its bits are rotated with rrca or rlca: one pixel of travel per turn, eight bytes per pattern.

The other variant shifts whole bytes one row with an lddr, wrapping the one that falls off.

An address here means nothing without a moment attached

0xE0B0 is two different things depending on when you look: while the zone is being built it holds the unpacked map, 120 bytes; during play it is the 32 sprite attributes, 128 bytes dumped in one go to 0x3B00 -where R5 puts its table-.

The same kilobyte does both jobs because they are never needed at the same time.

A loop that counts fourteen over a list of thirteen

The routine at 0x41D5 looks up the zone number in the list of those carrying a big razzon and, failing to find it, prints the NO BIG RAZZON notice. It enters with ld b,00eh, that is fourteen turns, but from 0x609E to 0x60AA there are only thirteen bytes.

The fourteenth comparison already falls into the next block, zone 0's, and reads 0x08. The thirteen on the list run in ascending order and that 0x08 breaks it. The effect can be stated without guessing at intent: zone 8 matches too, and so it never gets the notice even though it is not on the list.

Code nobody calls

At 0x4575 sits a ten-byte routine that sets up a READ from video memory: the exact twin of the write one that is used. There is not a single call or jp to that address in the whole ROM, nor does it appear as a word in any table. It was left in.

What the cartridge draws

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

<b>The title screen</b>, built by running the cartridge's own steps. The big wordmark is not a single piece of artwork: it is <b>three rows of twenty cells with consecutive patterns</b> from 0xC0 on, written by the loop at 0x44A8 with one <code>inc d</code> per cell. The colour comes from a 480-byte fill that alternates between two values, which is why the wordmark changes colour
The title screen, built by running the cartridge's own steps. The big wordmark is not a single piece of artwork: it is three rows of twenty cells with consecutive patterns from 0xC0 on, written by the loop at 0x44A8 with one inc d per cell. The colour comes from a 480-byte fill that alternates between two values, which is why the wordmark changes colour
The same screen in the other colour. These are not two drawings: it is one, with the colour fill set to 0xC0 instead of 0xD0 depending on bit 0 of the counter at 0xE043
The same screen in the other colour. These are not two drawings: it is one, with the colour fill set to 0xC0 instead of 0xD0 depending on bit 0 of the counter at 0xE043
The <b>playfield frame</b> with no zone in it, as the routine at 0x4A61 leaves it: two rows of twenty-four cells top and bottom, four columns of twenty-two down the sides, and on top the script at 0x71F7 with the rest of the trim
The playfield frame with no zone in it, as the routine at 0x4A61 leaves it: two rows of twenty-four cells top and bottom, four columns of twenty-two down the sides, and on top the script at 0x71F7 with the rest of the trim
The <b>first zone</b>. Each of the map's 120 bytes is a <b>metatile</b>, a 2x2 block of cells whose four indices come from the table at 0x6EF3. Twelve across by ten down, and those two figures do not come from how the picture looks: they are the <code>cp 00ch</code> and <code>cp 00ah</code> the loop at 0x64CD counts with
The first zone. Each of the map's 120 bytes is a metatile, a 2x2 block of cells whose four indices come from the table at 0x6EF3. Twelve across by ten down, and those two figures do not come from how the picture looks: they are the cp 00ch and cp 00ah the loop at 0x64CD counts with
The <b>third zone</b>, now with the clumps that act as obstacles. The picture comes from unpacking the block at 0x6648 with the cartridge's RLE and assembling its metatiles: no capture involved
The third zone, now with the clumps that act as obstacles. The picture comes from unpacking the block at 0x6648 with the cartridge's RLE and assembling its metatiles: no capture involved
The <b>bonus stage</b>, the same one for all five zones that use it (entries 4, 9, 14, 19 and 24 all point at the block at 0x6E87). It draws letters out of the scenery's own metatiles
The bonus stage, the same one for all five zones that use it (entries 4, 9, 14, 19 and 24 all point at the block at 0x6E87). It draws letters out of the scenery's own metatiles
The zone at index <b>8</b> -the one the scoreboard calls 9-, the odd one out: because of the loop that counts fourteen over a list of thirteen, it is the only one that escapes the <code>NO BIG RAZZON</code> notice without being on the list
The zone at index 8 -the one the scoreboard calls 9-, the odd one out: because of the loop that counts fourteen over a list of thirteen, it is the only one that escapes the NO BIG RAZZON notice without being on the list
The <b>thirteenth</b>, one of the tightest in the cartridge
The thirteenth, one of the tightest in the cartridge
The <b>twenty-first</b>. From zone 25 on the game reuses these very maps: fifty zones announced, twenty-five drawings
The twenty-first. From zone 25 on the game reuses these very maps: fifty zones announced, twenty-five drawings
The <b>twenty-fourth</b>, the last one before the bonus stage that closes the lap
The twenty-fourth, the last one before the bonus stage that closes the lap