Konami's Baseball

The screen's three thirds painted with a single loop that reads its own output, the twelve teams of the 1984 Japanese league hidden in twelve letters, and a computer opponent that plays by writing into the joystick slot.

Konami - (c) Konami 1984 - An RC-724 16 KB cartridge - MSX1 - page 1 - Dump 06504efb...

Not one capture here. Every picture is drawn from the bytes of the ROM, by running in Python the same script interpreter the Z80 runs. The listing and the numbers are reproducible with make.

The cartridge in numbers

100%of the binary explained
629named routines
44.5%of the listing commented
9,618bytes of code
6,766bytes of data
0bytes unidentified

What turned up when we took it apart

The screen's three thirds, with a single loop

SCREEN 2 is three independent thirds, and for all three to hold the same thing you have to write it three times. 0x4485 copies VRAM to VRAM byte by byte, and is given 4,095 bytes from 0x0000 to 0x0800: since the destination runs 0x800 ahead, past the first block it is reading what it has just written. One loop, three identical thirds, 4 KB saved. Done twice: colours and patterns.

And it falls one byte short: 4,095 and not 4,096, so the last byte of the third third is never written.

The colour table sits underneath the pattern table

In SCREEN 2 the TMS9918 does not read R3 and R4 as an address, but as a base bit and a mask. With R4 = 0x07 the patterns land at 0x2000 and with R3 = 0x7F the colours at 0x0000, the reverse of the usual layout.

This cartridge's register table and King's Valley's are identical but for one byte, the border colour: 02 E2 0E 7F 07 76 03 E1 against ... E4.

The Japanese league's twelve teams, in twelve letters

The selection grid shows no names: it shows initials. The twelve bytes at 0x4649 are tile numbers, and drawing the font from the ROM they read: C D G S T W for the Central -Carp, Dragons, Giants, Swallows, Tigers, Whales- and B Bu F H L O for the Pacific -Braves, Buffaloes, Fighters, Hawks, Lions, Orions-. The twelve teams of 1984 Nippon Professional Baseball, alphabetical within each league.

And there is a tile made on purpose for this: 0xE8 is a "Bu" in a single character, which exists only so the Buffaloes are not mistaken for the Braves.

The computer plays by writing into the joystick slot

There is no separate path for the opponent. 0x7d04 works out what a player would do and leaves it written in 0xE011, the very byte where 0x43e2 puts the second player's freshly pressed bits. The menu's demo does the same with 0xE00E, the first player's.

So the rest of the cartridge -the batting, the running, the pitching- neither knows nor cares whether a person or the cartridge itself is playing. And that is why, while the demo is running, 0x6c0e refuses to play any sound at all: the automatic game is silent.

The byte that ends a script is the next sprite's first byte

Every player pose is three scripts -one per colour layer- followed by six offset bytes. In 21 of the 22 poses, the pointer to those six bytes points AT THE 0x00 THAT ENDS THE THIRD SCRIPT: that byte does both jobs, ending the script and being the first layer's row offset.

The only one that does not is 0x50EC, and only because its first offset is 1 and not 0. One byte saved per pose, twenty-one times over.

The ball shrinks because there are five balls

There is no scaling: there are five different drawings at 0x6573, from seven rows down to two. 0x646b picks between them by subtracting the ball's row from its shadow's -which is the height- and comparing against 0x21, 0x0F and 0x06, and drops one more if the shadow is above row 0x40, that is, if the play is going far.

The bounce is not computed: it happens when the ball's row catches up with its shadow's.

The script's address is written behind the CALL itself

0x4582 receives nothing in registers: it does ex (sp),hl, reads from the code itself the two bytes that follow the call, pushes the return address past them so they are never executed, and starts drawing. Nine places call it that way.

Not knowing this, a disassembler takes those eighteen bytes for instructions. The binary still comes out identical -they are the same bytes- but the listing lies, and no amount of re-assembling will catch it.

The batter eats three bytes of the routine next door

The fifteen fielders' records take 21 bytes in the ROM and 32 in RAM. Fifteen times 32 fills exactly 0xE180..0xE35F, right up to where the meter starts: the top end adds up.

The bottom end does not: fifteen times 21 is 315 bytes and from 0x5C03 to 0x5D3B there are 312. The three missing ones are the first three of the routine at 0x5D3B -21 00 E1, that is ld hl,0e100h- and they end up inside the fifteenth record.

A script nobody draws

99 bytes at 0x4AF0 that form a perfectly valid script: they load four sprite patterns into VRAM 0x1800, four more into 0x1D00 and five attributes, and end exactly where code resumes.

