War in Middle Earth

Una conversión del ZX Spectrum que se trajo el sistema de cinta entero, los atributos de color pegados a cada dibujo y hasta el motor de sonido del altavoz… que aquí no lo llama nadie. Los cuatro sitios que piden un efecto acaban en un ret pelado, y del PSG del MSX sólo se tocan los dos registros del joystick: este juego es mudo.

Melbourne House / Dro Soft · 1989 · Cinta, 62.261 bytes · MSX1 · 64 KB, sin BIOS · Conversión de Animagic S.A.

Aquí no hay ni una captura de pantalla. Todas las imágenes están dibujadas desde la cinta: se leen los bytes en los rangos que el listado tiene acotados y se revelan como los revela el juego, con sus máscaras y con el atributo de color que cada dibujo lleva pegado. Que salgan dibujos y no ruido es la prueba de que los rangos están bien leídos. El listado y las cifras salen del binario y se reproducen con make.

La cinta en cifras

100 %de la cinta explicada
5listados
767rutinas identificadas
11.814bytes de código
50.191bytes de datos
0bytes sin identificar
29,7 %de densidad de comentarios
0rutinas por debajo del 10 %

Lo que apareció al desmontarla

Este juego es mudo, y se puede señalar dónde se quedó el sonido

La conversión se trajo del Spectrum su motor de sonido entero: está en 0x6600, saca las notas por el out (0xFE) con el bit 4, y detrás lleva cinco efectos de veintiún bytes en 0x636F-0x63D7.

No lo llama nadie. Ni una sola instrucción de los cinco listados apunta a 0x6600. Y los cuatro sitios que piden un efecto —0x5F90, 0x647A, 0x6AA1 y 0x833D— llaman a 0x65FF, que es un ret pelado.

Del PSG del MSX sólo se escriben dos registros, el 7 y el 14, y los dos son para leer el joystick (0x046E). La única rutina que sabría escribir una nota en el PSG, 0x04F2, no la llama nadie tampoco. No hay un tercer camino: el juego no suena.

La pantalla de carga, entera, sacada de la cinta

Los 12.388 bytes del bloque [08] son una pantalla de SCREEN 2 completa: 6.144 de patrones y 6.144 de colores, y las cuentas cierran solas (0x88B8 + 100 + 6.144 + 6.144 = 0xB91C, el final exacto del bloque).

Dibujada, se lee lo que el juego dice de sí mismo: MAELSTROM GAMES LTD. PRESENTS, War in Middle Earth, Mike Singleton y, abajo a la derecha, CONVERSION by ANIMAGIC sa. Y el menú añade el resto: «Programado por C.J.Pink».

Los tiles del mapa van a nueve bytes, y ése es el sello de la conversión

Un tile de MSX ocupa ocho bytes. Los del mapa de este juego ocupan nueve: las ocho líneas del dibujo y, pegado detrás, un atributo del ZX Spectrum —tinta en los bits 0-2, papel en los 3-5, brillo en el 6—.

Los lee 0x75C7-0x75EB cuando el código de la rejilla lleva puesto el bit 7. La conversión no rehizo los gráficos: se trajo los del Spectrum con su color puesto y los traduce al vuelo, en 0x049F.

En 0x62FF no está el dibujo del cursor: está lo que el cursor tapa

Esos 24 bytes estaban documentados como el dibujo de la marca del cursor. No lo son. 0x6580 mete 0x62FF en el HL alternativo y el bucle de 0x65B4, por cada uno de los tres bytes de la columna, primero lee la pantalla (ld a,(iy+n)), la copia ahí, y sólo después compone el cursor encima.

0x64DC hace el camino de vuelta para borrarlo. El dibujo de verdad está en 0x6345, con su máscara detrás (ld ix,0x6345 en 0x657B). Y los 0xAD que trae la cinta ahí no son un dibujo: son lo que había bajo el cursor el día que se grabó.

El tablero de batalla se monta encima del menú, y es un damero

La batalla usa 0x5E00-0x62FF, que es donde vive el código del menú: una vez empezada la partida, el menú y sus textos son papel de borrador. Lo dice 0x8E08 con su ld b,0x5E, y el ldir de 0x904D lo borra entero antes de cada batalla.

