Hole in One Professional

Two eighteen-hole courses, an editor to build your own and thirty-five real tour professionals to play against, in 32 KB. And the opponent does not compute its shot: it rehearses it with the real physics and retries until it likes the result.

HAL Laboratory · © HAL 1985 · A 32 KB cartridge · MSX1 · pages 1 and 2 · Dump 99900247…

There is not one illustration and not one screen capture here. The credits, the menu, the scoreboard, the sprites, the swing and all thirty-six holes are drawn from the bytes of the ROM, by running in Python the same decompressors and the same interpreters the Z80 runs. And they do not count because they “look right”: the VRAM built this way is compared byte for byte against openMSX's and 28,240 of 28,240 match. The listing and the numbers come from the binary and are reproducible with make.

The cartridge in numbers

100%of the binary explained
44.4%comment density
36holes across two par-72 courses
35real tour professionals
14,186bytes of code
18,582bytes of data
0bytes unidentified
0routines left unexplained

What turned up when we took it apart

The wordmark and the course take turns with the same forty-five tiles

The title screen carries a wordmark that fills half the screen: HOLE IN ONE in block capitals over a red gradient and Professional in a script face over green, with a golf ball for a dot. And it is not stored separately: it is tiles 0xD3 to 0xFF, the same forty-five that in play are the tee, the green and the flag.

The cartridge swaps them by entering one instruction or the next. 0x66D4 is an or 0AFh, that is the two bytes F6 AF: call there and Z goes clear, and the six calls behind it load the 2 KB block at 0x9F85, which carries the playing tiles. But 0x66C6 ends in a jr $+3 that lands on 0x66D5, the second byte of that same instruction, and 0xAF on its own is xor a: A goes to zero, Z is set, and then the six load only the 360 bytes at 0xAA0E and 0xAAFD, which are the wordmark.

(0xCA40) records which of the two sets is in place, which is why pressing F1 at the menu loads the playing tiles to draw the scorecard and then puts the wordmark's back. The title screen spends 416 of its 768 cells on those forty-five tiles.

The opponent does not compute its shot: it REHEARSES it

What the computer does on its turn is not solve an equation. 0x5B39 rolls it some starting values — a power between 0x18 and 0x1B, a curve between 0x19 and 0x20, the angle to the flag and a club obtained by dividing the distance by eight — and then it enters the loop at 0x5BB4, which plays the whole shot with the real physics: same routine, same wind, same terrain.

When it ends it looks at where the ball landed. Into the water? change the club or the power and hit it again. Too long? trim it. Holed out? knock a point off, so it does not hole every one. And so on until it likes the result, or until it runs out of the tries it is allowed (0xC119, which grows when it is losing).

Only then does 0x5408 replay it in front of the player, walking the power and curve bars up to the values already decided. What you see is not the shot: it is the re-enactment of the rehearsal. During the rehearsal, (0xC118) set to one switches off the joystick, the frame wait and the drawing, so the dozens of shots the opponent plays fit between two frames.

The terrain is decided by the pixel, not by the tile

0x629C classifies what is under the ball by tile number: 0x60 to 0x77 are trees, 0x94 to 0xB3 bunker, 0xB4 to 0xD1 water. But tiles that straddle two terrains cannot be resolved that way, and for those the cartridge reads the VRAM.

0x63B1 pulls the exact bit under the ball out of the pattern table, with the right one of the eight masks at 0x63E9. And 0x63D3 reads from the colour table the nibble belonging to that pixel: the high one if the bit is set, the low one if not. That is what separates fairway from rough, bunker from water, and a bank from everything else.

So collision against the scenery is settled by the drawing, and not by a second table someone would have to keep in step with it.

Golf's honour rule is in the code

In golf, between two players, the one farther from the hole plays first. 0x46FA does exactly that: it measures both distances with 0x475C — the difference in X and in Y, each in absolute value and halved so they fit, then the root of the sum of squares — and gives the turn to whoever is worse off.