Nobody draws them. The previous script ends right there but does not chain; in the whole ROM there is not a single 16-bit immediate between 0x4AF0 and 0x4B53; the two script pointer tables point inside their own blocks; and the nine call 0x4582 carry their argument alongside and none of them is this one.

Every counter at zero means 256

Clearing the screen is three passes with B at zero. They are not empty passes: the Z80 decrements before testing, so a djnz with B at zero goes round 256 times. Three times 256 is the name table's 768 cells, written without the count appearing anywhere.

The font is not ASCII: it is the order the letters were needed in

A is 0xDA, B is 0xD0 and C is 0xD6. There is no order at all: there are the 24 letters the cartridge ever writes, laid down as they were needed. And in the middle, a gift: tiles 0xD8 to 0xDE are P L A Y E R S in a row, which is what lets it write "1 PLAYER" and "2 PLAYERS" with no table at all.

The digits do run in order, 0xF0 plus the digit, which is why the scoreboard and the count are written with a plain or 0f0h.

It carries Konami's hidden mark

Konami hid its catalogue number and the katakana title at the end of many cartridges; Manuel Pazos (@ManuelPazosMSX) found it. This one carries it at 0x7FF6: RC-724 and YA KI U, which is 野球 (yakyu), baseball.

What the cartridge draws

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

The <b>game's title</b>, exactly as 0x44b7 paints it: not a script but <b>46 consecutive tiles</b> from 0x40 to 0x6D in two rows of 23. Since the artwork is unique, counting is enough
The game's title, exactly as 0x44b7 paints it: not a script but 46 consecutive tiles from 0x40 to 0x6D in two rows of 23. Since the artwork is unique, counting is enough
The <b>Konami logo</b> rising up the screen. The main loop writes three rows of consecutive tiles at 0x7a8b and every four frames drops the pointer by 0x20, which is one row
The Konami logo rising up the screen. The main loop writes three rows of consecutive tiles at 0x7a8b and every four frames drops the pointer by 0x20, which is one row
The whole <b>title screen</b>: the 0x44b7 title plus the three chained scripts at 0x46d4, which write the copyright line, PLAY SELECT and the two player lines
The whole title screen: the 0x44b7 title plus the three chained scripts at 0x46d4, which write the copyright line, PLAY SELECT and the two player lines
The <b>league choice</b>. 0x41a5 writes it BELOW the menu without clearing anything: the scripts at 0x470c and 0x4718 sit back to back, so asking the interpreter for two is enough
The league choice. 0x41a5 writes it BELOW the menu without clearing anything: the scripts at 0x470c and 0x4718 sit back to back, so asking the interpreter for two is enough
The <b>Central League</b> grid: C D G S T W, that is Carp, Dragons, Giants, Swallows, Tigers and Whales. The script writes the six initials over the word CENTRAL and blanks the other league's row
The Central League grid: C D G S T W, that is Carp, Dragons, Giants, Swallows, Tigers and Whales. The script writes the six initials over the word CENTRAL and blanks the other league's row
The <b>Pacific League</b> one: B Bu F H L O -Braves, Buffaloes, Fighters, Hawks, Lions and Orions-. The <b>Bu</b> is a tile made on purpose, 0xE8, so as not to repeat the B
The Pacific League one: B Bu F H L O -Braves, Buffaloes, Fighters, Hawks, Lions and Orions-. The Bu is a tile made on purpose, 0xE8, so as not to repeat the B
The <b>stadium</b>, built the way 0x4219 builds it: clear the name table, decompress the script at 0x65ad -patterns and colours-, replicate the two missing thirds and draw the name table with the script at 0x6a1c
The stadium, built the way 0x4219 builds it: clear the name table, decompress the script at 0x65ad -patterns and colours-, replicate the two missing thirds and draw the name table with the script at 0x6a1c
The players' <b>22 poses</b>, with their <b>three colour layers</b> placed exactly where their offsets say. The cartridge does not keep these patterns in VRAM: it uploads them from ROM every time the pose changes
The players' 22 poses, with their three colour layers placed exactly where their offsets say. The cartridge does not keep these patterns in VRAM: it uploads them from ROM every time the pose changes
The <b>font</b> everything is written with, tiles 0xD0 to 0xFF. It is neither ASCII nor in order: it is the 24 letters the cartridge ever writes, laid down as they were needed. Look at 0xD8..0xDE: <b>PLAYERS</b> in a row
The font everything is written with, tiles 0xD0 to 0xFF. It is neither ASCII nor in order: it is the 24 letters the cartridge ever writes, laid down as they were needed. Look at 0xD8..0xDE: PLAYERS in a row