Super Cobra

Eight kilobytes in which the main thread does nothing: it starts up, hooks the interrupt and settles into a jr $ forever. The whole game fits inside the video hook, split into fifteen states and eight jobs that take turns, one frame each.

Konami · ©KONAMI 1983 · An RC-705 8 KB cartridge · MSX1 · page 1 · Dump 062aeefd…

There are two kinds of picture here and they are not mixed. The tiles, the sprite drawings and the Konami logo are reconstructed: they are drawn by a tool that repeats, instruction by instruction, the cartridge's two drawing interpreters over an empty video memory. The screens are openMSX screenshots, and their captions say so; the title above is cropped from one of them. The listing and the numbers come from the binary and are reproducible with make.

The cartridge in numbers

100%of the binary explained
15game states
8jobs taking turns
5,783bytes of code
2,409bytes of data
0bytes unidentified

What turned up when we took it apart

With Frogger, from 1983 and 8 KB like this one, it shares no run of bytes

tools/comun_konami.py indexes every twelve-byte chunk of one cartridge and looks for it in the other, stretching each match as far as it goes. With the tool's threshold —24 bytes in a row— Super Cobra gives 400 bytes in common with Athletic Land, 287 with Monkey Academy, 239 with Antarctic Adventure… and zero with Frogger.

The 28 bytes that turn up against Time Pilot are not code either: they are the small KONAMI logo at 0x43BE, a drawing. Konami had two different frameworks running at once, and these two 1983 cartridges are one of each.

The sound player is not copied from Athletic Land: it is revised

It is the biggest thing the two share, and there is no single offset that aligns them. Dropping the threshold to eight bytes, of the 320 in 0x5D30–0x5E70 there are 177 —55.3 %— inside an identical run, spread over six runs whose offsets range from 0x1B0B to 0x1B28.

An offset that drifts 29 bytes along the same block is the signature of code with pieces added and removed in the middle, not of a copy and paste.

The game's letters are not in the cartridge

SUBE_FUENTE (0x4AA0) does ld hl,(00004h). That address is CGTBL, the pointer to the font the BASIC ROM keeps there, and 0x180 bytes are uploaded from it: 48 characters, from 0 to _.

Neither the score digits nor the menu words are Konami artwork. And they are uploaded twice, at two different offsets and in two different colours, because in SCREEN 2 colour goes per pattern line and the same character cannot have two colours.

The same routine draws or erases, depending on where you enter

PINTA_DIBUJO is at 0x4068 and BORRA_DIBUJO two bytes earlier, at 0x4064. The only difference is what they load into C: 0xFF one, 0x00 the other. Down in the loop there is an and c (0x4076) which with 0xFF leaves the byte alone and with 0x00 turns it into zero.

The game really uses it that way: the INVASION SUCCEEDED banner is drawn by entering at 0x4068 and taken away by entering at 0x4064. And the same goes for the submodes: 2 enters at 0x5275 and 4 at 0x5278, three instructions further in, skipping the call that moves the engine flame.

Four tables that start inside an instruction

It is not a misreading, and it is not one: there are four. The explosion offset table (0x566B) starts on the operand of the jp at 0x566A; the how-many-per-zone one (0x58D6), on that of the jp at 0x58D5; the bomb margins one (0x55D3), on a call and an scf/ret.

In all three, the entries that land on top of code cannot be used: the index never reaches the value it would take to read them.

The fourth is uglier. SONIDO_PISTAS (0x5CD8) uses 0x5E5F as its base, two bytes before the first real word: entry 0 sits on the last two note periods and points at 0x383C, outside the cartridge. Sound number 0 cannot be requested, and nobody requests it.

A dispatcher that never returns, and two routines nobody calls

DESPACHA (0x4050) does not keep its table apart: it does a pop hl to take the return address and use it as a base, so the table sits right behind the call and is never returned to. It ends in jp (hl).

That has a consequence: the ret of the dispatched routine does not go back to the dispatcher, it goes back to whatever the caller left on the stack. 0x4691 exploits that with a push hl before dispatching, and that is why 0x488B and 0x49EA run without a single instruction calling them.

Seven bytes that run in RAM because the Z80 cannot do it

