Programando em C no MSX

Olá pessoal, um artigo que achei interessante e quero reproduzir aqui pra vocês é do Giovanni Nunes sobre programar em C no MSX, realmente vale a pena a leitura.

É possível programar em C no MSX? Claro que sim, no MSX Archive é até possível baixar tanto o Hitech-C quanto o MSX-C. Este último foi desenvolvido pela japonesa ASCII e “tecnicamente” é o C oficial do MSX — se você ficou interessado o Javier Lavandeira tem uma uma série intitulada relearning MSX em seu blog onde ele resolveu um fazer guia passo a passo sobre desenvolvimento para MSX partindo bem do princípio e tratando deste compilador.

Porém, se preferir algo mais “moderno” há o Small Device C Compiler, ou simplesmente SDCC, que é um compilador padrão ANSI C que suporta uma série de microcontroladores e microprocessadores de “pequeno porte” e entre eles o Z80. E seguindo uma sugestão feita pelo Rogério Machado via grupo GDMSX do Google+ resolvi montar um passo a passo sobre como configurar este compilador para ser usado no MSX.

Antes de começar

Se preferir, prepare um ambiente separado, seja utilizando uma máquina virtual,contêiner, chroot etc. Vá lá que eu espero 🙂

Instalando o SDCC

Claro, a primeira coisa é instalar o SDCC e também algumas ferramentas que serão utilizadas para a geração dos programas, nas distribuições que usam apt-get faça:

$ sudo apt-get --yes install make sdcc wget

As dependências serão resolvidas pelo apt-get portanto é só aguardar o download e a instalação terminarem.

Adicionando suporte ao MSX

O SDCC tem um suporte para geração de código para o processadores Z80 mas para que ele produza executáveis específicos para o hardware do MSX é necessário “ensiná-lo” corretamente sobre como fazê-lo. Isto significa basicamente que você precisará baixar e compilar os arquivos preparados pelo Avelino Herreras Morales na pagina dele. Mas se preferir eu preparei este script para fazer a tarefa:

#!/bin/bash
# configure MSX support in SDCC

function Create_Directories() {

    OLDPWD=$( pwd )

    for DIR in ${SDCC_INC_DIR}; do
        if [ ! -d ${DIR} ]; then
            echo -n "Creating directory ./${DIR}..."
            mkdir ${DIR}
            Return_Status ${?}
       fi
    done

    cd ${OLDPWD}
}

function Compile_Libraries() {

    ASM=$( which sdasz80 )
    CC=$( which sdcc )
    OLDPWD=$( pwd )

    cd ${DESTINATION_PATH}

    for S in $( ls *.s ); do
        echo "Assembling ${S}..."
        ${ASM} -o ${S}
        #Return_Status ${?}
    done

    for C in $( ls *.c | sed 's/\.c//g' ); do
        echo "Compiling ${C}.c...."
        ${CC} -mz80 -o ${C}.rel ${C}.c
        #Return_Status ${?}
    done

    cd ${OLDPWD}
}

function Download_Files() {

    OLDPWD=$( pwd )

    if [ -d ${DESTINATION_PATH} ]; then
        cd ${DESTINATION_PATH}
        for FILE in ${FILELIST}; do
            echo -n "Downloading ${FILE}... "
            echo $( HTTP_Download ${REPOSITORY} ${FILE} 2>/dev/null )
        done
    else
        echo "---FAIL--- DESTINATION_PATH not found!"
        exit 2
    fi
    cd ${OLDPWD}
}

function HTTP_Download() {

    FETCH=$( basename $( which curl || which wget || which lynx ) )
    URL=${1}
    FILE=${2}

    case ${FETCH} in
        curl)
            curl -L -o ${FILE} ${URL}/${FILE} -C -
            ;;
        lynx)
            lynx -source ${URL}/${FILE} >${FILE}
            ;;
        wget)
            wget -c ${URL}/${FILE}
            ;;
        *)
        echo "---FAIL--- I can't download files! :("
        exit 1
    esac

    echo "OK"
}

function Return_Status() {

    STATUS=${1}

    if [ ${STATUS} -eq 0 ]; then
        echo ${OKEY}
    else
        echo ${FAIL}
    fi
}

OKEY="OK"
FAIL="FAIL"
DESTINATION_PATH='msx'
DIRECTORIES=${DESTINATION_PATH}
REPOSITORY="http://msx.atlantes.org/sdcc_msx"
FILELIST="crt0msx_msxdos.s crt0msx_msxdos_advanced.s
types.h putchar.s getchar.s dos.s dos.h dos2.s dos2.h 
interrupt.s interrupt.h ioport.s ioport.h conio.c conio.h 
heap.c heap.h keyboard.s keyboard.h vdp.s vdp.h mem.c mem.h"

Create_Directories

Download_Files ${DESTINATION_PATH}

Compile_Libraries

Compile_Libraries

exit 0

Crie um diretório, mova o script para lá e o execute. Ele se encarregará de  baixar todos os arquivos necessários e compilá-los:

