King's Valley

Un juego que no guarda por donde va la carretera -la LEE de la pantalla-, una rutina escondida dentro de su propia tabla de punteros, y dos compilaciones que se diferencian en UN solo byte.

Konami - (c) Konami 1985 - Cartucho RC-730, 16 KB - MSX1 - pagina 1 - Volcado 6d36c9e9...

Aqui no hay ninguna captura. Todas las imagenes estan dibujadas desde los bytes de la ROM, ejecutando en Python los dos interpretes de guiones que corre el Z80. El listado y las cifras se reproducen con make, y el reensamblado devuelve la ROM byte a byte.

El cartucho en cifras

100 %del binario explicado
482rutinas con nombre
55,1 %del listado comentado
7.797bytes de codigo
8.587bytes de datos
0bytes sin identificar

Lo que aparecio al desmontarlo

El mapa de colisiones es la propia pantalla

Este cartucho no guarda en ninguna parte por donde va la carretera. Para saber si el coche ha tocado el borde lee la pantalla: la rutina de 0x6D8B calcula la casilla en la que esta el coche, se la pide al VDP con SETRD y se trae con un in a,(c) el tile que hay dibujado ahi.

Despues lo clasifica por tandas: por debajo de 0xCF hay golpe seguro, de 0xCF a 0xD8 esta libre, y de 0xD9 a 0xE8 es el borde y hay que afinar hasta el pixel. Es la manera mas barata de que el coche choque con lo que se ve, sea lo que sea lo que la carretera haya pintado ahi.

La carretera no existe: se fabrica, fila a fila

No hay mapas de circuito. Hay un anillo de RAM de veinticuatro filas por veintidos columnas en 0xE186, y cada vez que la carretera avanza se retrocede el puntero una fila y se mete una fila nueva en el hueco que queda. No se mueve un solo byte de paisaje: lo que se mueve es por donde se empieza a leer.

Y la fila nueva la arma un motor con una rama por etapa: la 2 pega cuatro columnas de una lista ciclica, la 3 saca la fila entera de una palabra de dieciseis bits, la 4 guarda siete columnas y calcula el espejo sumando 0x0D a cada tile, la 5 hace lo mismo con cuatro, y la 6 es como la 3 pero ademas rehace las lineas encima.

Las seis carreteras de esta pagina estan dibujadas ejecutando ese motor en Python, rutina por rutina. La comprobacion no es que se vean bien: es que en 264 pasos cotejados contra openMSX -44 por etapa- el anillo entero de 528 bytes y todas las variables del generador salieron identicos a los de la maquina.

Una rutina escondida dentro de su propia tabla de punteros

0x5540 hace call 05716h, y 0x5716 cae dentro de la tabla de punteros de paisaje de 0x570C: son sus dos ultimos bytes. Konami los usa para dos cosas a la vez. Leidos como palabra son la sexta entrada de la tabla; ejecutados son el ld hl,(0e046h) con el que arranca la rutina que corre el anillo.

Que la sexta entrada apunte a 0x462A -un jr de dentro del descompresor RLE, que no es ningun dibujo de paisaje- es lo que delata el truco: la tabla tiene cinco entradas, y lo que sigue ya es codigo. Estos treinta y seis bytes estuvieron todo el desensamblado clasificados como datos que no lee nadie.

Las dos compilaciones se diferencian en UN byte

Del cartucho circulan dos volcados. Difieren en un solo byte, el 0x53CB: uno tiene 0x05 y el otro 0xFF.

Ese byte es el decimoquinto tramo de la fila de la etapa 5 en el plan de 0x537D, que son seis filas de dieciseis bytes cerradas con 0xFF. Medido en el emulador colocando el puntero al final de esa fila: la version con 0x05 juega quince tramos por ciclo y la del 0xFF, catorce. El que desaparece es el tramo 5.

Cual de las dos se juega mas dificil no se dice aqui, porque no se ha medido. Los nombres "Easy" y "Hard" con los que circulan son del volcado, no de la ROM.

El coche tiene una franja muerta de velocidad

