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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Debajo de cada pie está la dirección de donde sale, y si la imagen es reconstruida o capturada.
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