Hallazgos

Los dieciocho hoyos son un solo mapa

Las dieciocho pantallas no son dieciocho decorados sueltos. Son ventanas de un mismo campo de 20 × 415 casillas, apilado con el hoyo 1 en el extremo sur y el 18 en el norte, y dos hoyos seguidos comparten una fila: la de arriba del hoyo n es la de abajo del n+1.

Lo vio theNestruo, en el issue #1. Aquí está medido, y la medida es lo que vigila tests/test_campo_continuo.py:

filas comparadascasillas iguales, de 20
la fila compartida (arriba de n / abajo de n+1)70,9 %
dos filas pegadas dentro de un mismo hoyo — la línea base41,6 %
dos filas del mismo hoyo que no se tocan21,0 %
apilado al revés — lo que se publicó aquí primero35,9 %

La línea base que importa es la del medio. Una fila compartida tiene que parecerse más que dos filas que simplemente están una al lado de la otra, y así es en las diecisiete junturas tomadas una a una. Apilarlo al revés no es que dé menos: da por debajo de dos filas cualesquiera del mismo hoyo.

El solape es de una fila exacta. Probando solapes de una a seis filas, la de una gana en las diecisiete parejas.

En el guión de un hoyo no hay ni una coordenada: la continuidad está dibujada, no calculada. El sentido lo da el propio juego, porque los dieciocho tees caen en las filas de arriba y las dieciocho banderas en las de abajo, así que cada hoyo se juega de norte a sur y el campo se recorre de sur a norte.

Cómo se falló esto la primera vez. La primera respuesta a ese issue daba 7,2 casillas iguales de 20 y decía que la premisa no se sostenía. El número era correcto y la lectura estaba del revés: comparaba la fila de abajo del hoyo n contra la de arriba del n+1, que es la pila boca abajo. El issue decía "de abajo arriba" con todas las letras.

CALL GOLF carga un campo que no está en la ROM

La cabecera AB de 0x8000 declara INIT en 0x8028 y STATEMENT en 0x8010, y theNestruo explicó en el issue #2 para qué sirve el segundo: arrancar con una tecla pulsada para que el juego no empiece, BLOAD"CAS:" un campo distinto en RAM, y CALL GOLF para jugar ése en vez del del cartucho. Tiene razón, y el listado dice exactamente por qué.

init (0x8028) hace tres cosas en este orden: lee la fila 7 del teclado por SNSMAT y hace ret z si el bit 2 está pulsado; escribe 0x9C33 en (0xE000) —la tabla de punteros de los dieciocho hoyos de la ROM— y 0x99DD en (0xE002); y sólo entonces monta la máquina, desde 0x8041.

statement (0x8010) compara la sentencia BASIC no reconocida contra los cuatro bytes "GOLF" de 0x8024. Si coinciden hace jr $+33, que cae en 0x8041: detrás del chequeo de tecla y detrás de las dos escrituras de punteros. Y hoyo_normal (0x9871) lee la tabla de hoyos de (0xE000), nunca de 0x9C33 directamente. Así que el campo que se juega es el que esté apuntado en (0xE000) cuando corre CALL GOLF.

Y el montaje de init no lo toca: borra de 0xE005 a 0xE01E y pone la pila en 0xF300, así que 0xE000–0xE004 sobreviven.

Probado escribiendo un campo y jugándolo

tools/campo.py escribe dieciocho hoyos en el formato del propio cartucho: una calle de arena recta, un lago que cambia de lado y una barra de agua en la fila 1 de exactamente tantas casillas como el número de hoyo, para que no se pueda confundir con el campo de la ROM. tools/omsx_call_golf.tcl hace luego la secuencia entera en openMSX: arrancar con la fila 7 bit 2 pulsada, dejar los 1.229 bytes en 0xC000 —que es lo que haría el BLOAD—, apuntar ahí (0xE000) y teclear CALL GOLF.

(0xE000) tras arrancar con la tecla pulsada0xFFFF — el cartucho no llegó a correr
(0xE000) tras CALL GOLF0xC000 — el puntero sobrevive
la pantalla contra los hoyos generados480 / 480 celdas, hoyos 1, 2, 3 y 4
esa misma pantalla contra el campo de la ROM261 / 480 como mucho (eso es el césped)

Y el marcador también los lee: la exhibición enseña HOLE 2, PAR 4, 302 m, que son el par y la longitud escritos en el hoyo 2 generado, y no los 168 m par 3 de la ROM.

El formato

tabla       dieciocho punteros de dos bytes, en orden de juego
cada hoyo   tres bytes de cabecera, el guión, un 0x21 y tres dígitos ASCII

