Bienvenido(a), Visitante. Por favor, ingresa o regístrate.

Ingresar con nombre de usuario, contraseña y duración de la sesión
 

Autor Hilo: TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY (Leído 24945 veces)

pocket_lucho

  • T-500
  • Mensajes: 1 117
INTRODUCCION

A raíz de la reciente Bitbitjam que se hizo en Junio y gracias a una de las entradas del concurso, tomé conciencia de que existía 'algo' con el que poder programar la Game Boy (conocida por cierto en su fase prototipo como DMG o Dot Matrix Game). Como el código fuente estaba disponible, me animé a darle un vistazo esperando que fuera en terrible ensamblador pero para mi sorpresa... ¡estaba en el amigable y sencillo C! Buscando información encontré que este juego se había escrito usando el GameBoy Developer's Kit (GBDK) de Michael Hope.

Este kit se compone de:

    Un compilador ANSI C.
    Un ensamblador.
    Un optimizador.
    Un linker para producir las roms de GameBoy.
    Soporte de multiples bancos de memoria.
    Un juego de librerias en ensamblador, incluido su fuente.
    Ejemplos en C y ensamblador.

La puñeta es que este kit no se actualiza desde el 2001... una pena porque funciona realmente bien y solo se le hecha en falta algunos detallitos para ser perfecto, así que toca conformarse con lo que hay que no es poco. Estos tutoriales se van a centrar en la consola original, pero eso no quita que este kit soporte también la GB COLOR y en algún tutorial se enseñará a darle soporte.


REQUISITOS

Vamos a distinguir requisitos de hardware, software y de conocimientos.

Evidentemente necesitaremos un ordenador PC, no hace falta que sea moderno. Para probar las roms sería interesante tener una GAMEBOY y un cartucho flash para quemar las roms. Como consola recomiendo la GB COLOR porque es la que mejor pantalla tiene aunque, por otro lado, es fácil de encontrar un clon chino llamado GB BOY COLOR, que además de incluir 66 juegos en memoria, su pantalla en retroiluminada y sale por unos 23 € en casa, en EBAY las tenéis.

https://www.youtube.com/watch?v=b7X4LTEchos

