King's Valley

Two copy protections that only fire if the cartridge runs from RAM, fifteen pyramids drawn and matched byte for byte against a real machine's VRAM, and the figures facing the other way, which are not in the ROM at all: they are made by reversing the bits.

Konami - (c) Konami 1985 - An RC-727 16 KB cartridge - MSX1 - page 1 - Dump a8f807a0...

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
651named routines
45.5%of the listing commented
9,803bytes of code
6,581bytes of data
0bytes unidentified

What turned up when we took it apart

The colour table sits underneath the pattern table

In SCREEN 2 the usual layout puts patterns at 0x0000 and colours at 0x2000. This cartridge does it the other way round, and you cannot see that in any address: you see it in the registers. tabla_registros_vdp (0x45C0) holds 02 E2 0E 7F 07 76 03 E4, and in SCREEN 2 registers 3 and 4 are not an address but base plus mask: bit 7 of R3 clear puts colour at 0x0000, and bit 2 of R4 set puts patterns at 0x2000.

The code settles it: 0x4831 draws the wordmark with ld hl,06300h, and 0x6300 masked to fourteen bits is 0x2300, inside the pattern table. Read it the usual way and the shapes come out right and the colours come out striped.

The explorer moves in twenty-four bits

X is not one byte, nor two: it is three. 0x73F6 adds the velocity with add hl,de over 0xE138/0xE139 and carries into 0xE13A with adc a,c. The lowest byte is the fraction, in 1/256 of a pixel, and the top two are exactly the ones lee_celda_de_sala takes as the whole-pixel X when it looks up a cell.

It needs that much X because a room is wider than the screen: the even-numbered rooms are 64 columns, 512 pixels, which will not fit in a byte. When the explorer walks off the side, task 9 does ld (0e139h),bc and changes the high byte by one: a 256-pixel jump, one whole screen.

Eighty-seven bytes of code that looked like data

Five entity loops do ld hl,<closer> / push hl before dispatching, so the ret of whatever they dispatch to does not return to the caller: it falls into the closer, which bumps the index and goes round again. A static tracer cannot follow that, because the address travels through the stack as if it were data.

That is why 87 bytes were showing as "unidentified". All five closers have the same shape -ld hl,<index> / inc (hl) / cp (hl) / jp nz,<body>- and the body they jump to is exactly the label that pushed them.

Two routines nobody calls, and one of them tells you something

0x4501 is nineteen bytes that decode as another variant of drawing a script across the three thirds. 0x4542 is ten bytes that are the counterpart of prepara_escritura_vdp for READING VRAM: it calls SETRD and takes the read port from 0x0007, just as the other takes the write port from 0x0006.

Neither is called, and that is not an impression: the byte pairs 01 45 and 42 45 appear nowhere in the 16,384, checked byte by byte. The second one says something about how the game is built: this cartridge never reads VRAM back. It writes and forgets.

Six entity lists, and what each of them is

The game carries six parallel entity tables and each has its own accessor. You do not have to guess how big an entry is: it is in the multiplication. 0x6A12 does i, 3i, 7i with B carrying the powers of two, so stride 7; 0x65A5 reaches 9i; 0x5AF6 joins the same chain halfway and reaches 17i; and 0x73D3 does 2i, 6i, 22i.

Reading the level descriptor byte by byte says what each one holds: stride 7 the exit doors and the revolving doors, stride 9 the jewels and the trap walls, stride 17 the knives already thrown and stride 22 the mummies. The stride-7 and stride-9 lists share an index, but they are not one entity split in two: they are the doors and the jewels, and what they share is a counter variable.

Sprite flicker is shared out on purpose

actualiza_tabla_de_sprites always writes the same four sprites into the attribute table, but each frame it starts from a different one of a four-entry ring, rotated by a counter at 0xE061.

It is not decoration. On the MSX1 only four sprites per scanline are shown and the lowest-numbered ones win; rotating the write order means the one that drops out changes every frame, so all four flicker evenly instead of the same one always vanishing.

The stone changes colour every four rooms

The rooms came out black on black until we found who sets the colour of the wall and floor tiles. It is not prepara_sala_nueva: it is columna_decorativa (0x6DA0), and the script it uses depends on the group of four levels -0x6DC4 plus 9 per group, with the group taken from (level-1) >> 2-.

That is why the first four rooms are ochre stone and the next ones change colour with the same brick artwork: the only thing that changes is eight bytes of colour.

The cartridge defends itself, twice

Two routines write into the cartridge’s own address space, and from ROM neither does anything. They are not dead code: they are copy protection, and doing nothing is the whole point. A pirated cartridge is a copy in RAM, and there the writes land.

0x403E smashes the first byte of task 1 with a pop hl + ret; 0x409C writes DE over 0x43C0, which is the operand of the jp nc at 0x43BF. Manuel Pazos identified both in his 2009 disassembly; this project had one written up as a failed patch and the other as a fill address.

This is the first version, and there is a second

At 0x5817 our ROM has the three separate comparisons the second build replaces with two subtractions, and the second build’s signature appears nowhere in the 16,384 bytes. What is disassembled here is version 1, bugs included: throwing a knife while the door opens corrupts its tiles, throwing it against an object passes through it, and two trap walls sit in the wrong place.

Every room is twice as wide as it looks

The pop de at 0x6B0E restores the pointer to the band that has just been unpacked, so the cp 030h two instructions later tests THAT band, not the next one: the 0x3x band is drawn and ends the list. Read the other way round it loses one band per room.

The fix is not an opinion: the room buffer was compared against the RAM of a real machine for all fifteen pyramids, 31,680 cells with no difference, and the drawn screens against its VRAM - name, pattern, colour and sprite tables - also with zero.

The text is ASCII minus 0x20

