The code

Two sibling decompressors

The cartridge stores everything it draws compressed, in two formats that look alike but are not the same.

The run one (0x983C) looks at each byte's high nibble: if it is 0xA it is a run - the low nibble plus two says how many times, the next byte says what value

zero high nibble to open a block, and then the next byte says how many times the pair that follows gets written.

Both stop on the destination pointer, not on the source: the caller leaves in BC the VRAM address to stop at. That is what lets one table serve three different destinations, and also what makes the short tables overrun.

The pair format's low nibble would be an outer counter, but across the 128 blocks of the cartridge's three tables it is zero, so the block never repeats: there is no data here that tells apart the two possible readings of that loop.

Three script interpreters

Neither the scoreboard, nor the title, nor the course is drawn with code: all three are walked as little languages.

One instruction with two entry points

0x9505 is or 0AFh - the bytes F6 AF - and some callers come in on its first byte and some on its second. Through the first, the or runs and the Z flag comes out clear; through the second, the operand runs, which on its own is xor a, and Z is set. That flag is what the six calls behind it read: long tables, or the wordmark's.

How it is traced

The tracer follows the flow from INIT, but there are two places it cannot reach on its own, declared by hand in src/holeinone.entries: the BASIC hook at 0x8010, which is only entered by typing GOLF, and the interrupt handler at 0x94CB, which the game installs itself by writing a jp into H.TIMI.

Everything else comes out of the trace. Of the 16,384 bytes, 6,065 are code actually reached and 10,319 are data declared one by one, with its format and its proof.