Super Cobra

Ocho kilobytes en los que el hilo principal no hace nada: arranca, engancha la interrupción y se queda en un jr $ para siempre. El juego entero cabe dentro del gancho de vídeo, repartido en quince estados y ocho trabajos que se turnan un fotograma cada uno.

Konami · ©KONAMI 1983 · Cartucho RC-705, 8 KB · MSX1 · página 1 · Volcado 062aeefd…

Aquí hay dos clases de imagen y no se mezclan. Los tiles, los dibujos de sprite y el logotipo de Konami están reconstruidos: los dibuja una herramienta que repite, instrucción a instrucción, los dos intérpretes de dibujo del cartucho sobre una memoria de vídeo vacía. Las pantallas son capturas de openMSX, y lo dicen en el pie; el rótulo de aquí arriba está recortado de una de ellas. El listado y las cifras salen del binario y se reproducen con make.

El cartucho en cifras

100 %del binario explicado
15estados del juego
8trabajos que se turnan
5.783bytes de código
2.409bytes de datos
0bytes sin identificar

Lo que apareció al desmontarlo

Con Frogger, de 1983 y de 8 KB como este, no comparte ni un byte seguido

tools/comun_konami.py indexa todos los trozos de doce bytes de un cartucho y los busca en el otro, estirando cada coincidencia hasta donde llega. Con el umbral de la herramienta —24 bytes seguidos— Super Cobra da 400 bytes en común con Athletic Land, 287 con Monkey Academy, 239 con Antarctic Adventure… y cero con Frogger.

Los 28 bytes que salen contra Time Pilot tampoco son código: son el logotipo KONAMI pequeño de 0x43BE, un dibujo. Konami tenía dos armazones distintos a la vez, y estos dos cartuchos de 1983 son uno de cada.

El reproductor de sonido no está copiado de Athletic Land: está revisado

Es lo más grande que comparten los dos, y no hay un desplazamiento único que los alinee. Bajando el umbral a ocho bytes, de los 320 de 0x5D30–0x5E70 hay 177 —el 55,3 %— dentro de una tira idéntica, repartidos en seis tiras cuyos desplazamientos van de 0x1B0B a 0x1B28.

Un desplazamiento que se mueve 29 bytes a lo largo del mismo bloque es la firma de un código al que le han metido y quitado trozos por el medio, no de un copia y pega.

Las letras del juego no están en el cartucho

SUBE_FUENTE (0x4AA0) hace ld hl,(00004h). Esa dirección es CGTBL, el puntero a la fuente que la ROM del BASIC guarda ahí, y de ella se suben 0x180 bytes: 48 caracteres, del 0 al _.

Ni las cifras del marcador ni las palabras del menú son dibujos de Konami. Y se suben dos veces, con dos desplazamientos y dos colores distintos, porque en SCREEN 2 el color va por línea de patrón y el mismo carácter no puede tener dos colores.

La misma rutina pinta y borra, según por dónde entres

PINTA_DIBUJO está en 0x4068 y BORRA_DIBUJO dos bytes antes, en 0x4064. La única diferencia es lo que cargan en C: 0xFF una y 0x00 la otra. Abajo, en el bucle, hay un and c (0x4076) que con 0xFF deja el byte tal cual y con 0x00 lo convierte en cero.

El juego lo usa así de verdad: el cartel INVASION SUCCEEDED se pinta entrando por 0x4068 y se quita entrando por 0x4064. Y con los submodos pasa lo mismo: el 2 entra en 0x5275 y el 4 en 0x5278, tres instrucciones más adentro, saltándose el call que mueve la llama del motor.

Cuatro tablas que empiezan dentro de una instrucción

No es un error de lectura, y no es una: son cuatro. La tabla de los desplazamientos de la explosión (0x566B) arranca sobre el operando del jp de 0x566A; la de cuántos salen por zona (0x58D6), sobre el del jp de 0x58D5; la de los márgenes de la bomba (0x55D3), sobre un call y un scf/ret.

En las tres, las entradas que caen encima del código no se pueden usar: el índice nunca llega a valer lo que haría falta para leerlas.

La cuarta es más fea. SONIDO_PISTAS (0x5CD8) usa como base 0x5E5F, dos bytes antes de la primera palabra de verdad: la entrada 0 se monta sobre los dos últimos periodos de nota y apunta a 0x383C, fuera del cartucho. El sonido número 0 no se puede pedir, y nadie lo pide.

Un despachador que no vuelve, y dos rutinas que nadie llama

DESPACHA (0x4050) no lleva la tabla aparte: hace pop hl para quedarse con la dirección de retorno y usarla de base, así que la tabla va pegada detrás del call y no se vuelve nunca a él. Termina en jp (hl).

Eso tiene una consecuencia: el ret de la rutina despachada no vuelve al despachador, vuelve a lo que hubiera dejado el llamador en la pila. 0x4691 se aprovecha haciendo un push hl antes de despachar, y por eso 0x488B y 0x49EA se ejecutan sin que ninguna instrucción las llame.

