Compilando que es gerundio
En artículos anteriores hemos visto cómo preparar el ambiente de trabajo a partir de NextBuild con Visual Studio Code (VSC), pero en algunos casos queremos, o necesitamos, un poco más de “libertad”, y acabamos creando un archivo .bat para compilar y ejecutar nuestro código.
En este artículo veremos algunos truquillos para personalizar Visual Studio Code con el fin de que programar para Next sea un poco más sencillo, aunque también se puede aplicar a los proyectos para ZX Spectrum “clásico”.
Antes de empezar
En este artículo asumo que ya tienes instalado Visual Studio Code y NextBuild, si no es así te recomiendo que te mires antes el artículo “Preparando el ambiente para programar para Next con Boriel ZX Basic y NextBuild”, y también “Compilar y ejecutar con F5 en Visual Studio Code”.
Así que partiendo de esta base, la carpeta donde se encuentra el compilador “Boriel ZX Basic” asumiremos que es “C:\ZXNext\NextBuildv7\zxbasic”, y el emulador “CSpect” se encuentra en la carpeta “C:\ZXNext\NextBuildv7\emu\CSpect”
Objetivos
En este artículo pretendo ayudar al lector a personalizar sus proyectos de Visual Studio. No es una biblia de la personalización de VSC, ya que es una herramienta con muchas opciones de configuración y personalización.
Si encontráis alguna inexactitud u omisión, dejadlo en los comentarios, o acudid a los canales habituales:
- Canal de Telegram: Boriel ZX Basic
- Twitter de Duefectu: @Duefectu https://twitter.com/Duefectu
- Foro de Boriel: https://www.boriel.com/forum/index.php
Áreas de trabajo en Visual Studio Code
VSC trabaja con áreas de trabajo, que se equiparan a directorios de nuestro disco duro. El detalle es que VSC, al abrir un área de trabajo o una carpeta, busca un subdirectorio que se llama “.vscode”, y si existe, lo utiliza como ubicación de los archivos de configuración del proyecto.
Vamos a ver las carpetas que necesitamos, y las que os sugiero yo, para gestionar vuestros proyectos:
- .vscode: Contiene los archivos de configuración del proyecto.
- data: Contiene el resultado de nuestro proyecto. Por llamarlo de alguna forma, el “master” con el resultado final.
- Scripts: Contiene los archivos .bat de compilación y ejecución, aparte de otros archivos auxiliares que necesitemos para esta labor.
El resto de contenido y carpetas lo dejo a vuestro gusto, aunque a mi personalmente me gusta utilizar una carpeta “_Recursos” donde tengo mis archivos de trabajo, como pueden ser las imágenes .png a partir de las que genero los sprites o los fondos de pantalla, archivos de sonido, mapeado, etc…
Y en la raíz ponemos nuestro fichero .bas principal, es decir, el que compilaremos. En este caso, y con un gran alarde de originalidad, le he llamado “Ejemplo.bas”.
La carpeta .vscode
En esta carpeta se colocan una serie de archivos de configuración, en formato .json, que Visual Studio Code utiliza para personalizar nuestro proyecto. En los ejemplos que se adjuntan a este artículo podemos ver los siguiente:
extensions.json
Contiene las extensiones que nos recomienda VSCode al abrir el proyecto. Aunque nosotros ya tenemos esas extensiones instaladas, cuando otro usuario abra nuestro código fuente, su VSCode le sugerirá las extensiones que debe instalar para poder trabajar de forma correcta.
{
"recommendations": [
"em00k.nextbuild",
"eliverlara.andromeda",
"maziac.nex-fileviewer",
"maziac.asm-code-lens",
"alefragnani.bookmarks"
]
}
En este caso, es una copia del archivo extensions.json de NextBuild en el que se nos recomienta la extensión NextBuild y algunas otras que nos ayudan en la edición.
settings.json
Este archivo contiene opciones de configuración relacionadas con los colores, el tipo de cursor, el lenguaje por defecto y el formateador (lo que da color al código) a utilizar. También lo hemos copiado de NextBuild.
{
"editor.cursorSmoothCaretAnimation": true,
"editor.cursorStyle": "block",
"files.defaultLanguage": ".bas",
"telemetry.enableCrashReporter": false,
"telemetry.enableTelemetry": false,
"[bas]": {
"editor.defaultFormatter": "em00k.nextbuild",
"editor.formatOnSave": true
},
"editor.tokenColorCustomizations": {
"comments": "#2ccf2c",
"numbers": "#e06565",
"keywords": "#f1db14",
"functions": "#13ad34"
}
}
tasks.json
Este es el archivo de configuración más importante, ya que permite personalizar las tareas de compilación y ejecución. Y en este caso… también lo hemos tomado prestado de NextBuild, pero le hemos hecho una pequeña modificación.
Básicamente hemos modificado la tareas “Compile ZXbasic” para que ejecute el archivo “Scripts/Compile.bat».
Tambien hemos modificado la tarea “Run in CSpect” para que ejecute el archivo “Scripts/Run.bat”, dejando el resto como estaba, aunque se puede personalizar sin problema.
La carpeta Scripts
En esta carpeta vamos a colocar los archivos que hemos referenciado en el tasks.json, aparte de los que necesitemos para poder realizar las tareas de compilación y ejecución.
El archivo Compile.bat
Este archivo se va a ejecutar cuando se compile el proyecto, y dependiendo del tipo de proyecto, lo personalizaremos a nuestro gusto.
Por ejemplo, para compilar nuestro programa para Spectrum clásico, el fichero “Compile.bat” sería algo así:
@echo off
echo Limpiando ficheros antiguos...
del *.tap /Q >nul
del data\*.* /Q >nul
:COMPILAR
echo Compilando...
C:\ZXNext\NextBuildv7\zxbasic\zxbc.exe Ejemplo.bas --org $6000 --heap-size 2048 --tap -B -a
if ERRORLEVEL 1 goto compilerError
echo Copiando el resultado a la carpeta data...
copy Ejemplo.tap data\Ejemplo.tap
goto endNow
:compilerError
echo -----------------------------------------------------------------------
echo - ERROR AL COMPILAR ---------------------------------------------------
echo -----------------------------------------------------------------------
exit 1
:endNow
echo Compilado correctamente!
El fichero está dividido en cuatro secciones:
En la primera eliminamos los archivos resultantes de compilaciones anteriores. Esto es útil para evitar confusiones. Más de una vez os habrá pasado que el compilador da un error y estáis ejecutando un archivo antiguo en el emulador.
La segunda sección es la que compila el programa Ejemplo.bas y genera un archivo .tap con cargador y autorun, si todo ha ido bien.
Si la compilación no ha ido bien la variable “ERRORLEVEL” coge el valor 1, y en este caso abortamos la operación saltando a la tercera sección, donde se informa al usuario con un mensaje y sale con un “exit 1” que lo que hace es que esa misma variable “ERRORLEVEL” valga 1, lo que hace que VSCode no ejecute el archivo “Scripts\Run.bat”
Si la compilación ha ido bien, se salta a “endNow”, que sencillamente regresa a VSCode, y este ejecuta el archivo “Scripts\Run.bat”.
En este ejemplo estamos generando un archivo .tap para Spectrum clásico, con el fin de no complicar demasiado el tema en el primer ejemplo, por lo que lo lanzaremos con el emulador ZXSpin, solo a modo de prueba, ya que al ser un .tap, CSpect no lo admite sin una imagen del NextOS, y no quiero complicarlo demasiado. Así que, en este primer ejemplo, el fichero “Run.bat” quedaría así:
start C:\ZXSpectrum\ZXSpin\zxspin.exe .\data\Ejemplo.tap
Una vez visto como funciona en clásico, vamos a complicarlo un poco más, y generaremos un archivo .nex con un recurso adicional que podemos cargar desde disco, y todo esto lo lanzaremos en CSpect.
Archivo compile.bat para Next
Compilar para Next es un pelín más complicado, ya que después de compilar, hay que convertir el resultado al formato .nex:
@echo on
set PROGRAMA=Ejemplo
echo Limpiando ficheros antiguos...
del *.nex /Q >nul
del *.bin /Q >nul
del data\*.nex /Q >nul
:COMPILAR
echo Compilando...
C:\ZXNext\NextBuildv7\zxbasic\zxbc.exe %PROGRAMA%.bas --org $6000 --heap-size 2048 –mmap %PROGRAMA%.map --output %PROGRAMA%.bin --zxnext --arch=zxnext
if ERRORLEVEL 1 goto compilerError
:BUILDNEX
echo Generando el archivo .nex...
python C:/ZXNext/NextBuildv7/zxbasic/tools/nextcreator.py ./Scripts/nex.cfg %PROGRAMA%.nex
if ERRORLEVEL 1 goto compilerError
echo Copiando el resultado a la carpeta data...
copy %PROGRAMA%.nex data\%PROGRAMA%.nex
goto endNow
:compilerError
echo -----------------------------------------------------------------------
echo - ERROR AL COMPILAR ---------------------------------------------------
echo -----------------------------------------------------------------------
exit 1
:endNow
echo Compilado correctamente!
Lo primero que añadimos en el .bat es una variable llamada “PROGRAMA”, a la que asignaremos el nombre del fichero principal que compilamos. En nuestro ejemplo, el fichero principal se llama “Ejemplo.bas”, así que asignaremos el valor a la variable con la siguiente línea:
set PROGRAMA=Ejemplo
Esto nos permite utilizar la variable dentro del .bat de forma repetida sin tener que cambiar demasiadas cosas en cada proyecto.
En esta versión, le pedimos al compilador que genere un archivo .bin (–output %PROGRAMA%.bin) para Next (–zxnext –arch=zxnext).
Este archivo .bin lo convertimos a .nex con la utilidad “nextcreator.py” incluida en Boriel ZX Basic. Esta utilidad utiliza un archivo “nex.cfg” donde definimos como queremos “montar” el archivo .nex
El archivo nex.cfg
Este archivo contiene la configuración para que la utilidad “nextcreator” componga el fichero .nex que ejecutaremos en CSpect:
; Minimum core versión
!COR3,0,0
!MMU./Scripts/sysvars.inc,10,$1C00
!PCSP$6000,$5ffe
.\programa.bin,5,$2000
El primer detalle es que, tal como se define en la tercera línea, el .nex va a incluir el archivo “sysvars.inc” en el banco 10, dirección $1c00. Este archivo contiene las variables de configuración del Spectrum, las títicas que empiezan en la dirección de memoria 23552. Sin estas variables, es posible que nuestro programa no funcione de forma correcta.
En la siguiente línea le indicamos que el programa se ejecutará en la dirección $6000, y que el stack se coloca en la dirección par inmediatamente inferior: $5ffe
Y por último, le indicamos que queremos que nuestro programa se coloque en el banco de memoria 5, a partir de la dirección relativa $2000, que se corresponde con la dirección absoluta $6000.
Será necesario reconfigurar este archivo en base a las necesidades de nuestro proyecto, pero para empezar con algo básico nos vale.
El archivo run.bat
Una vez se haya compilado y generado el archivo .nex, que se coloca en la carpeta “data”, podemos lanzar CSpect.
CSpect puede funcionar de dos maneras básicas: Con unidades mapeadas en nuestro disco duro, o con una tarjeta SD virtual que contiene el sistema operativo NextZXOS.
El caso más sencillo, que se basa en el mapeado de la carpeta data, en el que el archivo run.bat quedaría así:
start C:\ZXNext\NextBuildv7\emu\CSpect\CSpect.exe -w3 -16bit -brk -tv -zxnext -r -mmc=.\data\ .\data\Ejemplo.nex
Atención al parámetro “mmc”, tiene dos valores asignados: la carpeta “data”, y el archivo “.nex”. Esto hace que ejecute el archivo .nex, y que el contenido de la carpeta data esté disponible en el emulador, por ejemplo para cargar sprites, imágenes, datos, código adicional, etc…
Para copiar hacia una SD virtual, podemos utilizar la utilidad “hdfmonkey”, que podéis encontrar en https://github.com/gasman/hdfmonkey, añadiendo al .bat de compilación o al de ejecución, algunas líneas del tipo:
C:\ZXNext\NextBuildv7\emu\CSpect\hdfmonkey.exe mkdir C:\ZXNext\NextBuildv7 \emu\CSpect\SDCard.img \Ejemplo
C:\ZXNext\NextBuildv7\emu\CSpect\hdfmonkey.exe put C:\ZXNext\NextBuildv7 \emu\CSpect\SDCard.img data\*.* \Ejemplo\
start C:\ZXNext\NextBuildv7\emu\CSpect\CSpect.exe -r -w3 -16bit -brk -tv -zxnext -nextrom -mmc=" C:\ZXNext\NextBuildv7\emu\CSpect\SDCard.img"
Estas dos líneas crearán una carpeta “Ejemplo” en la raíz del disco, copiará todo el contenido de la carpeta “data” dentro de ese directorio y ejecutará el emulador cargando la imagen del sistema operativo.
En este caso, asumimos que el programa “hdfmonkey” se encuentra en la carpeta “C:\ZXNext\NextBuildv7\emu\CSpect\”, y que la imagen del NextZXOS se llama “SDCard.img”
Recursos
El código de ejemplo se puede descargar desde aquí.
Todo puede salir mal
En ese caso, recordad que podéis conseguir soporte en:
- Canal de Telegram: Boriel ZX Basic
- Twitter de Duefectu: @Duefectu https://twitter.com/Duefectu
- Foro de Boriel: https://www.boriel.com/forum/index.php
Menciones y agradecimientos
Especial agradecimiento a David Saphier (@em00k) por su excelente NextBuild, que me ha servido como inspiración y punto de partida. Sin su ayuda no habría sabido por dónde empezar.
A Boriel por su excelente compilador y su trabajo diario.
Y a toda la comunidad de aficionados por alentarme a seguir con mi trabajo de difusión.