Mahjong Dojo

The cartridge is in Japanese, and so is the screen that tells you why you won. This puts it into English without touching a single instruction of the game — and gives it the tutorial it never had: twenty attract screens, with all thirty-four tiles drawn, hooked on with a single jp.

Konami · © Konami 1984 · An RC-707 32 KB cartridge · An IPS patch, unofficial · English only

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 patch in numbers

12,103bytes changed
46blocks touched
0bytes changed outside them
12,511bytes of IPS patch
20tutorial screens
34tiles drawn in it

What it took to do it

The cyan band that was not in the patch but on the screen

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 CYAN

The 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.

The text lives in the gap the tiles leave behind

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.

Two letters per slot, and that is why the texts are generated

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 tutorial costs one single jump

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.

The missing tiles: slot numbers are not sacred

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 tiles already there were upside down; and the gap cut the rows

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.

The drawn-hand sign erased what the Japanese one erased

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.

And a letter A that was not there, found only by drawing it

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.

What changes, screen by screen

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.

The title. Only AMACHUA was Japanese —the transcription of «amateur»— so what really changes is the logo: the four kanji 麻雀道場 give way to MAHJONG DOJO on the same 144×24 pixel canvas. And the menu gains a fourth line, 4-key TUTORIAL, which starts the tutorial without waiting for the demo
The title. Only AMACHUA was Japanese —the transcription of «amateur»— so what really changes is the logo: the four kanji 麻雀道場 give way to MAHJONG DOJO on the same 144×24 pixel canvas. And the menu gains a fourth line, 4-key TUTORIAL, which starts the tutorial without waiting for the demo
The table's status bar with the deal starting: EAST 1, the DORA and URA indicators, the HONBA counter, STICK for the riichi sticks and SEM (semiprofessional) in red on the right
The table's status bar with the deal starting: EAST 1, the DORA and URA indicators, the HONBA counter, STICK for the riichi sticks and SEM (semiprofessional) in red on the right
The scoring screen, the one you have to read to know why you won: DEALER, FU 30, HAN 7, PAYS 6000, SCORE 18000, the list of yaku with their han on the right, and the hand split into sets below, each with its fu
The scoring screen, the one you have to read to know why you won: DEALER, FU 30, HAN 7, PAYS 6000, SCORE 18000, the list of yaku with their han on the right, and the hand split into sets below, each with its fu
The message box and the call menu, both at two letters per slot: CALL KAN OR DISCARD ONE, and WIN / RIICHI / PON / CHI / KAN in the cyan panel. With 8×8 letters the box only held seven characters a line
The message box and the call menu, both at two letters per slot: CALL KAN OR DISCARD ONE, and WIN / RIICHI / PON / CHI / KAN in the cyan panel. With 8×8 letters the box only held seven characters a line
CALL TSUMO PON CHI KAN, forced: what the Japanese says in four syllables and what would not fit in 8×8 by any arrangement
CALL TSUMO PON CHI KAN, forced: what the Japanese says in four syllables and what would not fit in 8×8 by any arrangement
NOT ALLOWED, forced. It comes up when you call with an incomplete hand, ask for a riichi that is not allowed, or make a call that does not fit: all three ask for the same drawing
NOT ALLOWED, forced. It comes up when you call with an incomplete hand, ask for a riichi that is not allowed, or make a call that does not fit: all three ask for the same drawing
FURITEN HAND, forced. One of the three warnings that come with the penalty, chosen by the low three bits of 0xE1AC
FURITEN HAND, forced. One of the three warnings that come with the penalty, chosen by the low three bits of 0xE1AC
NO YAKU HAND with PENALTY HAND under it, forced in that order because that is how they come up in play: calling with no yaku costs 12,000 if the player is dealing and 8,000 if not
NO YAKU HAND with PENALTY HAND under it, forced in that order because that is how they come up in play: calling with no yaku costs 12,000 if the player is dealing and 8,000 if not
DRAW / GAME, the drawn-hand sign, forced. This is the one that cleared the wrong cells and left stray letters around it; here with the clearing redone
DRAW / GAME, the drawn-hand sign, forced. This is the one that cleared the wrong cells and left stray letters around it; here with the clearing redone
END, the end-of-game label. The eighteen characters of 終局 are exactly enough for three 16×24 letters, with one blank cell between each pair
END, the end-of-game label. The eighteen characters of 終局 are exactly enough for three 16×24 letters, with one blank cell between each pair

The tutorial, all twenty screens

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.

HOW TO PLAY: two players, you and the computer
HOW TO PLAY: two players, you and the computer
THE TILES: the three suits in full, twenty-seven tiles
THE TILES: the three suits in full, twenty-seven tiles
WINDS AND DRAGONS: the seven honours, each with its name beside it
WINDS AND DRAGONS: the seven honours, each with its name beside it
YOUR HAND: thirteen tiles, you draw one and throw one away
YOUR HAND: thirteen tiles, you draw one and throw one away
THE TABLE: his hand face down, what has been thrown, and yours
THE TABLE: his hand face down, what has been thrown, and yours
THE GOAL: four sets and one pair
THE GOAL: four sets and one pair
A RUN, with the winds as the counter-example
A RUN, with the winds as the counter-example
A TRIPLET: even a wind or a dragon will do
A TRIPLET: even a wind or a dragon will do
THE PAIR, with the white dragon, which is a blank tile
THE PAIR, with the white dragon, which is a blank tile
TURN BY TURN
TURN BY TURN
CALLING: pon, chi and kan drawn out
CALLING: pon, chi and kan drawn out
RIICHI: the thirteen-tile hand and the tile it waits for
RIICHI: the thirteen-tile hand and the tile it waits for
TO WIN: tsumo and ron
TO WIN: tsumo and ron
THE MENU: what each of the five entries does and when to pick it
THE MENU: what each of the five entries does and when to pick it
BE CAREFUL: the river that leaves you furiten
BE CAREFUL: the river that leaves you furiten
THE HAND ENDS: someone calls, or the throws run out
THE HAND ENDS: someone calls, or the throws run out
THE COUNT
THE COUNT
THE SCORE: the dora indicator and the next one
THE SCORE: the dora indicator and the next one
WHAT YOU JUST SAW: the hand the demo has just played
WHAT YOU JUST SAW: the hand the demo has just played
And the keys, which is where you start
And the keys, which is where you start