Como flash recomiendo el aparecido este año 2014, EVERDRIVE de Krizz (http://krikzz.com/index.php?route=product/product&product_id=60), una autentica maravilla de cacharrito y que lo podeis comprar en España (http://www.videojuegoshoracio.com/ por ejemplo).

El kit y herramientas que usaremos en los tutoriales funcionan sobre Windows, yo voy a trabajar sobre XP virtualizado. ¿Eso que es? Pues si sois usuarios de Linux, OSX o cosas más extrañas aún, podéis usar un programa gratuito llamado Virtualbox, que os permitirá 'emular' un sistema operativo sobre otro. Aquí os dejo un video de como instalarlo:

https://www.youtube.com/watch?v=-jFU-Zq7G1E

Conocimientos... tema espinoso, en principio debéis saber lenguaje C. Tampoco es que tengáis un nivel de maestro informático a lo Carmack, con saber lo que es una variable, constante, función, instrucciones lógicas como IF, FOR, WHILE... bastaría. Es de los lenguajes más sencillos que hay y se usa como introducción a la programación, así que nunca está de más aprenderlo. Os dejo otro tutorial para que le deis un vistazo, en serio, no es difícil (http://www.elrincondelc.com/cursoc/cursoc.html).

En la carpeta DOC del paquete del kit que os pongo en el siguiente apartado, hay varios textos, incluidos el oficial de Nintendo de 300 páginas, pero en concreto os recomiendo el pandocs.txt que seria interesante que lo imprimieseis para tenerlo a mano.


TUTORIAL 1: HOLA MUNDO
http://www.fasebonus.net/foro/index.php?topic=36662.msg59470#msg59470


TUTORIAL 2: CONTROL DEL PAD
http://www.fasebonus.net/foro/index.php?topic=36662.msg59475#msg59475


TUTORIAL 3: SPRITES
http://www.fasebonus.net/foro/index.php?topic=36662.msg59838#msg59838


TUTORIAL 4: FONDOS (I)
http://www.fasebonus.net/foro/index.php?topic=36662.msg60134#msg60134


TUTORIAL 5: FONDOS (II)
http://www.fasebonus.net/foro/index.php?topic=36662.msg60387#msg60387


TUTORIAL 6: SONIDO
http://www.fasebonus.net/foro/index.php?topic=36662.msg60626#msg60626



ENLACES INTERESANTES
Podemos encontrar más tutoriales sobre GB en varios sitios de la red:

- Tutoriales de Darkryoga sobre GBDK en C:
http://www.elotrolado.net/hilo_desarrollo-software-proyectos-de-darkryoga_1901847_s100

- Tutoriales de xzakox en ensamblador:
http://wiki.ladecadence.net/doku.php?id=tutorial_de_ensamblador

- Ejemplos de GBDK en C de Retroisle:
http://www.retroisle.com/others/nintendogameboy/Technical/Firmware/dev.php


INDICE DE LOS TUTORIALES
En principio, el plan de capítulos será el siguiente:

1.- Hola Mundo
2.- Controles
3.- Sprites
4.- Backgrounds (I)
5.- Backgrounds (II)
6.- Sonido

7.- Juego ejemplo (I)
8.- Juego ejemplo (II)

Si tenéis dudas o sugerencias para otros capítulos por favor comentarlos en el hilo.


Vídeo grabado del taller de GB del RetroConsolas Alicante... http://vertice.cpd.ua.es/126068

El material en PDF lo tenéis aquí http://tinyurl.com/o4eesw6













última modificación: 01 Noviembre 2014, 11:19:43 por pocket_lucho

pocket_lucho

  • T-500
  • Mensajes: 1 117

TUTORIAL 1: INSTALACIÓN DEL ENTORNO - HOLA MUNDO


Nos podemos descargar el kit desde su web http://gbdk.sourceforge.net/ aunque yo os he creado este paquete con algunos extras que podéis descargar de aquí (https://dl.dropboxusercontent.com/u/33369593/gbdk.rar).

Simplemente lo descomprimís en C:\ y listo. Os debe quedar algo así c:\GBDK\BIN, c:\GBDK\DOC, c:\GBDK\EXAMPLES, etc.



Ahora sería interesante modificar el PATH. Para lo cual hemos de acceder a la ventana de "Propiedades del sistema" y una vez ahí nos encontraremos el botón "Variables del sistema" en la pestaña de "Opciones avanzadas". Allí buscamos "PATH" y añadimos al final "c:\GBDK" (tiene que haber el signo ";" de separación con la anterior, por ejemplo, c:\mingw\bin;c:\GBDK\bin). Si vamos a usar otra ruta diferente, pues es aquí donde debemos ponerla, procurar no usar carpetas raras con espacios como el Escritorio, etc. Incluso si queremos podríamos pasar de este paso, pero tendremos que poner la ruta completa más tarde cuando vayamos a compilar nuestro programa.



Y listo, ¡ya podemos crear roms para la consola! Vamos a empezar con lo más básico, el clásico Hola Mundo. Acudimos a la carpeta "Examples" y creamos una llamada "01_hola_mundo".

Abrimos el editor de textos que más os guste y escribimos (yo uso CodeBlocks porque te marca con colores la sintaxis de C) en un fichero llamado main.c lo siguiente:

Citar
#include <gb/gb.h>

Esto nos enlazaría a la librería del kit GBDK.

Citar
#include <stdio.h>

Lo mismo a las funciones básicas de Entrada/salida que vienen con el kit, para mostrar texto en pantalla en nuestro caso.

Citar
void main(){

Creamos la función Main, que es el punto de entrada a nuestro programa.

Citar
printf("HOLA MUNDO");

Escribimos nuestro texto con la función de C printf.

Citar
while(1)
;

Creamos un bucle infinito donde no hacemos nada para no alcanzar el final del programa, en un ordenador saldríamos el Sistema Operativo pero en una consola se resetearía.

Citar
}

Y cerramos la función Main. ¿A que no ha sido nada difícil? Nos queda el último paso, compilar este código y crear la rom para la consola. El código completo quedaría de esta forma:

Código: [Seleccionar]
#include <gb/gb.h>
#include <stdio.h>

void main(){

    printf("HOLA MUNDO");

    while(1)
    ;
}

Creamos un fichero compile.bat y escribimos:

Citar
lcc -o rom.gb main.c

Mediante el compilador "lcc" crea el objeto (-o) del fichero main.c y genera el fichero de salida rom.gb. Si no habéis modificado el PATH antes, deberéis poner la ruta completa del "lcc" (c:\gbdk\bin\lcc).

Citar
pause

Pausamos la ejecución para ver si ha habido errores hasta que se pulse una tecla, se puede quitar si queréis.
Citar
bgb.exe C:\gbdk\examples\01_hola_mundo\rom.gb

Ejecutamos la rom en el emulador BGB que viene con el paquete que os he incluido en el tutorial, modificad la ruta de esta linea si habéis instalado el entorno en otro sitio. Este emulador está muy bien porque es de los más fieles y trae unas opciones de depuración de primer nivel, también he incluido el NO$GMB si os gusta más, ambos funcionan en VirtualBox. Si tenemos un cartucho flash podremos 'quemar' la rom y probarla en la consola que mostraría lo siguiente:



En la carpeta EXAMPLES podréis ver que tenéis el tutorial ya escrito por si no os aclaráis.


DEBERES

Si, la idea es que tengáis que hacer deberes para afianzar conocimientos. En este tutorial con lograr configurar bien y lograr una rom ya es suficiente. También estaría bien que dierais un vistazo a los ejemplos que trae la librería (carpeta "EXAMPLES/GB"), leyerais los documentos de la carpeta "DOCS" (sobretodo gbdk-doc.pdf y pandocs.txt) o aprender/refrescar el lenguaje C ya que no es el objetivo de estos tutoriales aunque yo intentaré primar la sencillez de la sintaxis frente a la limpieza o eficiencia ;)

última modificación: 19 Septiembre 2014, 07:54:19 por pocket_lucho

Balthier

  • T-70
  • Mensajes: 100
Yo ya sigo el de DarkRyoga, pero también seguiré este. Mas vale que sobre que que falte xD
"...7 secrets, 7 sins, this is where the end begins..."

pocket_lucho

  • T-500
  • Mensajes: 1 117


TUTORIAL 2: CONTROL DEL PAD

En este tutorial nos vamos a centrar en algo fundamental para un juego como sería la lectura de la pulsación de los botones. Como podréis comprobar, se hace de forma muy sencilla ;)

