Tutoriales

Tutorial de programación para Game Boy Advance

El Game Boy Advance de Nintendo fue una consola portátil que sustituyó al Game Boy Color y que podía correr juegos muy al estilo del Super Nintendo. Cuenta con un procesador ARM7 de 32 bits que corre a 16.8MHz, 288kB de RAM y 96kB de VRAM. Como siempre, la comunidad Homebrew desarrolló hace tiempo un compilador GNU capaz de generar programas ejecutables en el GBA, ya sea cargándolos en un cartucho Flash o enviándolos a través de su Link Port por un cable Xboo o una interfaz SPI (Serial Peripheral Interface). En este tutorial aprenderás a instalar el kit de desarrollo de software devkitARM (parte de devkitPPC) para generar tus propios ejecutables GBA.

 

 

Ítems necesarios

Para iniciar este tutorial deberás contar con lo siguiente:
+ Conocimientos de lenguaje C
+ Un equipo Windows
+ Un emulador de Game Boy Advance (busca en Google 'VisualBoyAdvance')

+ El kit de desarrollo de software devkitARM parte de devkitPRO

(Descarga)

Instalando devkitARM

Una vez que hayas descargado los archivos, deberás ejecutar el archivo devkitProUpdater-1.5.0.exe. Te recomiendo que guardes los archivos y que elijas que no se eliminen después de instalarlos. En los componentes a instalar sólo es necesario que instales devkitARM para el GBA, pero también puedes instalar devkitPPC (Gamecube) y devkitPSP (PlayStation Portable). También es bueno que instales Notepad++ ya que te servirá para editar tu código fuente. Es obligatorio que instales mSys (MINGW32) ya que ejecutará un mini ambiente Linux que se encargará de compilar tu código.

El instalador creará una carpeta en tu disco duro llamada C:\devkitPro en donde encontrarás todas las librerías y compiladores necesarios para generar tu ejecutable GBA. Dentro de la carpeta C:\devkitPro\examples\gba\ encontrarás ejemplos de programas funcionales de GBA de los cuáles podrás aprender.

Estudiando el 'Hola Mundo'

Para compilar tu primer programa deberás copiar el directorio template dentro de C:\devkitPro\examples\gba\ a otra ubicación en tu disco duro. Es conveniente que esa ubicación sea cercana a la raíz de tu disco duro y que los nombres de directorio no tengan espacions o caracteres especiales. Un ejemplo apropiado sería: d:\gba\.

La carpeta template contiene lo siguiente:

+ Carpeta source. Contiene el código fuente de tu programa.
+ Archivo makefile. Archivo de texto que contiene las instrucciones necesarias para integrar tu ejecutable GBA.

Abre el archivo template.c en tu Notepad++, verás el siguiente código:

#include <gba_console.h>

#include <gba_video.h>

#include <gba_interrupt.h>

#include <gba_systemcalls.h>

#include <gba_input.h>

#include <stdio.h>

#include <stdlib.h>

 

//---------------------------------------------------------------------------------

// Program entry point

//---------------------------------------------------------------------------------

int main(void) {

//---------------------------------------------------------------------------------

 

 

   // the vblank interrupt must be enabled for VBlankIntrWait() to work

   // since the default dispatcher handles the bios flags no vblank handler

   // is required

   irqInit();

   irqEnable(IRQ_VBLANK);

 

   consoleDemoInit();

 

   // ansi escape sequence to set print co-ordinates

   // /x1b[line;columnH

   iprintf("\x1b[10;10HHello World!\n");

 

   while (1) {

      VBlankIntrWait();

   }

}

La primera sección son las inclusiones de librerías para controlar el hardware del GBA. Puedes abrirlas y estudiar su contenido. Es conveniente para tener en cuenta qué funciones podrás usar en tu código. Posteriormente se inicializan las interrupciones hardware del GBA con irqInit() y en este caso se prepara la interrupción de refresco de video, pero no se usará.

Después se inicializa la pantalla del GBA para que opere como consola de texto ASCII con la función consoleDemoInit(). Al haber inicializado la pantalla ya se puede usar la función iprintf() para enviar cadenas de texto a pantalla. Esta función opera con secuencias de escape ANSI para mover el cursor o colocar texto en lugares específicos, algo parecidas a gotoxy() del antiguo TurboC.

Por último el programa entra a un ciclo infinito.