0x412B copies seven bytes from 0x41DD to 0xE5F8 and calls them as a routine from then on:

ld (0E5FDh),a  ·  ld (ix+000h),b  ·  ret

0xE5FD is the third byte of the ld (ix+000h),b, that is, its own displacement: the routine writes it over itself with A and then stores B. It is ld (IX+A),B, which does not exist, because IX's displacement is a fixed byte of the opcode and not a register. Those are the only seven bytes of the cartridge that do not run from ROM.

This cartridge does not carry Konami's hidden mark

Manuel Pazos found that Konami cartridges hide their RC-7xx catalogue number and the katakana title at the end of the ROM. It is not here.

The last byte with content is 0x5FF3 —the end of the last sound track— and from 0x5FF4 to 0x5FFF there are twelve 0xFF bytes and nothing else. The "RC-705" on this site comes from the catalogue, not from the binary.

The memory refresh counter, used as a dice

PUNTOS_DE_PREMIO (0x501E) needs a random number and has no generator. It uses the Z80's R register, the dynamic memory refresh counter, which climbs by itself with every instruction executed: its low two bits give 0, 1, 2 or 3, and that goes into the high byte of the prize. Out come 0, 100, 200 or 300 points.

What the cartridge draws

Under each caption is the address it comes from, and whether the picture is reconstructed or captured.

openMSX SCREENSHOT — the title screen and menu, built by states 04 and 06. Keys 1 and 2 play with a joystick, 3 and 4 with the keyboard; what they pick is two bits of 0xE002
openMSX SCREENSHOT — the title screen and menu, built by states 04 and 06. Keys 1 and 2 play with a joystick, 3 and 4 with the keyboard; what they pick is two bits of 0xE002
openMSX SCREENSHOT — a zone in progress: the terrain scrolling double-buffered from 0xE800, the scoreboard on top and the fuel gauge from 0x4F7C
openMSX SCREENSHOT — a zone in progress: the terrain scrolling double-buffered from 0xE800, the scoreboard on top and the fuel gauge from 0x4F7C
openMSX SCREENSHOT — state 01, caught halfway: SUBE_LOGOTIPO (0x4CBF) raises the KONAMI from the bottom up, one 32-byte row every two frames
openMSX SCREENSHOT — state 01, caught halfway: SUBE_LOGOTIPO (0x4CBF) raises the KONAMI from the bottom up, one 32-byte row every two frames
RECONSTRUCTED from 0x4248 — the 256 tiles of the top third with their colour, as MONTA_EL_TITULO leaves them. The grey ones are what the cartridge does not carry: that is where the BIOS letters land
RECONSTRUCTED from 0x4248 — the 256 tiles of the top third with their colour, as MONTA_EL_TITULO leaves them. The grey ones are what the cartridge does not carry: that is where the BIOS letters land
RECONSTRUCTED from 0x443A — the 16×16 sprite drawings. That stream is the only thing in the whole cartridge writing to VRAM 0x1800, which is where VDP register 6 puts the sprite pattern table
RECONSTRUCTED from 0x443A — the 16×16 sprite drawings. That stream is the only thing in the whole cartridge writing to VRAM 0x1800, which is where VDP register 6 puts the sprite pattern table
FLOWN — the whole of zone 1, its 485 columns, with the rockets and the fuel tanks where the cartridge puts them. It is not read from the ROM, because it is not stored in the ROM: <code>tools/mapa.py</code> runs the cartridge on a Z80 interpreter written in Python, plays the game, and saves the column that comes in from the right on every scroll step
FLOWN — the whole of zone 1, its 485 columns, with the rockets and the fuel tanks where the cartridge puts them. It is not read from the ROM, because it is not stored in the ROM: tools/mapa.py runs the cartridge on a Z80 interpreter written in Python, plays the game, and saves the column that comes in from the right on every scroll step
RECONSTRUCTED from 0x4CFA — the 26 tiles of the big KONAMI, 147 bytes identical to Athletic Land's, laid out the way the cartridge lays them: three tiles on top, eleven in the middle and twelve below
RECONSTRUCTED from 0x4CFA — the 26 tiles of the big KONAMI, 147 bytes identical to Athletic Land's, laid out the way the cartridge lays them: three tiles on top, eleven in the middle and twelve below