Siete bytes que se ejecutan en la RAM porque el Z80 no sabe hacerlo

0x412B copia siete bytes de 0x41DD a 0xE5F8 y desde entonces se los llama como rutina:

ld (0E5FDh),a  ·  ld (ix+000h),b  ·  ret

0xE5FD es el tercer byte del ld (ix+000h),b, o sea su propio desplazamiento: la rutina se lo escribe encima con A y entonces guarda B. Es ld (IX+A),B, que no existe, porque el desplazamiento de IX es un byte fijo del opcode y no un registro. Son los únicos siete bytes del cartucho que no corren desde la ROM.

Este cartucho no lleva la marca oculta de Konami

Manuel Pazos descubrió que los cartuchos de Konami esconden al final de la ROM su número de catálogo RC-7xx y el título en katakana. Aquí no está.

El último byte con contenido es 0x5FF3 —el final de la última pista de sonido— y de 0x5FF4 a 0x5FFF hay doce bytes de 0xFF y nada más. El «RC-705» de esta web sale del catálogo, no del binario.

El contador de refresco de la memoria, usado de dado

PUNTOS_DE_PREMIO (0x501E) necesita un número al azar y no tiene generador. Usa el registro R del Z80, el contador de refresco de la memoria dinámica, que sube solo con cada instrucción que se ejecuta: sus dos bits bajos dan 0, 1, 2 o 3, y eso va al byte alto del premio. Salen 0, 100, 200 o 300 puntos.

Lo que el cartucho dibuja

Debajo de cada pie está la dirección de donde sale, y si la imagen es reconstruida o capturada.

CAPTURA de openMSX — la pantalla del título y el menú, montada por el estado 04 y el 06. Las teclas 1 y 2 juegan con joystick, la 3 y la 4 con el teclado; lo que eligen son dos bits de 0xE002
CAPTURA de openMSX — la pantalla del título y el menú, montada por el estado 04 y el 06. Las teclas 1 y 2 juegan con joystick, la 3 y la 4 con el teclado; lo que eligen son dos bits de 0xE002
CAPTURA de openMSX — una zona en marcha: el decorado que corre a doble búfer desde 0xE800, el marcador de arriba y la barra de combustible de 0x4F7C
CAPTURA de openMSX — una zona en marcha: el decorado que corre a doble búfer desde 0xE800, el marcador de arriba y la barra de combustible de 0x4F7C
CAPTURA de openMSX — el estado 01, cazado a medias: SUBE_LOGOTIPO (0x4CBF) sube el KONAMI de abajo arriba, una fila de 32 bytes cada dos fotogramas
CAPTURA de openMSX — el estado 01, cazado a medias: SUBE_LOGOTIPO (0x4CBF) sube el KONAMI de abajo arriba, una fila de 32 bytes cada dos fotogramas
RECONSTRUIDA de 0x4248 — los 256 tiles del tercio de arriba con su color, tal como los deja MONTA_EL_TITULO. Los grises son los que el cartucho no trae: ahí caen las letras que se copian de la BIOS
RECONSTRUIDA de 0x4248 — los 256 tiles del tercio de arriba con su color, tal como los deja MONTA_EL_TITULO. Los grises son los que el cartucho no trae: ahí caen las letras que se copian de la BIOS
RECONSTRUIDA de 0x443A — los dibujos de sprite de 16×16. Ese flujo es lo único de todo el cartucho que escribe en la VRAM 0x1800, que es donde el registro 6 del VDP pone la tabla de patrones de sprite
RECONSTRUIDA de 0x443A — los dibujos de sprite de 16×16. Ese flujo es lo único de todo el cartucho que escribe en la VRAM 0x1800, que es donde el registro 6 del VDP pone la tabla de patrones de sprite
VOLADA — la zona 1 entera, sus 485 columnas, con los cohetes y los depósitos donde el cartucho los pone. No está leída de la ROM, porque no está guardada en la ROM: <code>tools/mapa.py</code> ejecuta el cartucho en un intérprete de Z80 escrito en Python, juega la partida y va guardando la columna que entra por la derecha en cada paso de scroll
VOLADA — la zona 1 entera, sus 485 columnas, con los cohetes y los depósitos donde el cartucho los pone. No está leída de la ROM, porque no está guardada en la ROM: tools/mapa.py ejecuta el cartucho en un intérprete de Z80 escrito en Python, juega la partida y va guardando la columna que entra por la derecha en cada paso de scroll
RECONSTRUIDA de 0x4CFA — los 26 tiles del KONAMI grande, 147 bytes idénticos a los de Athletic Land, montados como los monta el cartucho: tres tiles arriba, once en medio y doce abajo
RECONSTRUIDA de 0x4CFA — los 26 tiles del KONAMI grande, 147 bytes idénticos a los de Athletic Land, montados como los monta el cartucho: tres tiles arriba, once en medio y doce abajo