Compilando 'Hola Mundo'

La compilación es bastante sencilla. Debes ir al menú Inicio y buscar en el menú devkitPRO el programa mSys y ejecutarlo. Se abrirá una ventana como ésta:

Para compilar tu programa debes entrar a la carpeta en donde está almacenado el makefile de tu proyecto. En mi caso la carpeta es D:\nintendo\GBA-Homebrew\HolaMundotexto. Para cambiar de carpeta usa el comando cd seguido de la carpeta inferior, una por una como se ve en la siguiente imagen.

 

 Y para compilar sólo falta que escribas make y el compilador hará el resto. Si todo salió bien, te generará un archivo con el nombre de tu carpeta y terminado en _mb.gba, donde _mb significa multiboot.

Link@ATHLONII-X2 /d/nintendo/gba-homebrew/Holamundotexto
$ make
template.c
arm-eabi-gcc -MMD -MP -MF /d/nintendo/gba-homebrew/Holamundotexto/build/template
.d -g -Wall -O3 -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer -ffast-math
-mthumb -mthumb-interwork  -I/c/devkitPro/libgba/include -I/d/nintendo/gba-homeb
rew/Holamundotexto/build -c /d/nintendo/gba-homebrew/Holamundotexto/source/templ
ate.c -o template.o
linking multiboot
built ... Holamundotexto_mb.gba
ROM fixed!

El archivo multiboot resulta práctico ya que se puede almacenar en un cartucho Flash y el GBA lo leerá como si fuera un cartucho original. Pero también se puede enviar este archivo mediante una conexión Xboo sin necesidad de contar con un cartucho (esto se detallará más adelante).

Probando tu 'Hola Mundo'

Una vez que hayas descargado VisualBoyAdvance sólo basta con que abras el archivo .gba con el emulador y verás con éxito la siguiente pantalla.

Pantalla de bienvenida

Ahora crearemos un visor sencillo de archivos PCX. Copia tu carpeta templates y modifica el archivo template.c para que muestre el siguiente contenido.

//---------------------------------------------------------------------------------

// GBA PCXView sample code for devkitARM - http://www.devkit.tk

// Suitable for a splash screen for a game

//---------------------------------------------------------------------------------

#include "gba_video.h"

#include "gba_systemcalls.h"

#include "gba_input.h"

#include "gba_interrupt.h"

#include "pcx.h"

#include "fade.h"

 

#include <stdlib.h>

 

//---------------------------------------------------------------------------------

// header for binary data generated by bin2o macro in makefile

//---------------------------------------------------------------------------------

#include "splash_pcx.h"

 

//---------------------------------------------------------------------------------

// storage space for palette data

//---------------------------------------------------------------------------------

u16 PaletteBuffer[256];

 

unsigned int frame;

 

//---------------------------------------------------------------------------------

void VblankInterrupt()

//---------------------------------------------------------------------------------

{

  frame += 1;

  scanKeys();

}

 

//---------------------------------------------------------------------------------

// Program entry point

//---------------------------------------------------------------------------------

int main(void)

//---------------------------------------------------------------------------------

{

  // Set up the interrupt handlers

  irqInit();

 

  irqSet( IRQ_VBLANK, VblankInterrupt);

 

  // Enable Vblank Interrupt to allow VblankIntrWait

  irqEnable(IRQ_VBLANK);

 

  // Allow Interrupts

  REG_IME = 1;

 

  SetMode( MODE_4 | BG2_ON );      // screen mode & background to display

  DecodePCX(splash_pcx, (u16*)VRAM , PaletteBuffer);

 

  FadeToPalette( PaletteBuffer, 60);

   

  while (1)

  {

     VBlankIntrWait();

  }

}

 

 Las instrucciones ejecutadas se describen a continuación.

 

+ El archivo splash_pcx.h contiene un archivo PCX definido como un arreglo constante de bytes. Este arreglo puede ser generado por la aplicación SL File2Array que podrás encontrar en este link. El archivo PCX debe medir 240x160 pixeles. Si gustas puedes probar con el archivo ya convertido aquí disponible. El archivo volcado en un arreglo C se ve así:

//Volcado de archivo C:\Users\Link\Desktop\splash.pcx

//9461 bytes totales

 

//Convertido por SL File2Array v0.01

//http://www.migsantiago.com

 

