El modo attract del cartucho juega una mano de demo y vuelve a empezar. No explica nada. Este parche engancha al final de ese ciclo veinte pantallas que enseñan a jugar, con las treinta y cuatro fichas dibujadas. Y no hace falta esperar al demo: la tecla 4 en el título las arranca al momento.
Trabajo en curso: mira Lo que falta.
El estado 14 del cartucho —el rótulo del final— acaba con un solo jp a la rutina que devuelve al estado 0. Ese salto, y sólo ése, es el enganche. Todo lo demás sale gratis:
tools/omsx_corta_el_attract.tcl).Lo que no se puede es añadir un estado dieciséis. La tabla de despacho de 0x40ED está pegada al código del estado 0 y el despachador la coge de su propia dirección de retorno con un pop hl. No hay hueco.
El menú del título tiene una cuarta entrada, 4-key TUTORIAL. Las tres de encima suben una fila para hacerle sitio (filas 17, 19 y 21, y PLAY SELECT a la 15), y el bloque de rótulos, 119 bytes donde su hueco eran 103, se reubica en la zona libre.
La puerta del teclado del cartucho (0x4ABC) ya leía las teclas 1 a 4: las reduce a un índice y lo busca en la tabla de dificultad, donde la 4 caía en una entrada vacía y no hacía nada. El parche cambia el call que sigue a esa reducción por otro del mismo tamaño a una rutina de la zona libre: con las teclas 1 a 3 sigue exactamente como antes; con la 4 descarta el retorno a la puerta y entra en el tutorial. Entrar desde el título obliga a cargar lo que el tutorial da por hecho tras el rótulo END y el título no tiene: el alfabeto de la pantalla de recuento en las celdas 0x30-0x7F del primer tercio, y su color, blanco sobre negro. Lo demás —las fichas, los honores, la letra A— lo carga el propio tutorial. Luego se pone en el estado 14 con la cuenta atrás a uno y el reloj del cartucho hace el resto. Pulsar la 4 con el tutorial ya en marcha no hace nada.
Medido en openMSX: el estado 14 llega 0,035 segundos después de la tecla, las veinte diapositivas son píxel a píxel las mismas que salen tras el demo, y el título siguiente es idéntico al de antes.
| pantalla | qué enseña | |
|---|---|---|
| 1 | HOW TO PLAY | dos jugadores, tú y el ordenador |
| 2 | THE TILES | los tres palos del uno al nueve — veintisiete fichas dibujadas |
| 3 | WINDS AND DRAGONS | los siete honores, cada uno con su nombre al lado |
| 4 | YOUR HAND | trece fichas; robas una, tiras otra |
| 5 | THE TABLE | su mano boca abajo, los descartes, tu mano |
| 6 | THE GOAL | cuatro figuras y una pareja |
| 7 | A RUN | tres en orden y del mismo palo — con los vientos de contraejemplo |
| 8 | A TRIPLET | tres iguales; hasta un viento o un dragón |
| 9 | THE PAIR | con el dragón blanco, que es una ficha en blanco |
| 10 | TURN BY TURN | cómo es un turno |
| 11 | CALLING | pon, chi y kan dibujados: lo que llevas y lo que suelta |
| 12 | RIICHI | la mano de trece y la ficha que espera |
| 13 | TO WIN | tsumo y ron |
| 14 | THE MENU | qué hace cada una de las cinco entradas y cuándo se pide |
| 15 | BE CAREFUL | el río que te deja en furiten |
| 16 | THE HAND ENDS | alguien canta, o se acaban los descartes |
| 17 | THE COUNT | las dos manos boca arriba y separadas en figuras |
| 18 | THE SCORE | el indicador de dora y el siguiente |
| 19 | WHAT YOU JUST SAW | la mano que el demo acaba de jugar |
| 20 | las teclas | uno, dos o tres para empezar |
Veinte pantallas a 6,4 segundos son algo más de dos minutos. El parche entero gasta ya 8.049 de los 8.219 bytes libres del cartucho: quedan 170, medidos como los 0xFF que siguen al final de la ROM.
Cada línea sale del manual del propio cartucho —el que se escribió para el desensamblado, con cada regla anclada a la rutina que la decide—. Por eso el tutorial dice dos jugadores y treinta mil puntos, y el furiten de la casa: porque es lo que hace este cartucho.
Dos ejemplos de la diferencia que eso supone:
En esa pantalla no hay dígitos cargados. Las celdas 0x10-0x19 son trozos del rótulo END, y cargar una fuente de dígitos costaría otro bloque. Así que el tutorial escribe los números con letras —«THIRTY THOUSAND POINTS», «IT COSTS ONE THOUSAND»— y no cita ni una cifra.
Que resultó ser lo acertado de todos modos, por una razón que hubo que medir. El plan era que la última pantalla comentase la mano que el jugador acababa de ver, porque el tutorial sale justo detrás del demo. El demo no juega la misma mano en cada vuelta. Volcando 0xE000-0xE3FF en el recuento de dos vueltas seguidas del mismo encendido salen 72 bytes distintos de 1.024 (tools/omsx_repite_la_demo.tcl): en una el marcador es 29.000 y en la otra 30.000. (Dos arrancadas en frío sí dan trazas idénticas; es otra cosa, y era lo que se había medido antes.) Así que la última pantalla comenta el flujo, que es la máquina de estados y sí es fijo, y no cita nada.
A la pantalla del tutorial le faltaban dieciséis de las treinta y cuatro fichas: los siete honores, porque sus celdas de siempre son justo las que ocupa el alfabeto del parche, y los círculos 3 a 9, que ahí no traen dibujo ninguno. La primera versión nombraba los vientos y los dragones sin enseñarlos, que para un juego de fichas no es un tutorial.
La salida es que el número de celda de una ficha no es sagrado. Se carga el dibujo en cualquier hueco y se pide por el número nuevo. Contando las celdas que esa pantalla no dibuja jamás quedaban dos tramos libres:
| fichas | en la ROM | en el tutorial |
|---|---|---|
| honores | 0x2E-0x57 | 0x4E-0x77 |
| círculos 3-9 | 0x58-0x81 | 0x02-0x2B |
| el dorso, al que echan los círculos | 0x28-0x2D | 0x78-0x7D |
Tres cabos, y cada uno costó una prueba:
tools/omsx_mide_la_carga.tcl; eran 1,24 hasta que hubo que recargar también las fichas que ya estaban, ver más abajo), así que el borrado de pantalla va antes de la carga. La primera prueba lo hizo al revés y enseñó el rótulo END con los círculos ya escritos encima de sus letras.No hay que restaurar nada al acabar: la rutina que cierra el tutorial recarga la pantalla entera. Comprobado con un volcado seis segundos después — el logo de Konami sale limpio.
La primera prueba salió con cuadrados verdes donde iban las aes. La celda 0x030 en esa pantalla no es la A: es el verde del interior de la caja del final, y el bloque de esa pantalla lo restaura desde la ROM.
No se arregla ahí, porque ese verde sí se ve, durante los 64 cuadros que tarda el muro de fichas en taparlo. El tutorial carga su propia A en el primer tercio y deja que la reparta la rutina del cartucho. Leer el código no lo habría cazado.
Las veinte fichas con las que venía la pantalla —caracteres, bambúes, círculos 1 y 2 y el hueco vacío, celdas 0x82-0xFF— eran el juego del rival, el que el tercio de arriba de la mesa enseña girado 180 grados: el kanji arriba, el número abajo, la sombra en la esquina de arriba a la izquierda y tres filas negras por debajo. Al lado de los honores y los círculos 3-9, cargados derechos del bloque del jugador, se leían como fichas recortadas por abajo. Medido, no a ojo: las seis celdas de SOU1 y de PIN1 en el volcado del tutorial son, byte a byte, la rotación de 180 grados de las de los bloques del tercio de abajo en 0x9343 y 0x99F9, patrones y colores.
El arreglo cuesta 54 bytes de código y ninguno de datos: el tutorial carga esos dos bloques tal cual desde la ROM —caen en el tercer tercio, el suyo— y copia las celdas 0x82-0xFF al primero antes de cargar lo demás y replicar. Recomprimir veinte fichas en la zona libre habría costado más de mil. Esa copia es por lo que la carga tarda ahora 1,66 segundos en vez de 1,24.
Enderezar las fichas destapó un segundo fallo que estaba desde agosto. El hueco vacío son las celdas 0xFA-0xFF, así que su fila de abajo es FE FF — y ésos son los códigos de control del intérprete de listas de 0x409F: 0xFE lee un destino nuevo y 0xFF acaba la lista. El intérprete se tragaba los dos bytes siguientes como dirección, dejaba sin pintar la fila de abajo de toda ficha que viniera detrás de un hueco —en THE GOAL, los tres bambúes y los tres círculos— y escribía el resto de la hilera en la tabla de patrones del tercer tercio. Con el juego girado esa fila era casi negra y nadie la vio; derecha, es la base de la ficha.
El generador pinta ahora el hueco con la celda negra y rechaza 0xFE y 0xFF como dato en cualquier lista, y un test enseña que el generador de antes producía exactamente feff en esa fila.