Artículo de Dani Crespo publicado en RetroWiki. Adaptado y publicado por Konamito.
El objetivo de este tutorial consiste en aprender a programar una versión del juego Manic Miner y descubrir distintas técnicas de programación para optimizar el código. He seleccionado este juego porque es un auténtico clásico, con pocas pantallas y gráficos. Esto nos permitirá generar un código muy compacto, ya que en los juegos, la mayor parte de la memoria se dedica a los gráficos y a los datos de las pantallas.
Quiero dejar claro que ignoro como se ha programado el juego original, y que lo que voy a hacer es reproducirlo según mis métodos de programación. Por otro lado, no vamos a programar el juego completo, pero lo que hagamos será totalmente funcional. El objetivo es explicar como se puede hacer, y el que quiera que lo complete o modifique a su gusto.
El programa está escrito en BASIC para MSX, pero las técnicas empleadas son completamente válidas para cualquier microordenador con unas características similares. Una vez el programa funcione, podremos empezar a reprogramar algunas partes del código en ensamblador para descubrir que el programa se ejecuta mucho más rápidamente y que la cantidad de memoria necesaria se reduce considerablemente.
Inicialmente, el tutorial se divide en 7 partes:
- Rutina de presentación de la pantalla de juego.
- Rutina de carga de los gráficos y colores.
- Nudo principal de desarrollo.
- Rutinas de control de enemigos.
- Rutinas de control de Willy, el protagonista.
- Rutinas de control de marcadores, inicio y final de partida.
- Adaptación a código máquina de algunas rutinas del juego.
Y si alguien se quiere entretener a adaptar el código a otros sistemas, encantado. Lo he diseñado para que sea bastante simple.
RUTINA DE PRESENTACIÓN DE LA PANTALLA DE JUEGO
Todos los elementos que configuran las distintas pantallas han sido codificados para conseguir que funcione con muy pocos datos. Con esto, conseguimos que ocupe poca memoria, se reduzca el tamaño del código y se ejecute más rápidamente.
Codificación de los datos
A partir de la línea 9010 se han introducido los datos de la primera pantalla, en varias líneas DATA.
Formato de la codificación
La rutina está preparada para poner un gráfico en una posición concreta de la pantalla, o una tira de ellos vertical o horizontalmente. Cada 4 o 5 valores representan un gráfico o una tira de ellos, según el siguiente formato:
- Acción a realizar: «1» Tira horizontal, «2» Tira vertical, «3» un único carácter y «255» fin datos de la pantalla.
- Posición inicial horizontal.
- Posición inicial vertical.
- Posición máxima en repeticiones. Si la acción es tipo «3» no hay que introducir este valor.
- Carácter a imprimir.
Por ejemplo: La secuencia «2, 0, 0, 15, 1» indica que hay que poner una tira de caracteres tipo «1» (ladrillos) a partir de la posición 0,0 hasta la posición 0,15. Esto dibuja la pared de ladrillos de la izquierda.
La secuencia «3, 24, 4, 5» coloca la llave (carácter 5) que hay en el suelo, entre las dos plantas.
Los códigos de los gráficos tienen la siguiente relación:
- Ladrillos.
- Suelo.
- Cinta transportadora.
- Suelo que se deshace.
- Llave.
- Estalactita.
- Planta.
En otras pantallas veremos como se añaden nuevos códigos.
En cada pantalla cambiaremos los gráficos, pero la función de cada uno de estos códigos será exactamente el mismo.
Funcionamiento de la rutina
La rutina está ubicada a partir de la línea 6200.
Con el READ de la línea 6210 empezamos a leer los valores del DATA de la línea 9010. El primer valor lo ponemos en «D», que es el código de la acción que hemos de realizar.
Si la acción es «1» o «2», leemos los siguientes 4 valores de DATA y los ponemos en las variables «H», «V», «R» y «G», y ejecutamos un bucle que repite la impresión hasta llegar a la posición indicada en «R».
Si la acción es «3», leemos los siguientes 3 valores de DATA y ponemos un único carácter en la posición indicada.
Si la acción es «255» damos por finalizada la impresión de la pantalla y salimos de esta rutina.
Así, la variable «D» contiene la acción, «V» la posición vertical, «H» la posición horizontal, «G» el gráfico elegido, y opcionalmente, en «R» la posición máxima cuando la acción es «1» o «2».
Por ahora, los códigos de los caracteres van del 1 al 7, pero en realidad no usamos estos, sino que en la línea 6240 lo pasamos al valor ASCII correcto. Se han seleccionado unos valores más simples para que sea más fácil recordarlos.
Como podéis ver, tanto el código de la rutina como de los datos es muy pequeño. Sólo 21 líneas.
Si ejecutamos el programa veremos que aparece la pantalla, pero en lugar de los gráficos aparecen distintos caracteres ASCII. Esto quiere decir que queda por redefinir el juego de caracteres con los gráficos del juego.
Vamos a ver como se hace.
RUTINA DE CARGA DE LOS GRÁFICOS
En el MSX el juego de caracteres está almacenado en la ROM, pero al iniciar el sistema se vuelcan en la memoria de video VRAM, y allí es donde los tendremos que modificar.
Codificación de los gráficos
A partir de la línea 9000 se han introducido los datos de los gráficos en líneas DATA.
Formato de la codificación
La rutina está preparada para redefinir los caracteres indicados. Así, el primer valor del DATA indica el carácter a redefinir, y los siguientes 8 valores corresponden a los datos del gráfico, con un tamaño de 8×8 pixels.
Funcionamiento de la rutina
La rutina está ubicada a partir de la línea 6000.
Mediante el RESTORE de la línea 6000 nos situaremos en la línea DATA que contiene los datos de los gráficos de la pantalla correspondiente.
Con el READ de la línea 6010 leemos el primer valor y lo ponemos en «D», que es el código del carácter a redefinir. Si este valor es «0», dejamos de redefinir más caracteres. En caso contrario, un bucle leer los siguientes 8 valores del DATA y los mete en la posición de memoria de la VRAM donde está almacenado ese carácter. El primer carácter está en la posición 0 de la VRAM. Con el cálculo de la línea 6025 sabremos a partir de que posición hemos de volcar los datos de ese carácter.
Si ejecutamos el programa, veremos que ya aparecen los gráficos en la pantalla pero en blanco sobre negro. Esto quiere decir que queda por redefinir los atributos de los caracteres del juego.
Un último esfuerzo y ya está.
RUTINA DE CARGAS DE LOS COLORES
El modo SCREEN 1 del MSX es una pantalla de texto con posibilidad de usar SPRITES. En este modo la forma de trabajar con los colores es un poco peculiar. En otros sistemas, un byte en la memoria de video indica un carácter en una posición de pantalla, y otro byte indica el atributo de color de esa posición. En el MSX la cosa es más simple y limitada. Cada 8 caracteres consecutivos de la tabla ASCII pueden tener un único atributo de color compartido. Así, «@ABCDEFG» han de tener el mismo color y la «HIJKLMNO» pueden tener otro distinto. De esta forma, con solo 32 bytes en la memoria de video controlamos los colores de los 256 caracteres. Una forma realmente original, pero poco práctica. Por un lado, al poner una letra en pantalla ya sale con el color asignado, cosa que hace que sea más rápido, pero por otro lado no te permite poner un texto en pantalla con distintos colores. Para ello deberíamos usar el modo SCREEN 2, que ya es totalmente gráfico, pero más complejo de gestionar.
Codificación de los colores
A partir de la línea 9007 se han introducido los datos de los colores en una línea DATA.
Formato de la codificación
Los colores se han almacenado en 10 valores. Se cambian los atributos de color desde el carácter 128 hasta el 207. En principio es más que suficiente para los pocos gráficos que hemos de usar.
Funcionamiento de la rutina
La rutina está ubicada a partir de la línea 6100. Simplemente leemos los 10 valores de la línea DATA y vamos haciendo un VPOKE en la dirección de la VRAM correspondiente. Este valor se indica en la línea 6100.
Misión cumplida.
NUDO PRINCIPAL
En la línea 100 comienza el nudo principal de desarrollo, que es el lugar desde donde iremos llamando al resto de rutinas.
Ahora mismo:
- Activa el modo SCREEN 1 haciendo un GOSUB 7000
- Carga los gráficos de la pantalla con un GOSUB 6000
- Queda en pausa hasta que se pulse una tecla, con el INKEY$ de la línea 300
- Activa el modo SCREEN 0 para volver al editor BASIC.
Estas líneas irán cambiando a lo largo del tutorial para ir recogiendo los sucesivos cambios que se produzcan.
RUTINA DE ACTIVACION DEL MODO GRAFICO
En la línea 7000 comienza una subrutina que desactiva la línea inferior del BASIC donde se muestran los valores de las teclas de función, activa el modo SCREEN 1, pone el ancho en 31 caracteres y configura los colores por defecto.
RUTINA DE ACTIVACION DEL MODO TEXTO
En la línea 7100 comienza una subrutina que activa el modo SCREEN 0, vuelve a configurar los colores normales y activa la línea inferior del BASIC y nos devuelve al editor.
RESUMEN Y COMENTARIOS
En las líneas DATA no es obligatorio seguir la numeración que he indicado. Lo único importante es que los datos estén introducidos con el formato y orden indicado: datos de los gráficos, datos de los atributos de color y datos de la pantalla de juego. Es recomendable no mezclar los valores en una misma línea para que sea más fácil una posterior identificación y modificación.
Algunos partes se podrían haber optimizado para ganar algo de velocidad, pero las he dejado como están para que sea más fácil y comprensible por si alguien quiere adaptarlo a otro sistema.
El nudo principal de desarrollo lo he puesto en las primeras líneas, ya que en esta zona el BASIC es más rápido.
Toda la explicación de este tutorial la he realizado al revés de como funciona el programa, ya que como se puede apreciar en el listado, lo primero que se hace es redefinir los gráficos, asignar sus atributos de color e imprimir la pantalla. Esto se ha hecho así para comprender mejor las distintas etapas del proceso.
El listado de todo este montaje queda así.
Para terminar, todo este desarrollo se ha realizado en un MSX-2 Philips VG-8235 y el listado se ha impreso en una impresora matricial Brother M-1109. A lo retro, como dios manda.
Muy bueno. Grande Manic Miner! Por cierto al final encontraron a M.Smith que estaba en paradero desconocido, ahora da charlas de como hizo el juego. Un clásico sin duda 🙂
Aún quedan dos capítulos más que publicaré antes de final de año. Los tenéis aquí y aquí, en RetroWiki, fuente original.
Cáspita. Traté de hacer lo mismo: una versión opensource del Manic Miner pero en ensamblador. Lo que me hizo abandonar el proyecto es que lo empecé con sprites – tal y como lo plantea Dani Crespo, pero consideré después que, por respeto al original, debería hacerse con sprites por software para conseguir los problemas de colisiones de color (atributos), como en la versión de Software Projects. Después, en un arrebato de ira, mi pobre eeePC cascó y se llevó por delante todo el código fuente, así que nada que hacer.
Me interesa ver qué tal se moverá el juego final, si es todo Basic puro.