Konami's Golf

Un campo de nueve hoyos en 16 KB, donde cada hoyo se guarda una sola vez y se lee de dos maneras, los gráficos valen el doble porque el cartucho los espeja al vuelo, y el viento se sortea con el registro de refresco de la memoria.

Konami · © Konami 1985 · Cartucho RC-723, 16 KB · MSX1 · página 1 · Volcado 6c539f0a…

Aquí no hay ninguna ilustración ni captura. El rótulo, el golfista y los nueve campos están dibujados desde los bytes de la ROM, ejecutando en Python los mismos descompresores que corre el Z80, y comprobados byte a byte contra la VRAM del emulador: cero diferencias en 385.199 bytes, repartidos en 30 volcados. El listado y las cifras salen del binario y se reproducen con make.

El cartucho en cifras

100 %del binario explicado
558rutinas identificadas
9hoyos, par 36, 3.512 m
8.665bytes de código
7.719bytes de datos
0bytes sin identificar

Lo que apareció al desmontarlo

Un hoyo, un bloque, dos lectores

Los datos de cada hoyo se guardan una sola vez, y el cartucho los lee de dos maneras distintas: como guión de VRAM pintan el plano de la derecha, y como datos 0x53B2 los desgrana en una rejilla de 12 por 18 en la RAM, que es la que sabe dónde está la calle y dónde el búnker.

Lo que engancha las dos lecturas es el último byte de la cabecera: un 0x80, que en el intérprete significa «cambia de destino», y cuyos dos bytes de destino son justo el principio de la rejilla. Así que pintar por el primer puntero pinta el hoyo entero. En los nueve, las 144 celdas del plano coinciden con lo que la rejilla dice que hay.

El mismo guion dibuja el tile y su espejo, por no hacer lo que parece

El intérprete de guiones tiene dos puertas: una escribe en la VRAM y otra (0x601E) lee el mismo formato contra la RAM. Con eso, 0x5FE2 pinta un tile del campo y luego el mismo tile espejado de izquierda a derecha (0x5FFD), sin gastar un byte más.

Y el espejo sale de un descuido aprovechado. 0x5FFD parece una trasposición —ocho vueltas de rl (hl) y rra, que es como se traspone una matriz de bits—, pero el inc hl de 0x600E está fuera del bucle interno: las ocho rotaciones machacan siempre el mismo byte, que al octavo giro vuelve a estar como estaba, mientras rra recoge sus bits por el otro lado. Lo que sale es la fila con los bits del revés. Se ve en el volcado: donde el guión de 0x60D6 pone F0, el cartucho deja 0F.

Y el remate: 0x6013 escribe un 0x00 detrás de la fila espejada y 0x601B un 0x88 delante, que es la orden de «ocho bytes literales». O sea que 0x5FFD no devuelve unos bytes: devuelve un guión de VRAM ya hecho, y por eso el original y su espejo los puede pintar la misma rutina.

El viento sale del registro de refresco de la memoria

Al empezar cada hoyo, 0x4932 hace ld a,r. R es el contador de refresco de la DRAM: lo lleva el propio Z80 y avanza con cada instrucción, así que su valor en un instante cualquiera es impredecible. De ahí salen las dos cosas: los tres bits bajos más uno dan la fuerza del viento (1 a 8) y los dos siguientes su dirección (0 a 3). Sin generador de aleatorios, sin semilla y sin una tabla que ocupe sitio.

Tiene una consecuencia práctica: el viento es lo único de este cartucho que no se puede predecir leyendo la ROM. Las imágenes de aquí abajo llevan su casilla en blanco por eso, y para comprobarlas contra el emulador hubo que darle los valores que cada volcado tenía en 0xE104 y 0xE105.

La ROM está cosida por solapes deliberados

Casi todas las tablas de este cartucho se indexan desde 1, y su entrada 0 —la que nunca se usa— está puesta encima de otra cosa. No es descuido: es no gastar los dos bytes.

0x79BA cae sobre el último cuadro del golfista; 0x5B1B, sobre un ld a,(hl); 0x5BDC, sobre un jr; 0x5470, sobre un ret que además es la base de una tabla de giro; 0x7538, sobre los dos últimos periodos de nota; y 0x4D3B, sobre la cola de un guión.

Los tres tercios de la pantalla, con una sola copia

SCREEN 2 del MSX son tres tercios independientes, y para que los tres tengan lo mismo hay que escribirlo tres veces. 0x4322 lo hace con un solo ldir solapado: copia 4.096 bytes desde 0x0000 a 0x0800. Como el destino va 0x800 por delante del origen, cuando la copia pasa del primer bloque está leyendo lo que ella misma acaba de escribir. Un ldir en vez de dos.

La altura de la bola no se guarda: es la distancia entre sus dos sprites

La bola son dos sprites superpuestos, uno negro y uno blanco. El negro se queda pegado al suelo y el blanco se levanta con la parábola, así que la separación entre los dos es la altura. No hay ninguna variable de altura en ningún sitio: hay dos coordenadas, y la altura es su resta.

