Stardust (1987)

Una cinta de cassette de 1987, desmontada bloque a bloque. Por dentro resultó ser una conversión del ZX Spectrum que se trajo hasta el sistema de grabación.

Topo Soft · 1987 · Conversión del ZX Spectrum · Carga de cinta multicarga · MSX1 · 64K

Esto no está terminado, y se sigue trabajando en ello. Que el presupuesto cierre al 100 % quiere decir que cada byte de la cinta tiene dueño —o es código que el trazador alcanza de verdad, o cae en un rango con nombre y medida—, no que se sepa para qué sirve cada uno. Cada byte tiene ya nombre, pero queda código sin trazar y buena parte de las rutinas sin comentar. Está contado con cifras en Lo que falta.

El juego en cifras

100%del binario con dueño
153rutinas identificadas
7+1zonas de naves, y una a pie
23.344bytes de código
70.517bytes de datos
0bytes sin identificar

Lo que apareció al desmontarlo

La cinta no es una cinta de MSX

Un juego de MSX se graba en bloques KCS, que es el formato del sistema. Stardust, no: sus cuatro bloques de datos son bloques del ZX Spectrum, con su bandera, sus datos y un XOR de comprobación. Los cuatro traen ese checksum correcto.

Y el cargador es una reimplementación de LD-BYTES, la rutina de carga de la ROM del Spectrum, con su mismo interfaz de registros.

El cargador trae una puerta trasera para trainers

Antes de arrancar el juego, el cargador salva 94 bytes a memoria alta y mira si empiezan por tres 0xC9. Si es así, los trata como una lista de parches y los aplica sobre el juego recién cargado: dirección y valor, uno detrás de otro.

La cuenta dice para cuántos: 3 de firma + 1 de contador + 30 parches de 3 bytes = 94. Está dimensionado exactamente para treinta. Es lo que usaban los cargadores de las revistas de la época.

Dos juegos en una cinta

Al superar la última zona de naves el juego vuelve al cassette a por una segunda parte en la que el protagonista va a pie. Y no usa para ello la rutina del cargador, que sigue viva en memoria: trae la suya, que enciende el motor de la cinta y lee el bit de datos del chip de sonido.

Los dos programas ni siquiera comparten motor: los objetos de la primera parte llevan estructuras de 8 bytes, y la segunda mezcla dos sistemas: unas entidades de 46 bytes que llevan apuntada dentro la rutina que las gobierna, y tablas ligeras de 5 para los enemigos —cuatro andantes como máximo, con los voladores aparte—. (Aquí decía «de 46 en la segunda» a secas: ese 46 es solo el de las entidades con puntero.)

Lo que el MSX obligó a cambiar

El Spectrum escribe directamente en su memoria de pantalla, que es RAM normal. En el MSX la memoria de vídeo está detrás del chip gráfico y hay que enviarla por un puerto, byte a byte.

Por eso esta versión lleva un buffer de pantalla que el original no necesita: 3840 bytes en 0x4000-0x4EFF, de 24 de ancho por 160 de alto, que el volcado envía a la VRAM en tres bandas de 56, 64 y 40 filas, columna a columna. Veinticuatro bytes son 192 píxeles, más estrecho que la pantalla: por eso el marco de los lados no se mueve. Y lo que sobra está a lo alto, que es por donde scrollea.

Los ejes estuvieron publicados al revés: el ld b,028h del volcado se leyó como «40 columnas» y es el bucle interior, que recoge 40 bytes de una misma columna a saltos de 24. El error se propagó al ancho de los mapas de nivel. Lo caza dibujarlo: de 24 en 24 sale la tabla de récords legible; de 40 en 40, ruido.

Sprites dibujados a mano

El MSX tiene sprites por hardware. Aquí no se usan: se dibujan por software, a la manera del Spectrum, desplazando el dibujo bit a bit y componiéndolo con AND y OR.

Las dos partes del juego comparten esa rutina. De 40 bytes comparados solo difieren seis, y tres de ellos son and (hl) contra or (hl).

Una cobertura que era mentira, dos veces

A mitad del trabajo, sembrar el trazador con rutinas sacadas del cotejo con la versión de Spectrum subió la cobertura del 25 % al 75,8 % de golpe. Parecía el hallazgo de la sesión y era contaminación: las tablas de color, el relleno de ceros y hasta los datos de nivel aparecían marcados como código al 100 %.

Se arregló declarando esas zonas como datos… y volvió a colarse, porque las rutinas se quedaron como puntos de entrada. Cuarenta y una caían dentro de los tiles y los sprites, así que el trazador seguía entrando a desensamblar dibujos: 17.000 bytes de gráficos publicados como instrucciones, con la cobertura hinchada del 24,6 % al 61,6 %.

Nada de lo que se comprobaba podía verlo. El binario reensamblaba igual —son los mismos bytes, solo cambia cómo se leen—, el presupuesto cerraba igual, y la sanidad del trazado sólo miraba los rangos de un fichero donde los gráficos no estaban. Ahora hay una comprobación para exactamente esto: ningún punto de entrada puede caer dentro de un rango declarado como datos.

Y luego llegó la prueba de verdad. Un aficionado, Araubi, había grabado una partida completa de 38 minutos en el emulador. Reproduciéndola y anotando por dónde pasa el procesador, de las 1489 direcciones que el juego ejecutó, el trazador ya alcanzaba 1444: la limpieza era correcta. Y las que faltaban dejaron de ser una corazonada para pasar a ser código con su cuenta de muestras al lado. La cobertura real del bloque es del 26,0 %, y la de la segunda parte subió al 35,0 % al aparecer ahí sus dos rutinas más trabajadoras, que estaban clasificadas como tablas de datos.

Los gráficos

No son capturas de pantalla. Están dibujadas a partir de los datos del propio binario, con la geometría que usa el juego. Por eso valen de comprobación: si el reparto del bloque estuviera mal, saldría ruido en vez de una tilería.

Los 111 tiles del decorado
Los 111 tiles del decorado
Los 83 sprites
Los 83 sprites
La pantalla de carga, firmada CANO
La pantalla de carga, firmada CANO
La tipografía: 59 caracteres
La tipografía: 59 caracteres