With a detail: if both have reached the green it also switches to the close-up view. And if one of the two has already holed out, there is nothing to decide.

Three whole screens at once in the VRAM

The MSX's SCREEN 2 has one name table, but VDP register 2 says where it is. This cartridge builds three and flips that register: 0x1800 is the playing screen, 0x1C00 the eighteen-hole scorecard and 0x3C00 the tournament leaderboard.

0x678B does an xor 1 on the RAM copy of the register — worth 0x400, exactly the gap between 0x1800 and 0x1C00 — and 0x67CC an xor 9, which lands on 0x3C00. Pressing F1 or F2 mid-round redraws nothing: it shows another screen that was already built, and letting go returns to the previous one without a byte lost.

Thirty-five real professionals, and a roll of the dice

At 0x5009 there are thirty-five names from the mid-eighties tour, stored one after another with no pointer and no length: bit 7 of the last character marks where each one ends. Nicklaus, Ballesteros, Trevino, Watson, Norman, Aoki, both Ozakis, Nakajima, Kuramoto…

The tournament does not simulate them shot by shot: for each hole, 0x4EC9 rolls a die, subtracts the personal difficulty each was dealt at the start (0xC09B), adds their fixed adjustment from the table at 0x5130 — one byte from 0 to 7 per golfer — and looks up which band it falls in. The bands give +2, +1, par, −1 and −2, and there are three tables of bands: which one is used depends on whether the player is under, on, or over par. Against a player who is going well, the field tightens.

Every hole declares its three materials and then paints with them

A whole hole takes some 311 bytes on average, and the trick is in the first three. The cartridge copies them to 0xCEC0 and there they stay: they are the hole's palette. Then, in the script, a 0x3n, 0x4n or 0x5n byte repeats the first, second or third of them n+1 times.

What links the two is a subtraction of three: the index comes from the opcode's high nibble and the table it reads from starts at 0xCEBD, three bytes before the header, exactly so that 3, 4 and 5 land on it. There is no palette table: there is an offset that makes the hole's header be the palette.

It is the same format, byte for byte, as the 1984 Hole in One. That cartridge's interpreter reads all thirty-six of these scripts whole.

One roll of the die sets both the tee spot and the pin

0x7005 throws a die modulo nine, and that one number decides two things at once. Through the table at 0x70F2 it places the ball inside the tee box: 0x7024 adds the entry to the tee's coordinates and the result goes to 0xC63F, the ball in the course view. The offsets run from 3 to 17 pixels, which is exactly what the tee box measures — three tiles by two — and the grid differs per par.

And through the table at 0x7128, the same number places the hole inside the green: 0x7043 builds from it the cell where 0x715F writes tile 0xD6. So where you tee off from and where the pin is when you get there are the same roll.

The flag in the long view, by contrast, is in the script: it is tile 0xE9, and 0x6FA5 notes where it lands. What is rolled, besides the tee spot, are the wind and the green's slope, and the level decides how much: on AVERAGE 0x7073 clears bit 6 of the wind, so it blows half as hard.

The file the editor saves is the 1984 cartridge's

GAME >>CONSTRUCTION is not a game mode: it is a full course editor, with SETCHR to pick which tile you paint with, SHOT to actually try the hole, and SAVE, LOAD, COPY, SWAP and CLEAR.

And what it saves is not a format of its own. The twenty-one bytes 0xBF14 puts in front of the file are exactly the ones in front of the SDATA, WDATA and NDATA files on the 1985 Hole In One Extension Course tape, and the offsets line up: 0x16 and 0x3A from the start to the two tables, just as there. Which means a course built on this 1986 cartridge loads into the 1984 Hole in One with BLOAD and CALL GOLF.

The call 0x72D4 that does not point into this cartridge

At 0xBE32 there is a call 072d4h, and 0x72D4 lands in the middle of the course scripts. It is not a tracing error: that address is no longer the cartridge when it executes.

