Hyper Sports 3

Four events and four different ways of moving the screen: a circuit that is not in VRAM but in two RAM windows, a runway stored twice so it can move half a tile at a time, half a sheet of ice mirrored by hand, and a cyclist who is not a sprite but four tiles with eight one-pixel-shifted copies. Plus a demo nobody plays: it is a recording.

Konami - (c) Konami 1985 - An RC-733 32 KB cartridge - MSX1 - pages 1 and 2 - Dump 247a1476...

Not one capture here. Every picture is drawn from the bytes of the ROM, by running in Python the same decompressor, figure engine and label interpreter the Z80 runs, and then checked byte for byte against openMSX's VRAM: all five screens come out with zero differences in colour, patterns and sprite patterns. 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
931named routines
34.5%of the listing commented
14,410bytes of code
18,358bytes of data
0bytes unidentified

What turned up when we took it apart

The world records live in RAM, which is why they can be beaten

The twelve bytes INIT copies from 0x40CF to 0xE053 are the four marks to beat: 1'45"34 for cycling, 17.97 m for the triple jump, 100 points for curling and 5.90 m for the pole vault. They are the only values in the whole work RAM that do not start at zero.

They sit in RAM rather than ROM because the game overwrites them: 0x93D1 writes the cyclist's time straight over the record as soon as it is improved. The ROM holds no record at all: it holds a starting value, and from then on the mark to beat is the player's own.

The demo is a RECORDED game

The demo is not played by a machine, it is replayed. Each event has its own tape of controller readings stored in ROM, and the loop feeds it frame by frame as if it were the joystick. That is why the demo always does exactly the same thing, down to the marks.

And there is one exception you can see: cycling has no recording. There the rival moves off ld a,r -the DRAM refresh register, which climbs with every instruction- used as a die. It is the only event whose demo never comes out the same twice.

Real sine and cosine, in a sports cartridge

The table at 0x7346 is not a curve drawn by eye: it is ninety degrees of sine, one byte per degree, with 0xFF at ninety. With it and a quarter-turn offset you get both components of any angle.

And in curling the angle is never worked out at all: the stone's two curves normalise the vector -divide it by its approximate modulus- and keep the two components. The stone travels straight without the cartridge ever knowing how many degrees it is on.

The period table has TWELVE values, not ten

The sound period table looked like it had ten entries, and two indices were left over that nobody could place. The two missing ones are hidden inside entry [0] of the track table, the one written off as dead because no track uses it: its two bytes are the continuation of the table next door.

It is the same trick as the pole vault bar table, pointed at two bytes low so the index can start at one instead of zero. Two bytes saved, twice.

Three different scrolling tricks, one per event

All four events move the screen, and no two do it the same way:

Cycling does not keep the circuit in VRAM at all. It lives in two RAM windows -0xE140 and 0xE260, nine rows of thirty-two tiles- that shift one column per frame and are dumped whole. And the cyclist is not a sprite either: he is four tiles from the pattern table, with eight copies of the drawing each shifted one pixel, generated when the event starts by rotating the bits.

The jumps -triple and pole vault- store the track twice, in place and shifted four pixels, and alternate: that is why it moves half a tile at a time. The shifting is done in RAM, with chained sla and rl across twelve consecutive tiles.

And curling does not store half a rink: the right half of the ice is mirrored by hand, bit by bit, as it is built.

Konami's hidden mark, here too

The last sixteen bytes of the cartridge -0xBFF0 to 0xBFFF- carry the game's title in katakana, backwards: ハイパースポーツ3, its length (0x0D), the 0x33 of RC-733 and an 0xAA to close. Nothing reads it: not one instruction in the cartridge points there.

The mark was discovered by Manuel Pazos, and it is in many of Konami's cartridges from these years. Here it is complete and it matches the catalogue number.

What the cartridge draws

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