Como en el anterior tutorial, creamos la carpeta "02_pad" en "C:\gbdk\examples" y dentro de esta los ficheros "main.c" y "compile.bat".

Empezamos con el main.c:

Citar
#include <gb/gb.h>

Enlazamos a la librería del kit GBDK, esto de aquí en adelante lo haremos siempre.

Citar
#include <gb/drawing.h>

Enlazamos a unas rutinas muy interesantes del kit que nos permiten desde dibujar texto, formas geometricas, imagenes...

Citar
void main(){

Creamos la función Main, que es el punto de entrada a nuestro programa, esto tampoco lo volveré a comentar en el futuro.

Citar
UBYTE keys = 0;

Cremos una varible unsigned byte (que podrá contener valores de 0 a 255) donde guardaremos las lecturas de los botones.

Citar
gotogxy(1, 1);
gprintf("GAMEBOY PAD TEST");

Gracias a las funciones de drawing.h, podemos usar unas funciones de texto más potentes que incluso nos permiten situarnos en posiciones especificas de la pantalla.

Código: [Seleccionar]
    gotogxy(1, 1);
    gprintf("GAMEBOY PAD TEST");
    gotogxy(1, 2);
    gprintf("----------------");

    gotogxy(1, 4);
    gprintf("Start : 0");
    gotogxy(1, 5);
    gprintf("Select: 0");
    gotogxy(1, 6);
    gprintf("Up    : 0");
    gotogxy(1, 7);
    gprintf("Down  : 0");
    gotogxy(1, 8);
    gprintf("Left  : 0");
    gotogxy(1, 9);
    gprintf("Right : 0");
    gotogxy(1, 10);
    gprintf("A     : 0");
    gotogxy(1, 11);
    gprintf("B     : 0");

Dibujamos el texto que nos indicará si se ha pulsado un botón en concreto.

Citar
while(1){

Otra vez creamos un bucle infinito, recordad que no debemos llegar al final del programa NUNCA.

Citar
wait_vbl_done();

Aquí llegamos a algo interesante, básicamente sincronizamos con el blanqueo vertical... ¿y eso en cristiano que quiere decir? ¿Os suena lo de los 60 fps en los juegos? Con esto hay que remontarse a los tiempos de las televisiones de tubo. Un haz de electrones iba dibujando la imagen linea a linea, de arriba a abajo, hasta llegar abajo y así otra vez... hasta hacerlo 60 veces por segundo en una televisión NTSC y 50 en una PAL, básicamente porque tenía más lineas que dibujar. Lo que hace esta instrucción, es esperarse hasta que se haya dibujado la imagen completa, bloqueándonos voluntariamente para que nuestro código se ejecute 60 veces por segundo. ¿Recordáis que pasaba en juegos de PC muy antiguos que al pasar de un 286 a 386 por ejemplo se hacían injugables por su aumento de velocidad? Pues esto era porque no sincronizaban su tasa de frames con el refresco de la pantalla. En GAME BOY toma más relevancia aún porque, si habéis leído la documentación como os puse de deberes... sabréis que mientras el controlador del LCD está trabajando, no es posible acceder a la memoria de vídeo de la consola (VRAM), por lo que para acceder a esta para cargar o modificar datos (sprites, tiles, fondos...) hay que esperar a que termine el dibujado en el LCD. Todas esas operaciones ES OBLIGATORIO hacerlas DESPUÉS de "wait_vbl_done();". Disponemos de un tiempo limitado antes de que vuelva a empezar el dibujado del LCD, si nos excedemos, bajaremos de esos 60 fps, ¡así que ojo con lo que ponemos aquí!

Citar
keys = joypad();

Usamos esta función de las GBDK para leer el estado de los botones y guardar el resultado en la variable que creamos al principio. Aunque he colocado estas instrucciones detrás de "wait_vbl_done();", no sería necesario porque no acceden a VRAM, podrían ponerse delante y no pasar nada.

Código: [Seleccionar]
    if( keys & (J_START)){
        gotogxy(9, 4);
        gprintf("1");
    }
    else{
        gotogxy(9, 4);
        gprintf("0");
    }

Ahora simplemente comprobamos los valores obtenidos con las constantes de los botones definidas en la librería, que son:

J_START
J_SELECT
J_B
J_A
J_DOWN
J_UP
J_LEFT
J_RIGHT


Código: [Seleccionar]
    if( keys & (J_SELECT)){
        gotogxy(9, 5);
        gprintf("1");
    }
    else{
        gotogxy(9, 5);
        gprintf("0");
    }

    if( keys & (J_UP)){
        gotogxy(9, 6);
        gprintf("1");
    }
    else{
        gotogxy(9, 6);
        gprintf("0");
    }

    if( keys & (J_DOWN)){
        gotogxy(9, 7);
        gprintf("1");
    }
    else{
        gotogxy(9, 7);
        gprintf("0");
    }

    if( keys & (J_LEFT)){
        gotogxy(9, 8);
        gprintf("1");
    }
    else{
        gotogxy(9, 8);
        gprintf("0");
    }


    if( keys & (J_RIGHT)){
        gotogxy(9, 9);
        gprintf("1");
    }
    else{
        gotogxy(9, 9);
        gprintf("0");
    }

    if( keys & (J_A)){
        gotogxy(9, 10);
        gprintf("1");
    }
    else{
        gotogxy(9, 10);
        gprintf("0");
    }

    if( keys & (J_B)){
        gotogxy(9, 11);
        gprintf("1");
    }
    else{
        gotogxy(9, 11);
        gprintf("0");
    }

Repetimos para el resto de botones y ya hemos terminado. Para abreviar podríamos crear un #define al principio del código juntando "gotogxy" con "gprintf" y haciendo la llamada de esta forma:

Código: [Seleccionar]
#define gprintf_XY(str,x,y);  gotogxy(x, y);  gprintf(str);

gprintf_XY(( keys & (J_LEFT)) ? "1" : "0", 9, 8);

El código completo quedaría de la siguiente forma:

Código: [Seleccionar]
#include <gb/gb.h>
#include <gb/drawing.h>

void main(){

    UBYTE keys = 0;

    gotogxy(1, 1);
    gprintf("GAMEBOY PAD TEST");
    gotogxy(1, 2);
    gprintf("----------------");

    gotogxy(1, 4);
    gprintf("Start : 0");
    gotogxy(1, 5);
    gprintf("Select: 0");
    gotogxy(1, 6);
    gprintf("Up    : 0");
    gotogxy(1, 7);
    gprintf("Down  : 0");
    gotogxy(1, 8);
    gprintf("Left  : 0");
    gotogxy(1, 9);
    gprintf("Right : 0");
    gotogxy(1, 10);
    gprintf("A     : 0");
    gotogxy(1, 11);
    gprintf("B     : 0");


    while(1){

        // sincroniza con el blanqueo vertical para dibujar los graficos y pone los contadores (timers)
wait_vbl_done();

// lee el pad
keys = joypad();

// si se pulsa start
if( keys & (J_START)){
            gotogxy(9, 4);
            gprintf("1");
}
else{
            gotogxy(9, 4);
            gprintf("0");
}

// ETC...
        if( keys & (J_SELECT)){
            gotogxy(9, 5);
            gprintf("1");
}
else{
            gotogxy(9, 5);
            gprintf("0");
}

if( keys & (J_UP)){
            gotogxy(9, 6);
            gprintf("1");
}
else{
            gotogxy(9, 6);
            gprintf("0");
}

        if( keys & (J_DOWN)){
            gotogxy(9, 7);
            gprintf("1");
}
else{
            gotogxy(9, 7);
            gprintf("0");
}

if( keys & (J_LEFT)){
            gotogxy(9, 8);
            gprintf("1");
}
else{
            gotogxy(9, 8);
            gprintf("0");
}

if( keys & (J_RIGHT)){
            gotogxy(9, 9);
            gprintf("1");
}
else{
            gotogxy(9, 9);
            gprintf("0");
}

if( keys & (J_A)){
            gotogxy(9, 10);
            gprintf("1");
}
else{
            gotogxy(9, 10);
            gprintf("0");
}

if( keys & (J_B)){
            gotogxy(9, 11);
            gprintf("1");
}
else{
            gotogxy(9, 11);
            gprintf("0");
}
    }
}

Ahora como en el tutorial anterior, abrimos el fichero compile.bat y escribimos lo mismo.

Citar
lcc -o rom.gb main.c
pause
bgb.exe rom.gb

Y ya tenemos la rom lista para grabarla en nuestro flash y comprobar el resultado.




DEBERES
Esta lección ha sido muy sencillita así que con que la entendais sobra. Lo que si os pido es que os leais las secciones "1.0 Important Notes" y "1.5 Sprites" del fichero "gbdok.txt" que está dentro de la carpeta DOC ya que son las funciones que usaremos en el próximo tutorial sobre sprites. Tambien seria interesante que fuerais a la carpeta "include\gb" y vierais los prototipos de las funciones contenidos en "drawing.h". Puede que alguna os resulte de utilidad, pero yo no las voy a usar en los tutoriales porque no me parecen interesantes dentro de un juego por su forma de trabajar, utilizando la VRAM completa simulando un FRAMEBUFFER.
última modificación: 19 Septiembre 2014, 07:54:34 por pocket_lucho

Uguru

  • Humano
  • Mensajes: 2

Ino

  • T-70
  • Mensajes: 108
Ole ole ole ole.
Espero seguir el tutorías y así volver a recordar la programación en C q hace mucho q no la toco.
Muchas gracias por el curro q te estas pegando.

Saludos.   


Enviado desde mi iPhone con Tapatalk

Vakapp

  • T-7T
  • Mensajes: 381
Ole ahi ese tutorial....yo porque soy un negao y conseguiria un pantallazo verde cone l hola mundo...que sino lo intentaba... XD...muchas gracias

karkayu

  • T-1
  • Mensajes: 50
  • Autentico y genuino 'Luser'
    • PNOID
PNOID para ZX Spectrum: http://pnoid.jaimeweb.es/

Victor

  • Humano
  • Mensajes: 14
Bug chorra
All usar el emulador BGB que ha puesto en el paquete y pulsar 1 y 2,  se activan a la vez Select + Left y Select + Right

Eso es porque el emu tiene varios pads definidos.  Hay que hacer Click derecho,  opciones y desasignarlos

xzakox

  • Humano
  • Mensajes: 1
Buenas! Acabo de llegar al foro por referencias, muy interesante todo.
Me encanta ver que la gente se tira a divulgar y a hacer cosas sobre la pequeña de nintendo  :D
Comentar que si alguien se queda con ganas de más y tirarse a lo "hardcore", podeis echar un vistazo a mi tutorial de ensamblador para gameboy:
http://wiki.ladecadence.net/doku.php?id=tutorial_de_ensamblador
Aunque no querais meteros con ASM, tiene bastante documentación sobre las interioridades de la gameboy, puede seros de ayuda.
Un saludo, nos veremos por aqui  :)
última modificación: 13 Septiembre 2014, 13:09:35 por xzakox

nolddor

  • Humano
  • Mensajes: 3
Muchas gracias por el tutorial,...

a la segunda vez que he tenido q escribir goto y gprintf no he podido evitarlo... vaya coñazo xDD


Citar
#define gprintf_XY(str,x,y);  gotogxy(x, y);  gprintf(str);

La semana que viene más!!
última modificación: 13 Septiembre 2014, 15:56:33 por nolddor

karkayu

  • T-1
  • Mensajes: 50
  • Autentico y genuino 'Luser'
    • PNOID
Buenas! Acabo de llegar al foro por referencias, muy interesante todo.
Me encanta ver que la gente se tira a divulgar y a hacer cosas sobre la pequeña de nintendo  :D
Comentar que si alguien se queda con ganas de más y tirarse a lo "hardcore", podeis echar un vistazo a mi tutorial de ensamblador para gameboy:
http://wiki.ladecadence.net/doku.php?id=tutorial_de_ensamblador
Aunque no querais meteros con ASM, tiene bastante documentación sobre las interioridades de la gameboy, puede seros de ayuda.
Un saludo, nos veremos por aqui  :)

