Konami's Tennis

Los tres tercios de la pantalla pintados con un solo bucle que se lee a si mismo, la tabla de colores debajo de la de patrones, y cada tenista montado con cinco sprites apilados.

Konami - (c) Konami 1984 - Cartucho RC-720, 16 KB - MSX1 - pagina 1 - Volcado 68bec817...

Aqui no hay ninguna captura. Todas las imagenes estan dibujadas desde los bytes de la ROM, ejecutando en Python los mismos interpretes que corre el Z80, y comprobadas contra la VRAM del emulador: cero diferencias en 137.260 bytes. El listado y las cifras se reproducen con make.

El cartucho en cifras

100 %del binario explicado
492rutinas con nombre
32,4 %del listado comentado
7.882bytes de codigo
8.502bytes de datos
0bytes sin identificar

Lo que aparecio al desmontarlo

Los tres tercios de la pantalla, con un solo bucle

SCREEN 2 son tres tercios independientes, y para que los tres tengan lo mismo hay que escribirlo tres veces. 0x442D copia de VRAM a VRAM byte a byte, y le mandan 4.095 bytes de 0x0000 a 0x0800: como el destino va 0x800 por delante, pasado el primer bloque esta leyendo lo que el mismo acaba de escribir. Un bucle, tres tercios iguales, 4 KB ahorrados. Se hace dos veces: colores y patrones.

La tabla de colores va debajo de la de patrones

En SCREEN 2 el TMS9918 no lee R3 y R4 como una direccion, sino como un bit de base y una mascara. Con R4 = 0x07 los patrones quedan en 0x2000 y con R3 = 0x7F los colores en 0x0000, al reves de lo habitual.

Leerlo del otro modo tiene un sintoma que engana: las formas se siguen reconociendo -los dos bloques son simetricos- pero los colores salen a franjas.

El juez de silla sigue la pelota con los ojos

No es un sprite: son 2x2 tiles de la tabla de nombres. 0x6ED2 mira donde esta la pelota, parte la pista en tres con 0x48 y 0x78, y elige una de las tres caras de 0x715D. Solo cambian los ojos.

Una figura no es un sprite: son cinco

Cada postura son cinco sprites de 16x16 apilados. La tabla de 0x5961 tiene 58 entradas que apuntan a 37 descripciones de doce bytes -cinco punteros a patron y uno a las cinco parejas (y,x)-, y entre todas gastan 189 patrones.

El color no esta ahi: sale de la ficha del jugador, y por eso las jugadoras 3 y 4 llevan el pelo magenta donde las 1 y 2 lo llevan negro.

El rival falla con el registro de refresco

0x6BE9 hace ld a,r. R es el contador de refresco de la DRAM, que el Z80 adelanta en cada instruccion, asi que no se puede predecir. Rotado dos veces, es el temblor de la punteria del rival -y 0x6BEE lo deja a cero en la mitad de los cuadros.

La dificultad sube con lo que dura el peloteo

0xE20A cuenta los golpes del punto. 0x6E3B lo divide por dos, lo topa en quince y lo busca en una de las tres curvas de dieciseis pasos de 0x6E67, una por opcion del GAME SELECT. Cuanto mas se alarga el punto, mejor juega la maquina; pasado el golpe treinta ya no sube.

Seis bytes de codigo en la tabla de sprites

0x4272 pide 22 bytes de atributos desde 0x7890, donde solo hay 16 de datos: lo que sigue en 0x78A0 ya es codigo. Asi que los seis primeros bytes de esa rutina acaban en la VRAM 0x3B3C, y ahi se quedan toda la partida. No se nota porque los patrones a los que apuntan estan vacios.

Una raqueta que no dibuja nadie

Nueve bytes en 0x61F5 se descomprimen a un sprite valido de 16x16. No la apunta nadie, y no es una impresion: la palabra 0x61F5 no aparece en toda la ROM en ninguno de los dos ordenes de byte, y todos los punteros a patron son palabras de 16 bits. Tampoco coincide con ninguno de los 189 patrones que si se dibujan.

Todo contador a cero vale 256

Los guiones estan llenos de longitudes a cero, y no son bloques vacios: el Z80 decrementa antes de comprobar, asi que un djnz con B a cero da 256 vueltas. Es como se escribe 256 en un byte. Leerlas como ceros descuadra el guion a los pocos bloques.

El marcador cambia de nombre segun quien juegue

Con un jugador pone PLY y MSX; con dos personas, 1UP y 2UP -los seis tiles de 0x7760 y los seis de 0x7766. El guion de la pista deja escrito CPU ahi, y el juego lo tapa despues.

El alfabeto tampoco es ASCII: la A es 0xD1 y de ahi seguido, sin la Q, y con la X fuera de orden en 0xE8, detras de la Y.

La proteccion anticopia no salta al arrancar: salta al ganar un juego

Lo llamativo no es que la lleve -Konami la ponia en muchos de sus cartuchos, y el RC-701 gasta la misma idea con un ldir- sino cuando salta. La comprobacion no esta en el arranque, donde se esperaria: esta en 0x7A31, dentro de la rutina que apunta un juego ganado. O sea que una copia arranca bien, ensena el titulo, deja elegir y deja jugar, y solo se rompe cuando alguien se lleva el primer juego. Para entonces quien la ha copiado ya la ha dado por buena.

