Not one capture here. Every picture is drawn from the bytes of the ROM, by running in Python the same two script interpreters the Z80 runs. The listing and the numbers are reproducible with make, and reassembling gives back the ROM byte for byte.
This cartridge stores nowhere where the road actually is. To find out whether the car has touched the verge it reads the screen: the routine at 0x6D8B works out the cell the car is in, asks the VDP for it with SETRD and pulls back, with a single in a,(c), whatever tile is drawn there.
Then it sorts it into bands: below 0xCF it is a certain crash, 0xCF to 0xD8 is clear, and 0xD9 to 0xE8 is the verge and needs pixel-level checking. It is the cheapest way to make the car hit what you can see, whatever the road happened to paint there.
There are no track maps. There is a ring of RAM, twenty-four rows by twenty-two columns at 0xE186, and every time the road moves the pointer steps back one row and a new row goes into the gap it leaves. Not one byte of scenery moves: what moves is where you start reading.
And the new row is built by an engine with one branch per stage: stage 2 pastes four columns from a cyclic list, stage 3 pulls the whole row out of a single sixteen-bit word, stage 4 stores seven columns and computes the mirror by adding 0x0D to each tile, stage 5 does the same with four, and stage 6 is like 3 but also redraws the lane markings on top.
The six roads on this page are drawn by running that engine in Python, routine by routine. The check is not that they look right: it is that across 264 steps compared against openMSX -44 per stage- the entire 528-byte ring and every generator variable came out identical to the machine's.
0x5540 does call 05716h, and 0x5716 lands inside the scenery pointer table at 0x570C: it is its last two bytes. Konami uses them for two things at once. Read as a word they are the table's sixth entry; executed they are the ld hl,(0e046h) that starts the routine which advances the ring.
The giveaway is that the sixth entry points at 0x462A - a jr inside the RLE decompressor, which is no scenery artwork at all. The table has five entries, and what follows is already code. These thirty-six bytes spent the whole disassembly classified as data nobody reads.
Two dumps of this cartridge are in circulation. They differ by a single byte, 0x53CB: one has 0x05, the other 0xFF.
That byte is the fifteenth segment in the stage 5 row of the plan at 0x537D, six rows of sixteen bytes each closed with 0xFF. Measured in the emulator by placing the pointer at the end of that row: the 0x05 version plays fifteen segments per cycle and the 0xFF one, fourteen. The one that vanishes is segment 5.
Which of the two plays harder is not claimed here, because it has not been measured. The "Easy" and "Hard" labels they circulate under come from the dump, not from the ROM.
Under acceleration the car moves up the screen by 0x48 of 256 of a pixel per frame. But not always: the routine at 0x6C93 only lets it move while the speed is between 0x18 and 0x50, or above 0x7E. Between 0x50 and 0x7E it stays put.
This is measured, not inferred: across 900 frames of the attract mode the car's Y sits still at 0x8FC0 while the speed climbs from 0x51 to 0x7D, and starts moving again the moment it passes 0x7E. 57 of the 58 comparable frames match the prediction, and the one that does not falls exactly on the boundary between two samples.
The end of a stage has three marks nine apart, which is nine ring rows: at 0x0F00 of distance the rival car is released, at 0x0F09 the finish sign is painted and at 0x0F12 it is crossed.
And the sign is not always the same: the first five stages get the eleven tiles of CHECK POINT, and the sixth the five of GOAL, three columns further right. They read with the same rule as every other text in the cartridge -the pattern index is the ASCII code minus 0x20- and were confirmed by drawing them out of the emulator's VRAM.
Stage 3 draws the whole row from a single sixteen-bit word: each bit picks one of two tiles. Twelve columns are asked for and then ten more, but the second call reloads the same word from the start, because the pointer has not moved.
The upshot is that columns 12 to 21 repeat the pattern of the first ten: the road comes out symmetrical without spending one extra byte or one extra instruction. It is not an oversight, it is the saving.
In SCREEN 2 the usual layout is patterns at 0x0000 and colours at 0x2000. Here it is the other way round, and the eight bytes the cartridge loads into the VDP registers say so - the table at 0x46A9, which reads 02 E2 0E 7F 07 76 03 E4: R3=0x7F puts colours at 0x0000 and R4=0x07 patterns at 0x2000.
R3 and R4 are not addresses, they are a base and a mask, and reading them as if they were gives a result that looks right: the shapes come out fine and the colours come out in stripes. The cartridge itself confirms it, filling the area at 0x0080 with 0xF0 at 0x477F, and 0xF0 only makes sense as a colour.
LEVEL A and LEVEL B are not a multiplier. The level, which lives at (0xE03B), gets involved in four separate places: it doubles or does not double the sideways push objects come out with (0x706D), it changes the fuel-burn step - 0x0180 against 0x01FF, at 0x7374 -, it changes the object spawn delay between seven and twelve (0x6F72), and it removes an entire segment: on the first level segment 0x0A is swapped for 9 (0x7044).
The last fifteen bytes of the cartridge are read by nobody: they are RC-730 and the title in katakana, ロードファイター, written backwards and closed with the length, the two RC digits in BCD and an 0xAA.
The format of that signature was discovered by Manuel Pazos, and without his find these fifteen bytes would have stayed filed under "data nobody reads". Our thanks.
Under each picture is where it comes from and what is on it.