Y de esa resta sale también el tamaño con que se dibuja. 0x7074 hace ld a,(0xE0B0) / sub d —la y de la capa de abajo menos la de la de arriba— y la compara con 0x21, 0x0F y 0x06: cuatro escalones de bola, de la más gorda a la más pequeña. Cuanto más alto va, más pequeña se ve. Al posarse, 0x701B vuelve a juntar las dos capas y la altura es cero otra vez.

Una sola curva para el seno y el coseno

La dirección del golpe no usa dos tablas: usa una curva de 66 bytes en 0x52BF, leída en dos puntos separados 0x21. Coseno y seno son la misma tabla desfasada un cuarto de vuelta, que es exactamente lo que son.

No lleva la marca oculta de Konami, y se ha comprobado en serio

Konami escondía al final de muchos cartuchos su número de catálogo y el título en katakana; lo descubrió Manuel Pazos (@ManuelPazosMSX) y el bloque vive en el offset 0x3FF0. Éste no la lleva, y no por no mirar: se rastrearon las 16.384 posiciones de la ROM con un buscador validado antes contra cartuchos de la misma familia que sí la llevan —los RC-718 y RC-729 de la serie sueltan la suya al primer intento—, que es la única manera de fiarse de un negativo. La razón se ve en el volcado: la ROM llega llena hasta 0x7FFD y sólo sobran dos bytes de relleno. No cabe.

Lo que el cartucho dibuja

Debajo de cada imagen está de dónde sale y qué se está viendo.

<b>Los nueve hoyos del campo</b>, cada uno con su panel: número, par, longitud en metros y la bandera puesta donde dice el cartucho. No son capturas: los pinta en Python el mismo intérprete de guiones del Z80, leyendo los punteros de 0x79BC. Que están bien no es una impresión — el plano se comparó celda a celda contra treinta volcados de openMSX, con <b>cero diferencias</b>
Los nueve hoyos del campo, cada uno con su panel: número, par, longitud en metros y la bandera puesta donde dice el cartucho. No son capturas: los pinta en Python el mismo intérprete de guiones del Z80, leyendo los punteros de 0x79BC. Que están bien no es una impresión — el plano se comparó celda a celda contra treinta volcados de openMSX, con cero diferencias
El hoyo 1 de cerca, par 4 y 475 metros. La columna de la izquierda es el panel entero tal como lo monta el cartucho; la casilla del viento va en blanco porque ese dato no está en la ROM, lo sortea el registro R
El hoyo 1 de cerca, par 4 y 475 metros. La columna de la izquierda es el panel entero tal como lo monta el cartucho; la casilla del viento va en blanco porque ese dato no está en la ROM, lo sortea el registro R
El hoyo 5, el único par 3 del campo: 168 metros, green casi pegado al tee y búnkeres por medio
El hoyo 5, el único par 3 del campo: 168 metros, green casi pegado al tee y búnkeres por medio
La pantalla del título, montada con los pasos del propio cartucho: el guion de 0x44E9 descomprime los 38 tiles del rótulo y 0x4354 los coloca en dos filas de 19 desde la VRAM 0x3887
La pantalla del título, montada con los pasos del propio cartucho: el guion de 0x44E9 descomprime los 38 tiles del rótulo y 0x4354 los coloca en dos filas de 19 desde la VRAM 0x3887
Los 54 códigos de casilla con los que se construye la vista en perspectiva, cada uno dibujado a las <b>cinco distancias</b> con que el cartucho los apila: el mismo código ocupa cuatro tiles de alto cerca y dos al fondo
Los 54 códigos de casilla con los que se construye la vista en perspectiva, cada uno dibujado a las cinco distancias con que el cartucho los apila: el mismo código ocupa cuatro tiles de alto cerca y dos al fondo
Los siete cuadros del swing, descomprimidos desde 0x78FF y montados sprite a sprite como hace 0x5862, con su orden de prioridad
Los siete cuadros del swing, descomprimidos desde 0x78FF y montados sprite a sprite como hace 0x5862, con su orden de prioridad
Los 256 tiles del campo con su color, tal como quedan en la VRAM después de que 0x482E cargue los dibujos
Los 256 tiles del campo con su color, tal como quedan en la VRAM después de que 0x482E cargue los dibujos
Los 32 patrones de sprite de 16×16 que hay cargados durante la partida: el golfista, la bola, su sombra y la bandera
Los 32 patrones de sprite de 16×16 que hay cargados durante la partida: el golfista, la bola, su sombra y la bandera
La fuente con la que se escribe todo. No es ASCII: E0 es la H, D3 la O, D9 la L y DC la E, y las cifras son 0xF0 más el dígito
La fuente con la que se escribe todo. No es ASCII: E0 es la H, D3 la O, D9 la L y DC la E, y las cifras son 0xF0 más el dígito