Acelerando, el coche avanza por la pantalla 0x48 de 256 de pixel por fotograma. Pero no siempre: la rutina de 0x6C93 solo lo deja moverse con la velocidad entre 0x18 y 0x50, o por encima de 0x7E. Entre 0x50 y 0x7E se queda clavado donde este.

Esta medido, no deducido: en 900 fotogramas de la demostracion la Y del coche se queda quieta en 0x8FC0 mientras la velocidad sube de 0x51 a 0x7D, y vuelve a moverse en cuanto pasa de 0x7E. Cumplen la prediccion 57 de los 58 fotogramas comparables, y el que no cae justo en la frontera entre dos muestras.

CHECK POINT, y GOAL solo en la ultima

El final de etapa tiene tres hitos separados por nueve, que son nueve filas de anillo: a 0x0F00 de recorrido se suelta el coche rival, a 0x0F09 se pinta el rotulo de meta y a 0x0F12 se cruza.

Y el rotulo no es el mismo siempre: en las cinco primeras etapas son los once tiles de CHECK POINT, y en la sexta los cinco de GOAL, tres columnas mas a la derecha. Se leen con la misma regla que el resto de textos del cartucho -el indice de patron es el codigo ASCII menos 0x20- y se comprobaron dibujandolos desde la VRAM del emulador.

La calzada simetrica sale gratis

La etapa 3 dibuja la fila entera desde una sola palabra de dieciseis bits: cada bit elige uno de dos tiles. Se piden doce columnas y despues diez mas, pero la segunda llamada vuelve a cargar la misma palabra desde el principio, porque el puntero no se ha movido.

El resultado es que las columnas 12 a 21 repiten el dibujo de las diez primeras: la calzada sale simetrica sin gastar un byte de mas ni una instruccion de mas. No es un descuido, es el ahorro.

Los colores van debajo de los patrones, al reves de lo normal

En SCREEN 2 lo habitual es poner los patrones en 0x0000 y los colores en 0x2000. Aqui es al reves, y lo dicen los ocho bytes que el cartucho carga en los registros del VDP -la tabla de 0x46A9, que vale 02 E2 0E 7F 07 76 03 E4-: R3=0x7F pone los colores en 0x0000 y R4=0x07 los patrones en 0x2000.

R3 y R4 no son direcciones, son base y mascara, y leerlos como si lo fueran da un resultado que parece bueno: las formas salen bien y los colores a franjas. Lo confirma el propio cartucho, que en 0x477F llena de 0xF0 la zona de 0x0080, y 0xF0 solo tiene sentido como color.

El nivel no cambia solo la dificultad: cambia el cartucho

LEVEL A y LEVEL B no son un multiplicador. El nivel, que vive en (0xE03B), se mete por medio en cuatro sitios distintos: dobla o no el empuje lateral con el que salen los objetos (0x706D), cambia el paso del gasto de gasolina -0x0180 contra 0x01FF, en 0x7374-, cambia la cuenta de espera del reparto de objetos entre siete y doce (0x6F72), y suprime un tramo entero: en el primer nivel el tramo 0x0A se cambia por el 9 (0x7044).

La marca oculta de Konami

Los ultimos quince bytes del cartucho no los lee nadie: son RC-730 y el titulo en katakana, ロードファイター, escritos del reves y rematados con la longitud, las dos cifras del RC en BCD y un 0xAA.

El formato de esa firma lo descubrio Manuel Pazos, y sin su hallazgo estos quince bytes se habrian quedado en "datos que no lee nadie". Las gracias, desde aqui.

Lo que el cartucho dibuja

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