0xBE16 does an ENASLT with EXPTBL[0] and page 1 becomes the BASIC ROM; 0x6FD7, 0x700B, 0x72D4 and 0x72E9 are its cassette routines. Page 2, where all this code lives, is not touched, which is why it can keep running while its own first half is swapped out. When it is done, 0xBE1B brings it back using the slot init stored at 0xFEDB.

Nineteen bytes nobody calls

0xB885 is a complete routine — it builds 10×H+L from (0xCEF9) and returns carry if the result is zero or over 18, that is, it validates a hole number — and its two bytes appear nowhere in the ROM. The routine before it ends in a ret, so nothing falls into it either. It is dead code from the editor.

What the cartridge draws

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

<b>The wordmark</b>, drawn from the ROM: the name table at 0xABA1 with the tiles from 0xAA0E on top. Checked against the emulator: the six pattern and colour tables and the whole name table, <b>13,056 bytes without a single difference</b>
The wordmark, drawn from the ROM: the name table at 0xABA1 with the tiles from 0xAA0E on top. Checked against the emulator: the six pattern and colour tables and the whole name table, 13,056 bytes without a single difference
<b>The cartridge's front page</b>, built with its own steps: the wordmark from 0xABA1 and 0xAA0E and, on top, the four rows of twenty-one characters 0x51BF lays down from 0x1A46. It says who made it: <b>© HAL LABORATORY 1985</b>, produced by <b>F. NAKAMURA</b> and programmed by <b>S. IWATA</b>. The at sign is this font's copyright symbol, and <code>></code> is its full stop
The cartridge's front page, built with its own steps: the wordmark from 0xABA1 and 0xAA0E and, on top, the four rows of twenty-one characters 0x51BF lays down from 0x1A46. It says who made it: © HAL LABORATORY 1985, produced by F. NAKAMURA and programmed by S. IWATA. The at sign is this font's copyright symbol, and > is its full stop
The menu, with its factory settings. Four lines and three parallel tables: 0x40CC says which routine lowers the value, 0x40D4 which raises it and 0x40DE which RAM variable it works on. The jump is not a <code>jp</code>: the address is pushed and the <code>ret</code> does the jumping
The menu, with its factory settings. Four lines and three parallel tables: 0x40CC says which routine lowers the value, 0x40D4 which raises it and 0x40DE which RAM variable it works on. The jump is not a jp: the address is pushed and the ret does the jumping
<b>Hole 1 of QUEEN SIDE</b>, par 4 and 352 metres, with the panel on the left exactly as 0x67EF writes it and the map starting at column eleven. This is the screen that is compared against the emulator: the <b>whole</b> name table, 624 of 768 cells, with <b>zero differences</b> — the 144 left out are the six columns where the game writes live figures
Hole 1 of QUEEN SIDE, par 4 and 352 metres, with the panel on the left exactly as 0x67EF writes it and the map starting at column eleven. This is the screen that is compared against the emulator: the whole name table, 624 of 768 cells, with zero differences — the 144 left out are the six columns where the game writes live figures
<b>QUEEN SIDE in full</b>: the eighteen holes, par 72 and 6,166 metres, drawn one by one with the same script interpreter the Z80 runs. Four par 3s, ten par 4s and four par 5s. Look at hole 10, shaped like a foot, and hole 16, which draws a figure three
QUEEN SIDE in full: the eighteen holes, par 72 and 6,166 metres, drawn one by one with the same script interpreter the Z80 runs. Four par 3s, ten par 4s and four par 5s. Look at hole 10, shaped like a foot, and hole 16, which draws a figure three
<b>KING SIDE</b>, the second course: also par 72 with the same spread of pars, but <b>6,290 metres</b> and visibly much harder. More water, narrower fairways and a lot more black, which is tile 0x00 and the game treats it as out of bounds
KING SIDE, the second course: also par 72 with the same spread of pars, but 6,290 metres and visibly much harder. More water, narrower fairways and a lot more black, which is tile 0x00 and the game treats it as out of bounds
<b>The second name table</b>, at 0x1C00: the eighteen-hole scorecard with its OUT and IN halves. The hole numbers and pars are not in the table: 0x49D8 writes them, reading each hole's par off the tee tile in its script. Here they are placed by that same arithmetic, and they land exactly on the cells the table at 0x4A18 points to
The second name table, at 0x1C00: the eighteen-hole scorecard with its OUT and IN halves. The hole numbers and pars are not in the table: 0x49D8 writes them, reading each hole's par off the tee tile in its script. Here they are placed by that same arithmetic, and they land exactly on the cells the table at 0x4A18 points to
<b>The third name table</b>, at 0x3C00, with the first eighteen of the thirty-five professionals at 0x5009, written in the cartridge's own font. The order is the table's, not a round's: the tournament shuffles them at the start
The third name table, at 0x3C00, with the first eighteen of the thirty-five professionals at 0x5009, written in the cartridge's own font. The order is the table's, not a round's: the tournament shuffles them at the start
And the remaining seventeen. Ballesteros, Nicklaus, Norman, Trevino, Aoki, Nakajima, Kuramoto and both Ozakis: the mid-eighties tour, European, American and Japanese
And the remaining seventeen. Ballesteros, Nicklaus, Norman, Trevino, Aoki, Nakajima, Kuramoto and both Ozakis: the mid-eighties tour, European, American and Japanese
<b>The seven frames of the swing</b>, from 0x9F21. Each frame is four by five tiles and every row starts with a four-bit mask: a bit set is a gap, a bit clear takes the next tile off the strip. The scripts at 0x9EC0 chain them, and on the third — the impact — track 5 plays
The seven frames of the swing, from 0x9F21. Each frame is four by five tiles and every row starts with a four-bit mask: a bit set is a gap, a bit clear takes the next tile off the strip. The scripts at 0x9EC0 chain them, and on the third — the impact — track 5 plays
<b>The close-up view.</b> There is one green script for all thirty-six holes (0x9D6C) and it is built at 0xCCE0 instead of 0xCB00; the patterns and colours that draw it decompress on top of the course's, which is why the panel's bottom six rows are blanked first. The hole goes wherever the table at 0x7128 says, the same nine-position grid but in green coordinates
The close-up view. There is one green script for all thirty-six holes (0x9D6C) and it is built at 0xCCE0 instead of 0xCB00; the patterns and colours that draw it decompress on top of the course's, which is why the panel's bottom six rows are blanked first. The hole goes wherever the table at 0x7128 says, the same nine-position grid but in green coordinates
<b>The whole pattern table</b>, 256 tiles of 2 KB decompressed from 0x9F85 and copied into all three thirds of the screen. Here are the panel frame, the font — with <code>©</code> on the at sign and the full stop on <code>></code> —, grass, water, sand, trees, the golfer and the clubhouse
The whole pattern table, 256 tiles of 2 KB decompressed from 0x9F85 and copied into all three thirds of the screen. Here are the panel frame, the font — with © on the at sign and the full stop on > —, grass, water, sand, trees, the golfer and the clubhouse
The twenty-three sprites, decompressed from 0x6898 to 0x3800. The ball in five sizes — it grows with height, which is how you see it is airborne —, its shadow, the flag, the eight wind arrows and the editor's cursor boxes
The twenty-three sprites, decompressed from 0x6898 to 0x3800. The ball in five sizes — it grows with height, which is how you see it is airborne —, its shadow, the flag, the eight wind arrows and the editor's cursor boxes
And the scorecard's banner, which is the closest thing to a title in the ROM: <b>HAL COUNTRY CLUB</b>
And the scorecard's banner, which is the closest thing to a title in the ROM: HAL COUNTRY CLUB
The tournament leaderboard screen as it comes out of the ROM, before anyone writes on it. RANK, PLAYER, SCORE and HOLE, and eighteen rows 0x674E builds by repeating the same thirty-two-cell block eighteen times
The tournament leaderboard screen as it comes out of the ROM, before anyone writes on it. RANK, PLAYER, SCORE and HOLE, and eighteen rows 0x674E builds by repeating the same thirty-two-cell block eighteen times