The title screen, built step by step the way the cartridge builds it. The big lettering is not a picture stored on its own: it is three compressed blocks decompressed into the pattern table with a strip of consecutive tiles laid over them. Checked against openMSX's VRAM: zero bytes different in colour, patterns and sprite patterns.
The title screen, built step by step the way the cartridge builds it. The big lettering is not a picture stored on its own: it is three compressed blocks decompressed into the pattern table with a strip of consecutive tiles laid over them. Checked against openMSX's VRAM: zero bytes different in colour, patterns and sprite patterns.
Cycling, event 0, at the instant the race starts. It is the only screen in the cartridge that closes at <b>zero bytes different across all four tables AND the sprite attributes</b>: 15,104 bytes of VRAM and 128 of sprites, identical to the emulator's. Each cyclist is four tiles plus five sprites; the circuit is not in VRAM at all but in two RAM windows.
Cycling, event 0, at the instant the race starts. It is the only screen in the cartridge that closes at zero bytes different across all four tables AND the sprite attributes: 15,104 bytes of VRAM and 128 of sprites, identical to the emulator's. Each cyclist is four tiles plus five sprites; the circuit is not in VRAM at all but in two RAM windows.
The triple jump, event 1, with the athlete on the mark. The scoreboard up top shows the world record -17.97 m- and the player's own. The runway is stored twice, in place and shifted four pixels, and the athlete is up to seven 16x16 sprites whose patterns are decompressed into VRAM on every single frame.
The triple jump, event 1, with the athlete on the mark. The scoreboard up top shows the world record -17.97 m- and the player's own. The runway is stored twice, in place and shifted four pixels, and the athlete is up to seven 16x16 sprites whose patterns are decompressed into VRAM on every single frame.
Curling, event 2, just built. The right half of the ice is stored nowhere: it is <b>mirrored by hand</b>, bit by bit, as the screen is put together. The house rings are drawn by a clipped-rectangle routine, and at the start they fall outside the view.
Curling, event 2, just built. The right half of the ice is stored nowhere: it is mirrored by hand, bit by bit, as the screen is put together. The house rings are drawn by a clipped-rectangle routine, and at the start they fall outside the view.
The pole vault, event 3, on the first frame of the run-up. The athlete does not come out of a figure table: he is composed from TWO blocks -three pieces from 0x6E15 and the ones at 0x6B6A- plus the sprite for the tip and the twelve tiles of the pole itself. All six sprites and their patterns are byte-for-byte identical to the emulator's.
The pole vault, event 3, on the first frame of the run-up. The athlete does not come out of a figure table: he is composed from TWO blocks -three pieces from 0x6E15 and the ones at 0x6B6A- plus the sprite for the tip and the twelve tiles of the pole itself. All six sprites and their patterns are byte-for-byte identical to the emulator's.
The sixteen versions of the cyclist, drawn from the ROM: two 16x16 drawings and, from each, <b>eight copies shifted one pixel</b>. They are not stored: 0x9CC7 generates them when the event starts, rotating the bits and feeding ones in from the left to get the mask for free. That is how a tile-based cyclist moves pixel by pixel.
The sixteen versions of the cyclist, drawn from the ROM: two 16x16 drawings and, from each, eight copies shifted one pixel. They are not stored: 0x9CC7 generates them when the event starts, rotating the bits and feeding ones in from the left to get the mask for free. That is how a tile-based cyclist moves pixel by pixel.
The fourteen figures of the triple jump athlete, taken from the table at 0x6BD9. Each figure is two to seven five-byte pieces -relative row and column, pattern pointer and colour- closed by an 0x80. The pattern is not sitting there beforehand: it is decompressed into VRAM on the spot.
The fourteen figures of the triple jump athlete, taken from the table at 0x6BD9. Each figure is two to seven five-byte pieces -relative row and column, pattern pointer and colour- closed by an 0x80. The pattern is not sitting there beforehand: it is decompressed into VRAM on the spot.
The eight figures in the table at 0x6E33, the one for the vault itself. The run-up does not use them: that one is composed from two other blocks. And one of them has a piece with colour 0 -transparent- off the screen, still unexplained.
The eight figures in the table at 0x6E33, the one for the vault itself. The run-up does not use them: that one is composed from two other blocks. And one of them has a piece with colour 0 -transparent- off the screen, still unexplained.
The six celebration figures at 0x6D5C, the ones that come out when the jump counts. They are the only athlete figures never drawn during the event itself.
The six celebration figures at 0x6D5C, the ones that come out when the jump counts. They are the only athlete figures never drawn during the event itself.
The cartridge's font, drawn from its own patterns. It is not ASCII: 0x00 is the space, the digits run from 0x10 to 0x19 and the letters start at 0x21. That is why the game's labels read as a string of odd bytes until you translate them.
The cartridge's font, drawn from its own patterns. It is not ASCII: 0x00 is the space, the digits run from 0x10 to 0x19 and the letters start at 0x21. That is why the game's labels read as a string of odd bytes until you translate them.