WORK IN PROGRESS: this patch is not finished. It is playable from end to end and every screen has been seen running, but it is published this way on purpose: the title logo is still weak, the tutorial cannot print a single digit, and the difficulty label is squeezed into three letters. The full list of what is missing is in What is missing; read it before you judge a screenshot.
The ROM came out byte for byte as asked and the scoring screen was wrong: a cyan band repeating «LT» ran right across it. No check in the project caught it, because no check looked at the screen.
Slot 0x0DF looked free by the rule we were using —it is the middle row of a mahjong tile, and those are never drawn in the centre third—. And it is, except that the scoring screen uses it twenty-four times in row 8 as the top edge of a grid of boxes. There it is invisible:
original : pattern FF 00 00 00 00 00 00 00 colour 10
one hairline, black ink on a transparent ground
patched : pattern 00 8E 84 84 84 84 84 E4 colour 17
the LT digraph, black on CYANThe fix was to move that digraph to slot 0x0FA, which no dump draws in that third. The real fix was make pantallas, which compares the original cartridge's screens with the patched ones cell by cell: if a cell draws the same slot number in both, was invisible before and is visible now, there is a letter inside the furniture.
Every mahjong tile is drawn with six characters, two wide by three tall, and the rows fall across two thirds of the screen. In the middle third the middle row of each tile is never drawn, and that is exactly where the cartridge writes its labels: of the 97 characters the status bar uses, 56 are the middle pair of some tile.
That leaves 49 slots for English. And English needs more room than katakana.
With 8×8 letters the message box is stuck at seven characters a line and what the Japanese says does not fit. With a 3×7 font and two letters per slot it goes to fourteen, and the menu from six to twelve: then «CALL TSUMO / PON CHI KAN» does fit.
The price is that a slot costs one per DISTINCT PAIR of letters, not one per letter. Changing a single word reshuffles the whole allocation, so the texts live in the generator and are regenerated; editing them by hand in the patch file is the reliable way to break it. As it stands: 49 distinct pairs for 49 slots, with no margin at all.
The cartridge's state 14 —the end-of-game label— finishes with a jp to the routine that returns to state 0. That jump, and only that one, is the hook: the tutorial goes in the middle and everything else comes for free.
The clock is the cartridge's own: state 14 decrements 0xE004 one frame in four and jumps when it reaches zero, so reloading it and returning is enough to be called again 6.4 seconds later. The slide counter is the sub-mode, which enters at zero by itself. And it is abandoned on a keypress without a single line written for it, because the keyboard door is already open in that state: measured, key 1 on slide 2 reaches the title in 0.08 seconds.
On the tutorial's screen sixteen of the thirty-four tiles were missing: the seven honours, because their usual slots are exactly the ones the patch's alphabet takes, and circles 3 to 9, which have no drawing there at all. A tutorial for a tile game that does not show the tiles is no tutorial.
The way out was that a tile's slot number is not sacred: load the drawing into any free slot and ask for it by the new number. Counting the slots that screen never draws left two clear stretches, and that is where they went. Three details, one test each: the drawings come from the original ROM and not from the already-patched block; they are loaded into one third only and the cartridge's own routine copies them to the others, 864 bytes instead of 2,592; and that takes 1.66 seconds, measured, so the screen is cleared before the load or you watch the previous label with the tiles already overwritten.
The twenty tiles the screen came with were the opponent's, rotated 180 degrees: kanji on top, the shadow in the top-left corner and three black rows underneath. Next to the honours, loaded upright, they looked cut off. Measured: the six slots of SOU1 and PIN1 are, byte for byte, the rotation of the player's block. The tutorial now loads that block as it is and copies 126 slots across VRAM: 54 bytes of code and none of data.
Straightening them exposed a fault from August: the empty slot is slots 0xFA-0xFF and its bottom row, FE FF, is the list interpreter's pair of control codes. Every tile after a gap lost its bottom row. The generator paints the gap black and refuses those two bytes as data, with a test that bites.
When a hand ends with no winner a sign comes up, and before drawing it the cartridge clears the cells it is about to cover. Those cells were chosen for the Japanese: in English the labels sit elsewhere, so what was left on screen was a «D» stuck to EAST 1, a stray «A» above the box and a DORA dangling underneath.
With the right clearing the block grows to 40 bytes and its hole is 39, so it is relocated into the free area and the ld hl that loads it is repointed.
The first tutorial test came out with green squares where the As should be. Slot 0x030 on that screen is not the A: it is the green inside of the end-screen's box, and the screen's own block restores it from the ROM.
It cannot be fixed in that block, because that green is seen, for the 64 frames the wall of tiles takes to cover it. The tutorial loads its own A. Reading the code would never have caught it.
Every picture here is a screenshot of the patched ROM. And not one was taken by hand: a script boots the ROM in openMSX with nothing being drawn, dumps video memory, and the PNG is built from the dump. Three passes: the demo, which plays itself and presses no key; the screens the demo never shows, forced by calling the routines that draw them; and the whole tutorial, photographed slide by slide as it runs on its own. Rebuild them with make capturas.
Each caption says what the game was doing when the shot was taken. The ones the demo never shows are forced by calling the routine that draws them.
They come up on their own at the end of the demo cycle —or at once, with key 4 on the title screen—, 6.4 seconds each, and are abandoned the moment another key is pressed. Here they are in order.