El mecanismo es de una sola instruccion: escribe un cero en 0x409A, que es el ret con el que acaba el manejador de interrupcion, y en 0x409B empieza INIT. En ROM no hace nada, porque no se deja escribir; en RAM ese ret se vuelve un nop, la interrupcion sigue de largo y cae en INIT, con lo que el juego se reinicia en cada cuadro. Es la unica escritura de toda la ROM a su propia pagina, y aqui esta sin parchear.

No lleva la marca oculta de Konami

Konami escondia su numero de catalogo y el titulo en katakana al final de muchos cartuchos, en el offset 0x3FF0; lo descubrio Manuel Pazos (@ManuelPazosMSX). Este no la lleva, y no por no mirar: se rastrearon las 16.384 posiciones con un buscador validado antes contra cartuchos de la misma familia que si la llevan, que es la unica manera de fiarse de un negativo.

Lo que el cartucho dibuja

Debajo de cada imagen esta de donde sale y que se esta viendo.

<b>La pantalla del titulo</b>, montada con los pasos del propio cartucho: el guion de 0x4686 deja los patrones y los colores, la copia solapada de 0x442D replica los tres tercios y las cuatro listas de tiles de 0x45D1 escriben el rotulo, el copyright y las tres opciones. Comparada con la VRAM del emulador, <b>cero diferencias</b>
La pantalla del titulo, montada con los pasos del propio cartucho: el guion de 0x4686 deja los patrones y los colores, la copia solapada de 0x442D replica los tres tercios y las cuatro listas de tiles de 0x45D1 escriben el rotulo, el copyright y las tres opciones. Comparada con la VRAM del emulador, cero diferencias
<b>La pista</b>, con la tierra batida, la red, el publico, el juez de silla y el recogepelotas. La monta el guion de 0x49B5 y la remata la lista de tiles de 0x4FF1. El marcador esta vacio porque los tanteos no estan en el guion: los pinta el juego cuando hay partida
La pista, con la tierra batida, la red, el publico, el juez de silla y el recogepelotas. La monta el guion de 0x49B5 y la remata la lista de tiles de 0x4FF1. El marcador esta vacio porque los tanteos no estan en el guion: los pinta el juego cuando hay partida
Las <b>52 posturas</b> del tenista, cada una montada capa a capa como las monta 0x58A9: cinco sprites de 16x16 colocados con las parejas (y,x) de su descripcion. Correr, sacar, la derecha, el reves y la volea
Las 52 posturas del tenista, cada una montada capa a capa como las monta 0x58A9: cinco sprites de 16x16 colocados con las parejas (y,x) de su descripcion. Correr, sacar, la derecha, el reves y la volea
Las mismas figuras con los colores de la <b>tercera ficha</b>. Los dibujos son identicos; lo que cambia son los cinco colores de sprite que trae la ficha del jugador (0x57EB), y por eso esta lleva el pelo <b>magenta</b> y la ropa roja
Las mismas figuras con los colores de la tercera ficha. Los dibujos son identicos; lo que cambia son los cinco colores de sprite que trae la ficha del jugador (0x57EB), y por eso esta lleva el pelo magenta y la ropa roja
Las <b>tres caras del juez de silla</b>. No es un sprite: son 2x2 tiles de la tabla de nombres, y 0x6ED2 elige entre las tres segun en cual de las tres franjas de la pista este la pelota. Solo cambian los ojos
Las tres caras del juez de silla. No es un sprite: son 2x2 tiles de la tabla de nombres, y 0x6ED2 elige entre las tres segun en cual de las tres franjas de la pista este la pelota. Solo cambian los ojos
Los <b>cinco pasos del recogepelotas</b>, que si es de sprites: 0x78A0 descomprime sus capas en la VRAM 0x1960 y les suma su posicion. Sale cuando la pelota se queda rodando, va a por ella y vuelve a su sitio
Los cinco pasos del recogepelotas, que si es de sprites: 0x78A0 descomprime sus capas en la VRAM 0x1960 y les suma su posicion. Sale cuando la pelota se queda rodando, va a por ella y vuelve a su sitio
La pelota en sus <b>cinco tamanos</b>, con su sombra debajo. 0x5416 resta la altura de la pelota y la de su sombra y compara con <b>0x21, 0x0F y 0x06</b>: cuanto mas alta va, mas pequena se dibuja
La pelota en sus cinco tamanos, con su sombra debajo. 0x5416 resta la altura de la pelota y la de su sombra y compara con 0x21, 0x0F y 0x06: cuanto mas alta va, mas pequena se dibuja
La <b>raqueta que no dibuja nadie</b>: nueve bytes en 0x61F5 que se descomprimen a un sprite valido y al que no apunta ninguna de las descripciones de postura. La palabra 0x61F5 no aparece en toda la ROM
La raqueta que no dibuja nadie: nueve bytes en 0x61F5 que se descomprimen a un sprite valido y al que no apunta ninguna de las descripciones de postura. La palabra 0x61F5 no aparece en toda la ROM
Los <b>256 tiles</b> del primer tercio de la pista con su color, tal como quedan en la VRAM despues del guion y de la copia solapada
Los 256 tiles del primer tercio de la pista con su color, tal como quedan en la VRAM despues del guion y de la copia solapada
La fuente con la que se escribe todo. No es ASCII: la A es 0xD1 y de ahi seguido, <b>sin la Q</b>, y con la <b>X fuera de orden en 0xE8</b>; las cifras son 0xF0 mas el digito
La fuente con la que se escribe todo. No es ASCII: la A es 0xD1 y de ahi seguido, sin la Q, y con la X fuera de orden en 0xE8; las cifras son 0xF0 mas el digito