Los tres bytes de cabecera son los materiales del hoyo. En el guión, un byte 0x3n, 0x4n o 0x5n repite n+1 veces el primero, el segundo o el tercero; cualquier otro byte es una celda literal —y por eso una celda literal no puede valer entre 0x30 y 0x5F—. Tres literales marcan sitio: 0xE9 es la bandera, y 0xD9, 0xDD y 0xE3 son el tee, que además dicen el par. Son 480 celdas, veinte por fila.

El campo generado se relee con el mismo intérprete que lee el de la ROM, y los dieciocho vuelven con sus 480 celdas intactas: ésa es la comprobación de que el formato está entendido y no sólo descrito.

La cinta: tres campos más, y las instrucciones del propio HAL

Hole In One Extension Course (HAL Laboratory, 1985) es una cinta de dos caras con tres campos de dieciocho hoyos más para este cartucho. Es lo que pedía la segunda mitad del issue #2, y convierte el mecanismo de CALL GOLF de una deducción en algo escrito por quien lo hizo.

Cada cara lleva siete ficheros:

ficherotipocarga en
CONSTbinario0x8000–0xAFFF, arranca en 0x8000
SOUTH / WEST / NORTHBASIC en ASCIItres líneas cada uno
SDATA / WDATA / NDATAbinario0xC050–0xD6FF, arranca en 0xC050

Y los programas BASIC son el procedimiento entero, con las palabras de HAL:

10 'SOUTH
20 BLOAD"CAS:SDATA",R
30 CALL GOLF

El ,R ejecuta el código con el que empieza cada fichero de campo, en 0xC050, y ese código hace exactamente lo que hace init en la ROM, sólo que apuntando a RAM:

push af / push hl
ld hl,0c066h / ld (0e000h),hl     la tabla de los dieciocho hoyos
ld hl,0c08ah / ld (0e002h),hl     la de los greens
ld a,001h    / ld (0e004h),a
pop hl / pop af / ret

Y luego CALL GOLF entra en 0x8041, detrás de las dos escrituras que habrían devuelto 0xE000 al campo de la ROM. Ése es el mecanismo, y la cinta es su manual.

Los tres campos

Se leen con el mismo intérprete que lee el del cartucho, y los pintan los mismos tiles, porque es el mismo formato byte a byte:

campoparlongitud
SOUTH726.147 m
WEST736.540 m
NORTH726.428 m

WEST es un par 73, cosa que el campo de la ROM no es nunca.

Y los tres son también una tira continua

El apilado que encontró theNestruo en el campo del cartucho no es una casualidad: es como este estudio construyó los cuatro. Medido igual, y con el mismo control:

campofila compartidafilas pegadas dentro de un hoyojunturas sobre la base
cartucho70,9 %41,6 %17 de 17
SOUTH72,6 %38,9 %17 de 17
WEST70,0 %37,8 %17 de 17
NORTH73,5 %38,6 %17 de 17

Cuatro campos, cuatro mapas continuos, y en los cuatro el hoyo 1 al sur y el 18 al norte.

Los tres campos apilados en la tira que forman, con el hoyo 1 abajo: SOUTH · WEST · NORTH

Las dos caras, y cómo se carga cada una

Los seis ficheros de campo son idénticos entre la cara A y la cara B, byte a byte. Sólo cambia CONST, y sólo en dos bytes de relleno detrás de su último ret (0xAFD0–0xAFD1: 0xFF en la cara A, 0x00 en la B). Lo que cambia es el orden: la cara A pone CONST delante, para BLOAD"CAS:",R; la B pone delante los programas BASIC, para RUN"CAS:".

Y ese orden es la diferencia de uso, porque la cara B necesita BASIC y la A no:

Lo de ESC no es una costumbre del MSX: lo hace el propio cartucho, y son las tres primeras instrucciones de init.

ld a,007h        ; 8028   fila 7 de la matriz del teclado
call 00141h      ; 802a   BIOS SNSMAT
and 004h         ; 802d   el bit 2 de esa fila es ESC
ret z            ; 802f   pulsada: devuelve el control sin montar nada

Con ESC pulsada el cartucho no monta la pantalla ni engancha la interrupción: devuelve el control a la BIOS y la máquina termina de arrancar en BASIC, con CALL GOLF ya registrado. Que es justo lo que piden los tres programas de la cinta.

CONST es el editor de campos

CONST no es un campo, y tampoco es -como decía antes esta página- el motor del juego para una máquina sin cartucho: esa lectura se cae sola en cuanto se sabe que las dos caras se cargan con el cartucho puesto. Lo que es se lee en los textos que lleva dentro:

SETCHR   SET=UP   MOVE   SWAP   CLEAR   SCROLL: OFF/ON
SAVE1    SAVE18   LOAD   FILES  DEVICE  DEV:
NAME:    SAVING   LOADING   SURE>>   OK =Y=
GREEN OR TEE NOT FOUND>
Directory of Drive     Too Many Disks !!!     Verify Error !?