<b>La pantalla de titulo</b>, montada ejecutando los pasos del propio cartucho. El rotulo grande entra deslizandose desde los dos lados, y por eso la palabra ROAD esta guardada <b>al reves</b> en la ROM, con su 0xFF por delante
La pantalla de titulo, montada ejecutando los pasos del propio cartucho. El rotulo grande entra deslizandose desde los dos lados, y por eso la palabra ROAD esta guardada al reves en la ROM, con su 0xFF por delante
La <b>salida</b>, con el arco de meta y el rotulo START. Esta pantalla no sale de ninguna lista: la monta a mano la rutina de 0x77C8, pegando ocho retales uno detras de otro y heredando cada llamada el destino que dejo la anterior
La salida, con el arco de meta y el rotulo START. Esta pantalla no sale de ninguna lista: la monta a mano la rutina de 0x77C8, pegando ocho retales uno detras de otro y heredando cada llamada el destino que dejo la anterior
<b>Etapa 1</b>, ciento veinte filas seguidas. No es una captura ni un mapa: es el motor de carretera del cartucho ejecutado en Python. Se ven las casas con su seto, la piscina, los coches aparcados, las pistas de tenis y un cartel de <b>Konami</b> al principio
Etapa 1, ciento veinte filas seguidas. No es una captura ni un mapa: es el motor de carretera del cartucho ejecutado en Python. Se ven las casas con su seto, la piscina, los coches aparcados, las pistas de tenis y un cartel de Konami al principio
<b>Etapa 2</b>: la playa. La calzada se estrecha hacia el final del tramo, y las cuatro columnas de la izquierda salen de una lista ciclica propia de esta etapa, la de 0x7DC5
Etapa 2: la playa. La calzada se estrecha hacia el final del tramo, y las cuatro columnas de la izquierda salen de una lista ciclica propia de esta etapa, la de 0x7DC5
<b>Etapa 3</b>: la unica que dibuja la fila entera desde una palabra de bits, y la unica que tiene tiles de calzada propios -0x9B y 0x04 en vez de 0x80 y 0x0F-, que es lo que le da ese borde distinto
Etapa 3: la unica que dibuja la fila entera desde una palabra de bits, y la unica que tiene tiles de calzada propios -0x9B y 0x04 en vez de 0x80 y 0x0F-, que es lo que le da ese borde distinto
<b>Etapa 4</b>: la curva en S. Aqui solo estan guardadas las siete columnas de un lado; las del otro se calculan sumando 0x0D a cada tile, que es el salto de un dibujo a su version espejada
Etapa 4: la curva en S. Aqui solo estan guardadas las siete columnas de un lado; las del otro se calculan sumando 0x0D a cada tile, que es el salto de un dibujo a su version espejada
<b>Etapa 5</b>, la que separa las dos compilaciones. El byte 0x53CB, el unico que las diferencia, es el decimoquinto tramo de esta fila del plan
Etapa 5, la que separa las dos compilaciones. El byte 0x53CB, el unico que las diferencia, es el decimoquinto tramo de esta fila del plan
<b>Etapa 6</b>: la ultima, la que remata con GOAL en vez de CHECK POINT. Trae su propio juego de guiones -no lo comparte con ninguna- y otro cartel de <b>KONAMI</b>, este en mayusculas
Etapa 6: la ultima, la que remata con GOAL en vez de CHECK POINT. Trae su propio juego de guiones -no lo comparte con ninguna- y otro cartel de KONAMI, este en mayusculas
Los <b>tiles de la etapa 1</b> con su color, tal como quedan en la VRAM. Arriba la fuente completa, ordenada como el ASCII a partir del espacio; por eso los textos del cartucho se leen restando 0x20 al indice de patron. Se ven tambien SPEED y FUEL, y el cartel de Konami
Los tiles de la etapa 1 con su color, tal como quedan en la VRAM. Arriba la fuente completa, ordenada como el ASCII a partir del espacio; por eso los textos del cartucho se leen restando 0x20 al indice de patron. Se ven tambien SPEED y FUEL, y el cartel de Konami
Los <b>patrones de sprite</b>, en blanco porque en el MSX1 el color de un sprite va en su atributo y no en el patron. Estan los coches en sus posturas, las explosiones, las banderas y los rotulos de puntos: <b>300, 500, 800 y 1000</b>
Los patrones de sprite, en blanco porque en el MSX1 el color de un sprite va en su atributo y no en el patron. Estan los coches en sus posturas, las explosiones, las banderas y los rotulos de puntos: 300, 500, 800 y 1000