$ mkdir -p ~/Projetos/msx
$ cd ~/Projetos$ 
$ ./sdcc_enable_msx_support ./msx
Downloading crt0msx_msxdos.s... OK
Downloading crt0msx_msxdos_advanced.s... OK
Downloading types.h... OK
...
Assembling keyboard.s...
Assembling putchar.s...
Assembling vdp.s...
Compiling conio.c....
Compiling heap.c....
Compiling mem.c....

Não se preocupe com as mensagens de aviso — os ?ASlink-Warning… — é normal.

No final da execução ele terá criado um diretório específico, o “./msx” contendo os arquivos baixados, compilados e também os cabeçalhos para serem usados no compilador C.

SDCC_msx_files

Ah sim, male a pena uma leitura na página do Avelino para entender as diferenças entre o crt0msx_msxdos e o crt0msx_msxdos_advanced.

Convertendo o IHX para binário

Os programas compilados pelo SDCC são gerados em Intel HEX — 😀 Yey! 😀 — e precisam ser convertidos em binário para rodar no MSX. Você pode baixar e utilizar o hex2bin mas acabei montando um conversor bem xexelento em Python para cuidar desta tarefa.

Daí será necessário também instalar:

$ sudo apt-get install python python-pip
$ pip install bincopy

Para executar estas mal traçadas linhas:

#!/usr/bin/env python2
import bincopy
import sys
def main(argv):
inputfile = argv[0]
f = bincopy.File()
with open(inputfile, r) as fin:
f.add_ihex(fin)
print f.as_binary()
if __name__ == __main__:
main(sys.argv[1:])
view raw hexbin.py hosted with ❤ by GitHub

Como ele foi feito para ser integrado ao Makefile, não sofistiquei muito mas contribuições são sempre bem vindas. 🙂

Montando um Makefile

Mas por que? Porque, como já disse em outra oportunidade, é muito chato ficar tendo de lembar a toda hora a sintaxe e os parâmetros do compilador:

CAT=cat
CC=sdcc
ECHO=echo
EMULATOR=openmsx
HEXBIN=../bin/hexbin.py
MKDISK=
RM=rm
INFILE=hello.c
OUTFILE=hello
INCLUDE=-I../msx
PARAMS=-mz80 –no-std-crt0 –data-loc 0
NORMAL=–code-loc 0x107 ../msx/crt0msx_msxdos.rel
ADVANCED=–code-loc 0x178 ../msx/crt0msx_msxdos_advanced.rel
RELOCATE=../msx/putchar.rel ../msx/getchar.rel ../msx/dos.rel ../msx/conio.rel
.PHONY: normal advanced clean superclean
default:
make advanced
normal:
${CC} ${INCLUDE} ${PARAMS} ${NORMAL} ${RELOCATE} ${INFILE}
${HEXBIN} ${OUTFILE}.ihx >${OUTFILE}.com
advanced:
${CC} ${INCLUDE} ${PARAMS} ${ADVANCED} ${RELOCATE} ${INFILE}
${HEXBIN} ${OUTFILE}.ihx >${OUTFILE}.com
clean:
${RM} ${OUTFILE}.com ${OUTFILE}.ihx
superclean:
${RM} -f ${OUTFILE}.asm ${OUTFILE.com ${OUTFILE}.ihx ${OUTFILE}.lk ${OUTFILE}.lst ${OUTFILE}.map ${OUTFILE}.noi ${OUTFILE}.rel ${OUTFILE}.sym
view raw Makefile hosted with ❤ by GitHub

Ele está está pronto para compilar programas em C e retornar um “.com”, por padrão ele utiliza o crt0msx_msxdos_advanced mas você pode usar “make normal” ou trocar para que este seja o padrão.

Fazendo um teste

E claro é preciso testar se está tudo certo com o compilador:

#include "conio.h"
#include "dos.h"

void main(void) {
    puts("Hello, world :-)\r\n");
    exit(0);
}

Este é o mesmo programa de testes da página do Avelino e para compilar use simplesmente make:

SDCC_make

Daí é transferir o arquivo para um disquete ou imagem de disco com MSX-DOS e rodar, mais ou menos isto aqui para as imagens de disco:

$ sudo mount msxdos.dsk /mnt -t msdos -o rw,loop
$ sudo cp hello.com /mnt/hello.com && sync
$ sudo umount /mnt

Para o caso do disquetes remova o “,loop” e substitua o “msxdos.dsk” pelo dispositivo que corresponde a unidade de disquetes.

Aliás estes procedimentos podem ser acrescentados ao Makefile fazendo-o gerar uma imagem de disco, acrescentando o(s) arquivo(s) e executando o emulador, mas isto fica como exercício. 🙂

E para terminar

Na página do Avelino há outros exemplos de código e bibliotecas, além dos arquivos para suporte a geração de imagens de cartucho (ROM) diretamente pelo SDCC. Outra fonte interessante é na página do Nestor Soriano (o Konamiman) com uma biblioteca alternativa para as funções básicas de console, suporte para as pilhas TCP/IP que ele desenvolveu entre outras coisas. E como o SDCC usa é compatível com o padrão ANSI-C, há uma grande quantidade de códigos em C que pode ser compilado com pouca/nenhuma modificação para o MSX!

 

O link original do artigo vocês podem encontrar em;

Programando em C no MSX

 

Por enquanto é isso pessoal

[]´s

Dex

Deixe um comentário