The cartridge’s labels are not in ASCII, and not in a private font with a lookup table either: they are ASCII shifted down by 0x20. The bytes 2B 2F 2E 21 2D 29 plus 0x20 give KONAMI, and the same sum gives SCORE, HI, REST, PUSH SPACE KEY, PLAY START, GAME OVER, SOFTWARE and PYRAMID. 0x00 is the space and 0x1A the copyright sign.

It does carry Konami's hidden mark

Konami hid its catalogue number and the title in katakana at the end of many cartridges; Manuel Pazos (@ManuelPazosMSX) found it. This one has it, ending at 0x7FFF: RC-727 and OU KE NO TA NI, the game’s Japanese title, 王家の谷, the Valley of the Kings.

What the cartridge draws

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

<b>The title screen</b>, built with the cartridge's own steps and matched byte for byte against a real machine's VRAM. The game's wordmark is not one piece of artwork: it is twenty-two steps, one per column, each writing two consecutive patterns from 0x9B on, plus the foot of the G, which drops one row further
The title screen, built with the cartridge's own steps and matched byte for byte against a real machine's VRAM. The game's wordmark is not one piece of artwork: it is twenty-two steps, one per column, each writing two consecutive patterns from 0x9B on, plus the foot of the G, which drops one row further
The screen BEFORE that one: the <b>Konami wordmark</b> scrolling up, which is task 0. Task 1 erases all of it and paints the game's own on top. They are two different screens, and mistaking one for the other is what kept the wrong logo here until 2026-09-04
The screen BEFORE that one: the Konami wordmark scrolling up, which is task 0. Task 1 erases all of it and paints the game's own on top. They are two different screens, and mistaking one for the other is what kept the wrong logo here until 2026-09-04
<b>Every figure in the cartridge, named.</b> The explorer has three sprite sets -empty-handed, with the knife and with the pickaxe- that load into the SAME VRAM address, which is why only one can be there at a time. There is no artwork for facing the other way: it is made on the fly by reversing the bits. The captions on this sheet are written in the cartridge's own typeface
Every figure in the cartridge, named. The explorer has three sprite sets -empty-handed, with the knife and with the pickaxe- that load into the SAME VRAM address, which is why only one can be there at a time. There is no artwork for facing the other way: it is made on the fly by reversing the bits. The captions on this sheet are written in the cartridge's own typeface
The <b>valley map</b>: the fifteen pyramids and the GOAL sign. It is not a list of levels but a <b>ring</b>, and every door in every pyramid carries the number of the pyramid it leads to. The parchment looks white because of a colour the title screen left behind and nothing touches again for the rest of the game: drawn on a clean VRAM it comes out black, which is how it looked here until 2026-09-04
The valley map: the fifteen pyramids and the GOAL sign. It is not a list of levels but a ring, and every door in every pyramid carries the number of the pyramid it leads to. The parchment looks white because of a colour the title screen left behind and nothing touches again for the rest of the game: drawn on a clean VRAM it comes out black, which is how it looked here until 2026-09-04
The <b>first</b>: four jewels, eight ladders, one knife and two mummies
The first: four jewels, eight ladders, one knife and two mummies
The <b>second</b>, two screens wide: seven pickaxes, two revolving doors and two trap walls
The second, two screens wide: seven pickaxes, two revolving doors and two trap walls
The <b>third</b>: five jewels, and the first trap wall in a one-screen room
The third: five jewels, and the first trap wall in a one-screen room
The <b>fourth</b>, with sixteen ladders: the most in the game
The fourth, with sixteen ladders: the most in the game
The <b>fifth</b>, the one the demo plays when nobody touches anything
The fifth, the one the demo plays when nobody touches anything
The <b>sixth</b>: ten pickaxes, and the change to the second group's stone
The sixth: ten pickaxes, and the change to the second group's stone
The <b>seventh</b>, no revolving doors and no traps: just ladders and jewels
The seventh, no revolving doors and no traps: just ladders and jewels
The <b>eighth</b>, with three trap walls and four knives
The eighth, with three trap walls and four knives
The <b>ninth</b>, the only one with a single mummy
The ninth, the only one with a single mummy
The <b>tenth</b>, now in the third group's red stone
The tenth, now in the third group's red stone
The <b>eleventh</b>: two revolving doors in a one-screen room
The eleventh: two revolving doors in a one-screen room
The <b>twelfth</b>, with eight pickaxes and two revolving doors
The twelfth, with eight pickaxes and two revolving doors
The <b>thirteenth</b>: eight pickaxes and no traps
The thirteenth: eight pickaxes and no traps
The <b>fourteenth</b>, twelve pickaxes -the most- and the last group's green stone
The fourteenth, twelve pickaxes -the most- and the last group's green stone
The <b>last</b>: six jewels, and its exit leads back to the first pyramid
The last: six jewels, and its exit leads back to the first pyramid
The <b>final screen</b>, with its labels that stretch. They are not artwork: <code>rotulo_horizontal</code> (0x76A7) writes one end tile and fills sideways, dropping a row and growing one cell each time round until it passes VRAM 0x3A80
The final screen, with its labels that stretch. They are not artwork: rotulo_horizontal (0x76A7) writes one end tile and fills sideways, dropping a row and growing one cell each time round until it passes VRAM 0x3A80
The <b>game screen frame</b> with no room in it, as <code>prepara_sala_nueva</code> (0x4FC9) leaves it. The wall tiles are loaded but still colourless: <code>columna_decorativa</code> supplies that afterwards, and it is what gives each group of four rooms its own stone
The game screen frame with no room in it, as prepara_sala_nueva (0x4FC9) leaves it. The wall tiles are loaded but still colourless: columna_decorativa supplies that afterwards, and it is what gives each group of four rooms its own stone