Un editor: se colocan tees y greens (y protesta si falta alguno), se mueve y se limpia, se pone nombre y se graba -un hoyo o los dieciocho- en cinta o en disco. Lo que produce es un fichero de campo del formato de SDATA/WDATA/NDATA, y por eso los tres campos de la cinta se leen con el intérprete del cartucho.

Comparte 2.803 bytes con la ROM del 84 en once tiras, la mayor de 2.123 bytes (la tabla de patrones de 0xB324, reubicada). Y comparte otros 3.050 bytes en 24 tiras con Hole in One Professional (HAL, 1986), incluida la tabla de palos y la hoja de sprites: el cartucho del 86 trae de fábrica un modo GAME >>CONSTRUCTION y un campo COURSE >>USER, o sea el editor de esta cinta metido dentro.

La cabecera del hoyo es su paleta

Cada mapa empieza con tres bytes que el cartucho copia a 0xE451. En el guión, un byte 0x3n, 0x4n o 0x5n repite n+1 veces uno de esos tres.

Lo que engancha las dos cosas es una cuenta de tres: el índice sale del nibble alto del opcode, y la tabla de la que se lee empieza en 0xE44E, tres bytes antes de la cabecera. Así que el 3, el 4 y el 5 caen justo encima de ella. No hay tabla de paleta por ningún lado; hay un desplazamiento que hace que la cabecera del hoyo sea la paleta.

El par y la longitud viven dentro del mapa

Tampoco hay una ficha de hoyos. El par lo dice el tile que dibuja el tee: 0xD9 es un par 3, 0xDD un par 4 y 0xE3 un par 5, y el intérprete aprovecha para apuntar dónde cae y colocar ahí la bola. La longitud son tres dígitos ASCII pegados detrás del 0x21 que cierra el mapa, y el marcador los escribe tal cual con su «m» al lado.

Sumando los dieciocho sale par 72 y 6.430 metros.

Una tabla de patrones para los tres tercios

El SCREEN 2 del MSX son tres tercios independientes: para que los tres tengan lo mismo hay que escribirlo tres veces. 0x9505 hace las seis llamadas -tres de patrones y tres de color-, pero 0x9834 vuelve a poner DE=0xB324 en cada una, así que las tres descomprimen la misma fuente. La tabla de patrones entera del juego son 1.613 bytes comprimidos.

El rótulo se carga entrando a mitad de una instrucción

0x9505 es un or 0AFh, o sea los dos bytes F6 AF. Llamando ahí, A queda distinto de cero, el flag Z se va a cero y las seis llamadas que vienen detrás cargan las tablas largas: el campo.

Pero 0x8829 no llama a 0x9505, llama a 0x9506, que es el segundo byte de esa misma instrucción. Y 0xAF, por su cuenta, es xor a. Así que entrar por ahí ejecuta el operando como instrucción, pone A a cero y levanta el flag Z, y entonces las seis llamadas cargan en su lugar dos tablas cortas.

Una instrucción de dos bytes que son dos instrucciones distintas según por dónde entres, y cada entrada elige un juego de tablas. Las cortas escriben 112 bytes -catorce tiles, del 0x10 al 0x1D- encima de lo que ya había: son las letras de HOLE IN ONE.

Las dos tablas del rótulo se pasan ocho bytes

Se quedan cortas: dan 104 de los 112 bytes que hay que escribir. Como el descompresor para por el puntero de VRAM y no por la fuente, sigue leyendo lo que venga detrás. Los ocho últimos bytes del tile 0x1D salen de la cabecera de la tabla de color, y los de la tabla de color, del principio del código de 0xBE0D.

Los dieciséis bytes están así en la VRAM del emulador. Y no se nota nunca, porque el tile 0x1D no lo nombra nadie: las dos mitades del rótulo llegan al 0x1C.

Los greens usan justo los tiles que el rótulo pisa

Los tres greens del modo de putt están dibujados con los tiles 0x10 a 0x1F, que son los catorce que el rótulo sobrescribe más dos. Los dieciocho hoyos, en cambio, no nombran ni uno de ese rango.

Por eso el cartucho puede dejar el rótulo puesto toda la partida sin recargar nada -comprobado: las tablas de patrones y color salen idénticas a las del título en seis volcados con el juego en marcha- y sólo tiene que recuperar las tablas largas cuando toca patear.

Diez columnas para el marcador, veinte para el campo

0x9571 escribe diez celdas por fila y salta veintidós, veinticuatro veces: el panel ocupa las columnas 1 a 10. 0x9A66 vuelca las 480 celdas del hoyo en veinte columnas por veinticuatro filas desde 0x180B, que es la columna 11. Ninguna de las dos mitades se dibuja centrada, así que nunca se pisan.