Y el tablero es un damero: las cuatro rutinas de movimiento (0x893E y compañía) cambian siempre las dos coordenadas a la vez, así que la paridad de x+y no cambia nunca. El despliegue rechaza los pares de paridad distinta y los obstáculos van justo en las casillas del otro color.

El filtro de amigo o enemigo es un interruptor por opcode

Para recorrer las unidades del bando contrario, el juego no usa una bandera: se reescribe la instrucción. 0x8980-0x8982 mete un 0xD0 en 0x8AF3, y 0x8991-0x8993 mete un 0xD8.

0xD0 es ret nc y 0xD8 es ret c. La misma rutina, con el mismo umbral, devuelve las de un bando o las del otro según qué opcode se le haya escrito encima un momento antes.

El mapa viaja comprimido, y se vuelve a comprimir antes de cada batalla

0x9366 aparta los 0x16ED bytes comprimidos del mapa a 0x4000 con un ldir y los expande a los 0x33CD de 0xCC00 leyendo parejas de cuenta y valor. Lo llama 0x5E28, en el arranque: el mapa llega de la cinta ya comprimido.

Y 0x9394 hace lo contrario antes de cada batalla, volviéndolo a dejar en 0x16EC bytes. No es por ahorrar cinta: es por hacer sitio. Lo que se libera, 0xE2EC-0xFFFF, es exactamente donde viven los búferes de la batalla.

Y restos del Spectrum que en un MSX no significan nada

El modo de control 2 del menú —el Interface Two del Spectrum— no existe aquí: su puntero, en 0x06D7, es 0x0000, así que el menú salta del 1 al 3.

El bloque de teclado del ZX de 0x5F75-0x5FB7, que lee el puerto 0xFE, es código muerto. Y en la rutina de grabar la partida quedó sin convertir la comprobación de la tecla de parada: 0x0930 hace in a,(0xFE), que en un MSX no es el teclado.

Lo que la cinta dibuja

Debajo de cada pie está la dirección de donde sale. Todas se rehacen con make imagenes y no hace falta emulador.

DIBUJADA de 0x891C y 0xA11C — la pantalla de carga entera: 6.144 bytes de patrones y 6.144 de color, tal como los sube el cargador. Aqui esta el juego diciendo quien lo hizo
DIBUJADA de 0x891C y 0xA11C — la pantalla de carga entera: 6.144 bytes de patrones y 6.144 de color, tal como los sube el cargador. Aqui esta el juego diciendo quien lo hizo
DIBUJADOS de 0x9E00 — los 128 tiles del mapa, con el color que dice su atributo del Spectrum. Van a NUEVE bytes: ocho de dibujo y el atributo pegado detras
DIBUJADOS de 0x9E00 — los 128 tiles del mapa, con el color que dice su atributo del Spectrum. Van a NUEVE bytes: ocho de dibujo y el atributo pegado detras
DIBUJADOS de 0xA2E8 — los sprites de batalla apilados de dos en dos. Medido: cada uno son 32 bytes de 16x8 en parejas mascara/dibujo. Que las entradas consecutivas encajen en figuras de 16x16 es una lectura de la imagen, no una rutina que se haya encontrado
DIBUJADOS de 0xA2E8 — los sprites de batalla apilados de dos en dos. Medido: cada uno son 32 bytes de 16x8 en parejas mascara/dibujo. Que las entradas consecutivas encajen en figuras de 16x16 es una lectura de la imagen, no una rutina que se haya encontrado
DIBUJADOS de 0xA2E8 — los mismos 176 sprites, uno a uno. El orden de sus bytes no es obvio: van en parejas mascara/dibujo y en zigzag, porque la rutina de 0x887B escribe izquierda, derecha, baja una linea y vuelve
DIBUJADOS de 0xA2E8 — los mismos 176 sprites, uno a uno. El orden de sus bytes no es obvio: van en parejas mascara/dibujo y en zigzag, porque la rutina de 0x887B escribe izquierda, derecha, baja una linea y vuelve
DIBUJADA de 0xC800 — los 128 caracteres de ocho bytes. Los 33 primeros estan a cero: el primero con dibujo es el 0x21, y de ahi salen marcos, flechas, digitos, mayusculas y minusculas
DIBUJADA de 0xC800 — los 128 caracteres de ocho bytes. Los 33 primeros estan a cero: el primero con dibujo es el 0x21, y de ahi salen marcos, flechas, digitos, mayusculas y minusculas