Mediante esta página pretendo dar a conocer algunos de mis proyectos de programación con el MSX
El compilador SDCC es un compilador cruzado para pequeños dispositivos, que se ejecuta tanto en Windows como en Unix/Linux y que permite generar código para una gran variedad de plataformas de 8 y 16 bits. Entre las plataformas que soporta se encuentra el Z80 y el Z80 con las extensiones de GameBoy (GBZ80).
El código Z80 que genera este compilador por defecto no está destinado para ser ejecutado en un MSX y la salida que genera es un fichero en formato IntelHex. Mediante el uso de este backend para MSXDOS conseguiremos que los ficheros de salida sean fácilmente convertibles a .COM. Los requisitos del sistema Windows o Unix/Linux donde vayamos a realizar la compilación son:
Ambas herramientas pueden ser instaladas tanto en forma binaria como partiendo de los fuentes y compilándolas. Los ficheros básicos para genererar código compatible MSXDOS mediante el SDCC son los siguientes:
main
(int main(char **argv, int argc)
) y que añade un poco de overheadin
y out
para facilitar la compatibilidad con código Hitechmemcpy
y memset
Lo primero que debemos hacer es ensamblar los ficheros .s
anteriores mediante el ensamblador sdasz80
y compilar los ficheros .c
anteriores con el sdcc
incluido en el paquete SDCC:
$ sdasz80 -o crt0msx_msxdos.s
ó $ sdasz80 -o crt0msx_msxdos_advanced.s
$ sdasz80 -o putchar.s
$ sdasz80 -o getchar.s
$ sdasz80 -o dos.s
$ sdasz80 -o dos2.s
$ sdasz80 -o interrupt.s
$ sdasz80 -o ioport.s
$ sdasz80 -o keyboard.s
$ sdasz80 -o vdp.s
$ sdcc -mz80 -c -o conio.rel conio.c
$ sdcc -mz80 -c -o heap.rel heap.c
$ sdcc -mz80 -c -o mem.rel mem.c
Después de esta operación obtendremos 11 ficheros objeto con extensión .rel
y con el mismo nombre que los originales. Para hacer una pequeña prueba partimos de un fichero fuente de ejemplo ej.c
:
#include "conio.h" #include "dos.h" void main(void) { puts("Hello, world :-)\r\n"); exit(0); }
Compilamos de la siguiente manera:
$ sdcc -mz80 --code-loc XXXX --data-loc 0 --no-std-crt0 crt0msx_msxdos.rel putchar.rel getchar.rel dos.rel conio.rel ej.c
Nótese el parámetro --no-std-crt0
que le indica al compilador que no utilice el código de inicialización (startup) que trae por defecto para el Z80, sino que nosotros suministramos el nuestro por línea de comandos. XXXX le indica al compilador la localización del código (si usamos crt0msx_msxdos.s
XXXX = 0x0107 y si usamos crt0msx_msxdos_advanced.s
XXXX = 0x0178). Las variables globales serán alojadas justo a continuación del código.
Si no hay errores de compilación, entre los ficheros resultantes habrá uno llamado ej.ihx
, el cual pasaremos por parámetros a la utilidad hex2bin
para que lo convierta a binario:
$ hex2bin ej.ihx
Después de esta sentencia tendremos en el directorio actual un fichero ej.bin
que podremos renombrar sin problemas a ej.com
y ejecutarlo en el MSXDOS.
$ mv ej.bin ej.com
#include "types.h" #include "mem.h" #include "dos.h" #include "vdp.h" uint8_t scratch[128]; uint8_t ge5_load(char *file_name, uint8_t vramh, uint16_t vraml) { fcb f; uint8_t i; memset((uint8_t *) &f, 0, sizeof(fcb)); f.record_size = 128; f.drive = 0; memcpy(f.name, file_name, 11); if (open(&f) != 0) return 0; vdp_set_write_address(vramh, vraml); for (i = 0; i < 213; i++) { if (block_set_data_ptr(scratch) != 0) return 0; if (block_read(&f) != 0) return 0; if (i == 0) vdp_load_screen(scratch + 7, 121); // to skip GE5 header else vdp_load_screen(scratch, 128); } close(&f); return 1; } int main(void) { vdp_set_screen5(); ge5_load("EXAMPLE GE5", 0, 0x0000); // load at visible VRAM getchar(); vdp_set_text(); exit(0); }
main
(crt0msx_msxdos_advanced.s
).main
.interrupt.h
actualizado para versiones recientes de SDCC. Gracias a Jan P. Schümann.memcpy
, memset
, algunas rutinas VDP y un ejemplo de acceso a ficheros.files.s
y files.h
ya que la función lseek
no tenía los parámetros en el orden lógico. Ahora ya cumple con la recomendación POSIX.out(dirección, dato)
y in(dirección)
.read
y write
de files.h
de "unsigned int" a "int" para poder detectar valores negativos.main
y arreglado el bug que afectaba a la inicialización de variables globales.La diferencia entre hacer ROMs y ficheros COM en MSX con SDCC radica, básicamente, en el fichero crt0
. Recomiendo la lectura de la sección anterior.
En la web de Nerlaska (que recomiendo) hay información abundante sobre este asunto a la que iremos aportando tanto yo como Alberto Orante código fuente e información adicional. Por ahora dejo una modificación hecha por Alberto de las rutinas de interrupción de MSXDOS para que funcionen en ROMs.
En esta sección iré publicando código fuente C para MSX relacionado con la programación de la Moonsound. Los códigos publicados están relacionados con la serie de dos artículos que he escrito para la revista Call MSX, en concreto para sus números 3 y 4 sobre la programación de la Moonsound.
sbiload
:En esta sección iré publicando código fuente y datos relacionados con la implementación del algoritmo de compresión/descompresión Huffman en el MSX.
huffman.tar.gz contiene una implementación ANSI-C de los algoritmos de compresión y descompresión Huffman así como una versión específica para MSX del algoritmo de descompresión. La versión específica para MSX requiere, para ser compilada:
Ver fichero README en la subcarpeta huffman/msx
.
En esta sección iré publicando código fuente, utilidades y datos relacionados con la programación del VDP.
á é í ó ú ü Á É Í Ó Ú Ü ñ Ñ ¡ ¿
así como algún que otro símbolo. Aquí está:screen 2
(1 bit por pixel, blanco = 1, negro = 0). Este es el resultado de aplicar este programa a la tabla de caracteres Latin1 anterior.En esta sección iré publicando código fuente, utilidades y datos relacionados con la programación del PSG.
psg_sample
anterior. Utiliza la tabla de conversión logarítmica indicada en http://map.tni.nl/articles/psg_sample.php.Sección dedicada al uso de aritmética de punto fijo en en Z80 y/o en el MSX en particular.
This work is licensed under a Creative Commons License.
Página mantenida por Avelino Herrera Morales