const u8 splash_pcx[] = {

0x0A, 0x05, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x9F, 0x00, 0x48, 0x00, 0x48, 0x00,

0x01, 0x01, 0x01, 0x08, 0x08, 0x17, 0x16, 0x09, 0x03, 0x1B, 0x05, 0x16, 0x1D, 0x13, 0x0C, 0x14,

0x13, 0x13, 0x0E, 0x0E, 0x27, 0x1A, 0x0B, 0x2A, 0x18, 0x0F, 0x39, 0x14, 0x14, 0x2B, 0x16, 0x14,

0x37, 0x2A, 0x07, 0x05, 0x29, 0x06, 0x19, 0x22, 0x17, 0x0F, 0x29, 0x18, 0x15, 0x37, 0x07, 0x05,

...,

 

 

+ La variable paletteBuffer sirvepara las librerías de decodificación PCX y para ajustar los colores a mostrar en el GBA. No hay que preocuparse por entenderlas por ahora.

+ La función vblankInterrupt() se ejecuta cada que el cuadro de video del GBA se actualiza. En esta función se incrementa el contador frame y se lee el estado de los botones del GBA mediante scanKeys() aunque no se deposita su estado en ninguna variable.

+ Ya dentro del main se vincula la función vblankInterrupt() a la interrupción IRQ_VBLANK.

+ Se habilitan las interrupciones poniendo en 1 la variable REG_IME.

+ Mediante SetMode() se establece el modo de color de la pantalla del GBA, pero ahora tampoco es necesario entrar en detalle.

+ La función DecodePCX() recibirá el archivo volcado splash_pcx y lo decodificará directamente en la memoria de video del GBA, apuntada mediante VRAM. Después de decodificarlo la pantalla ya contendrá la imagen pero deberá pasar por un degradado de color mediante la función FadeToPalette(). El segundo parámetro de la función indica el número de cuadros que tardará el degradado del color, siendo 60 en este ejemplo.

+ Al final tu pantalla se verá como sigue.

El cable Xboo y la interfaz SPI

El GBA cuenta con un puerto de expansión en la parte trasera.

Este conector normalmente se usa para intercambiar datos entre 2 o más GameBoys, cargar juegos sin usar cartucho desde otro GameBoy o desde el Gamecube o para conectar expansiones como el eReader. El puerto se puede comportar en varios modos, de entre los cuales están:

+ Modo Normal. Transferencia de datos entre dos unidades. Puede efectuarse sin tener un cartucho insertado.
+ Modo Multijugador. Transferencia de dato de 2 hasta 4 unidades.
+ Modo UART. Se comporta como un RS232.
+ Modo JoyBus. Sólo compatible con software de Nintendo.
+ Modo de uso general. Los 4 pines del puerto se comportan como entradas/salidas digitales.

En el modo normal se pueden cargar programas en el GBA sin necesidad de tener un juego insertado. Existen interfaces como el cable Xboo que mediante el puerto paralelo de la PC se envían juegos multiboot al GBA. Mediante esta aplicación es posible enviar nuestros archivos compilados _mb.gba al GameBoy y probarlos en vivo.

La comunicación involucra el envío de parámetros de cierta forma encriptados y es algo complicado. La velocidad de SPI puede ser de 256kHz hasta 2MHz con envío de 16 bits por evento, pero se recomienda de 256kHz para cuando se usan cables largos. Si quieres más detalles sobre el hardware del GBA aquí los puedes estudiar.
http://nocash.emubase.de/gbatek.htm

Un programador llamado Ken Kaarvik logró compilar un programa en un PIC24 que mediante la interfaz SPI envía el archivo .gba al GBA y lo ejecuta. Después mide 2 potenciómetros y muestra su valor en un vúmetro en la pantalla del GBA. Aquí el link de su proyecto:
http://sites.google.com/site/kenselectronicsprojects/gameboy-analog-meter

Si deseas construir un cable Xboo para enviar tus programas al GBA aquí puedes encontrar las instrucciones:
http://nocash.emubase.de/gba-xboo.htm

Con esto termina el tutorial del GBA. Si deseas aprender máste recomiendo que estudies el contenido de los ejemplos y que descargues otras aplicaciones creadas por programadores Homebrew. También puedes compilar software para el Gamecube o para el PSP ya que el compilador es el mismo, sólo debes usar el template respectivo.