Cargador BASIC

Cuando desarrollamos un programa en ensamblador con CMB prg Studio podemos ensamblarlo y cargarlo con Ctrl + F5. Si el programa tiene errores de ensamblado habrá que corregirlos; si no los tiene el programa se cargará y quedará listo para ejecutar. Para ejecutarlo tendremos que ejecutar manualmente la sentencia BASIC “SYS 49152”, donde 49152 debe sustituirse por la dirección de comienzo del programa en ensamblador (ej. * = $c000).

El proceso puede automatizarse un poco más con un “cargador BASIC”. Un cargador BASIC es un programa en BASIC que carga y ejecuta el programa en ensamblador. Este programa en BASIC puede generarse automáticamente desde CBM prg Studio con Tools > Generate BASIC Loader.

Utilizando esta opción se genera automáticamente un programa en BASIC similar al que sigue:

Cargador BASIC

Este programa es muy sencillo, y consta de:

  • Una variable llamada “SA” con la dirección de comienzo del programa en ensamblador.
  • Un bucle “FOR – NEXT” que recorre la sección DATA y carga el programa en ensamblador a partir de la dirección de comienzo.
  • Una llamada “SYS” para ejecutar el programa en ensamblador.
  • Una sección DATA con el programa en ensamblador ya ensamblado y codificado en decimal.

Este programa puede guardarse en un archivo *.bas y, a partir de ese momento, puede utilizarse para cargar y ejecutar el programa en ensamblador.

Otra alternativa es generar una llamada “SYS” e insertarla en el programa en ensamblador. Esto se hace en CBM prg Studio con Tools > Generate SYS Call.

Si utilizamos esta opción CBM prg Studio nos preguntará la dirección a la que llamar, y nos ofrecerá un par de opciones que no tienen mucha importancia (comentario y si la llamada será “elaborada” o “estándar”):

SYS Call

Elijamos lo que elijamos, CMB prg Studio generará e insertará en nuestro programa en ensamblador una secuencia de bytes como la que sigue:

SYS Call 2

Esa secuencia de bytes se carga a partir de la posición $0801, es decir, justo en el comienzo de la RAM de BASIC. Y es la forma en que BASIC codifica la sentencia “10 SYS 49152”.

Es decir, no es más que una forma indirecta de cargar en BASIC el programa “10 SYS 49152” (o “10 SYS DIRECCIÓN”), que vale para ejecutar nuestro programa en ensamblador.

De las dos opciones presentadas, cargador BASIC y llamada SYS, a mí me gusta más la segunda. Se genera menos BASIC y el grueso del trabajo se sigue haciendo en ensamblador. Además, con la segunda opción, aunque cambie el programa en ensamblador, el programa en BASIC no cambia (porque sólo es una llamada BASIC => ensamblador), mientras que con el cargador cada vez que cambie el programa en ensamblador habrá que regenerar el cargador.


Programa de ejemplo: Prog39

Interrupciones del VIC

Como ya hemos comentado en entradas anteriores, el C64 tiene un mecanismo muy interesante llamado “interrupciones”. Las “interrupciones” son, como su nombre indica, interrupciones en el flujo de ejecución normal de los programas que, de forma temporal, pasan a ejecutar una rutina de interrupción para luego continuar con el programa interrumpido.

Estas interrupciones se pueden generar por eventos en el software (ej. instrucción “brk”) o en el hardware (ej. eventos que ocurren en el VIC o en otros chips y que activan las patillas de interrupción del 6510).

Esta entrada está dedicada a las interrupciones que puede generar el VIC, es decir, las que guardan relación con la programación gráfica del C64.

El VIC puede generar interrupciones cuando se producen los siguientes eventos:

  • El raster llega a una determinada línea (registro $d012; ver entrada anterior).
  • Un sprite colisiona con el fondo.
  • Un sprite colisiona con otro sprite.

Por otro lado, el VIC tiene dos registros relacionados con interrupciones:

  • El registro $d019, que sirve para obtener información sobre las interrupciones generadas.
  • El registro $d01a que sirve para programar las interrupciones deseadas.

En ambos casos existe una correlación uno a uno entra la causa que genera la interrupción (o que se quiere que genere la interrupción), y los bits del registro $d019/$d01a:

  • Bit 0: El raster llega a la línea programada en el registro $d012.
  • Bit 1: Un sprite colisiona con el fondo.
  • Bit 2: Un sprite colisiona con otro sprite.

Además, el bit 3 sirve para consultar/generar interrupciones relativas al lápiz óptico (sin mucho interés para este blog), y el bit 7 para obtener información sobre si se ha generado una interrupción de cualquiera de los tipos.

En definitiva, para trabajar con interrupciones del VIC (ej. para detectar una colisión y restar vidas), hay que programar en el registro $d01a las interrupciones deseadas. Además, cuando se produzca una interrupción, y ya desde la rutina de interrupción, hay que averiguar de qué naturaleza es con el registro $d019 (esto sólo es necesario si pudieran ocurrir interrupciones de varias causas a la vez), y atender la interrupción ejecutando el código que sea necesario.

InterrupVIC


Programa de ejemplo: Prog38