Muy buena documentación. Totalmente recomendable.
Yo ya la conocía. Supongo que la pusiste alguna vez en GP32Spain.
PNOID para ZX Spectrum: http://pnoid.jaimeweb.es/

Victor

  • Humano
  • Mensajes: 14
Buenas! Acabo de llegar al foro por referencias, muy interesante todo.
Me encanta ver que la gente se tira a divulgar y a hacer cosas sobre la pequeña de nintendo  :D
Comentar que si alguien se queda con ganas de más y tirarse a lo "hardcore", podeis echar un vistazo a mi tutorial de ensamblador para gameboy:
http://wiki.ladecadence.net/doku.php?id=tutorial_de_ensamblador
Aunque no querais meteros con ASM, tiene bastante documentación sobre las interioridades de la gameboy, puede seros de ayuda.
Un saludo, nos veremos por aqui  :)

Muy práctico. Me ha venido muy bien lo de la organización de la ROM y los bancos de memoria. A primera vista diría que es igual que en un Spectrum de 128KB, dónde hay que ir rotando las páginas de 16KB...

pocket_lucho

  • T-500
  • Mensajes: 1 117
Muchas gracias por el aporte! Me lo miraré tb! Si, es cierto lo de los bancos (no eran de 32 kbs menos el primero que es de 16?) y en el proximo tutorial lo usaremos.

josepzin

  • T-90
  • Mensajes: 1 224
  • Habitacus!
    • Mi blog
Muy buen aporte, no creo que lo use para Gameboy pero me va a venir bien por los concejos de C.