Foro Fase Bonus

Videojuegos => Homebrew => Mensaje iniciado por: pocket_lucho en 12 Septiembre 2014, 19:08:56

Título: TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 12 Septiembre 2014, 19:08:56
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 (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 (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/ (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (http://vertice.cpd.ua.es/126068)

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













Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 12 Septiembre 2014, 19:49:28

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 (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.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/cap0.png)

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.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt01.png)

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:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/bgb00001.bmp)

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 ;)

Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Balthier en 12 Septiembre 2014, 20:36:50
Yo ya sigo el de DarkRyoga, pero también seguiré este. Mas vale que sobre que que falte xD
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 12 Septiembre 2014, 21:00:48


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.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/bgb00002.bmp)


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.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Uguru en 12 Septiembre 2014, 23:47:33
Me ha encantado, sigue así estoy ansioso de más entregas
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Ino en 13 Septiembre 2014, 01:03:58
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
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Vakapp en 13 Septiembre 2014, 07:58:03
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
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: karkayu en 13 Septiembre 2014, 12:07:45
Muy interesante el tutorial.
Aquí tienes otro seguidor ;)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Victor en 13 Septiembre 2014, 12:08:05
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
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: xzakox en 13 Septiembre 2014, 13:05:36
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 (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  :)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: nolddor en 13 Septiembre 2014, 15:50:04
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!!
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: karkayu en 13 Septiembre 2014, 17:10:30
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 (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.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Victor en 13 Septiembre 2014, 18:19:09
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 (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...
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 13 Septiembre 2014, 20:19:25
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.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: josepzin en 13 Septiembre 2014, 21:09:56
Muy buen aporte, no creo que lo use para Gameboy pero me va a venir bien por los concejos de C.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: seiyouh en 13 Septiembre 2014, 21:51:43
Lo mio no es la programación pero
cuando llegues al 3º punto me veras por aqui

Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Davidian en 14 Septiembre 2014, 10:38:16
¡Grande Lucho!

De las pruebas que hemos estado haciendo ya tenemos sonando la máquina y bastante bien por cierto.

A ver si llego a tiempo de hacer algún ejemplo para la parte del sonido ;)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 14 Septiembre 2014, 12:36:14
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!!

Jajajaja, es verdad, por ejemplo en vez de tanto if/else se debería hacer "gprintf( ( keys & (J_START)) ? "1" : "0");" para acortar... O incluso se podría hacer todo eso en un for o una función... pero la idea es que estos tutos sean para gente con conocimientos MINIMOS de C, el que ya controle lo verá, lo hará a su manera más elegante y se buscará la vida para programar el cacharrito... Para los próximos usaré para meter código la etiqueta CODIGO en vez de CITA por el tema de la identación y las llaves, estos primeros como eran muy sencillos los he hecho así pq se vee algo mejor para mi gusto ;)

Lo dicho, no dejéis de añadir vuestros comentarios sobre el código para que sirva de ayuda a los demás, mi tiempo es el que es y hago lo que puedo xD
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Victor en 14 Septiembre 2014, 15:16:48
Pues ya que lo dices... He encontrado unos cuantos ejemplos más en retroisle:
http://www.retroisle.com/others/nintendogameboy/Technical/Firmware/dev.php (http://www.retroisle.com/others/nintendogameboy/Technical/Firmware/dev.php)

También he localizado el GB Development Studio que mencionan en ese tuto, pero desde mi punto de vista no merece mucho la pena. Lo pongo por si alguien quiere darle un ojo. El BMP2GB digo yo que será útil, pero como no se que otras cosas existen, lo mismo haya algo mejor (png2gb por ejemplo)...
http://www.semis.demon.co.uk/Apps/gbdev063.zip (http://www.semis.demon.co.uk/Apps/gbdev063.zip)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 14 Septiembre 2014, 21:37:21
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 (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 buenos tutoriales en ensamblador si señor! Y todo muy bien explicado, si señor ;) Ya se donde ir cuando busque optimizar jejeje
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 14 Septiembre 2014, 22:20:52
Pues ya que lo dices... He encontrado unos cuantos ejemplos más en retroisle:
http://www.retroisle.com/others/nintendogameboy/Technical/Firmware/dev.php (http://www.retroisle.com/others/nintendogameboy/Technical/Firmware/dev.php)

También he localizado el GB Development Studio que mencionan en ese tuto, pero desde mi punto de vista no merece mucho la pena. Lo pongo por si alguien quiere darle un ojo. El BMP2GB digo yo que será útil, pero como no se que otras cosas existen, lo mismo haya algo mejor (png2gb por ejemplo)...
http://www.semis.demon.co.uk/Apps/gbdev063.zip (http://www.semis.demon.co.uk/Apps/gbdev063.zip)

Pues muchas gracias, hay tutos ahi tb interesantes! Yo como conversor para imagenes uso este online http://www.chrisantonellis.com/gameboy/gbtdg/, (http://www.chrisantonellis.com/gameboy/gbtdg/,) para crear tiles el GBTD y para mapas el GBMB, pero vamos, que los iremos viendo en los proximos tutos ;)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Bubu en 14 Septiembre 2014, 22:54:32
Grandioso, pocket_lucho. Esto me recuerda años ha, cuando chiquetito, que me dio por pogramar en ensamblador en la GB color, jiji. Me resultó sencillo porque al ser un Z80 tenía el mismo micro que el Spectrum ;-) ¡¡pero con sprites!!


Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Victor en 16 Septiembre 2014, 09:45:33
Tetris para GB en GBDK y C. Fuentes y Compilado. También hay un tuto explicando uno de los ejemplos que vienenn de series en el GBDK:
http://forums.tigsource.com/index.php?topic=10848.msg345959#msg345959 (http://forums.tigsource.com/index.php?topic=10848.msg345959#msg345959)

Hay fuentes de un Scroller también, pero está en assembler.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 19 Septiembre 2014, 07:49:15
TUTORIAL 3: SPRITES

Para la Game Boy, un sprite es una imagen de 8x8 u 8x16 pixels que se puede mover por la pantalla de forma independiente al fondo y a otros sprites. La consola presenta ciertas limitaciones además del tamaño, solo puede haber 40 sprites en pantalla y como mucho 10 en la misma linea horizontal (scanline) o se producirá parpadeo (flicker). Además, dentro de que la consola solo trabaja con 4 colores (Blanco, Negro, Gris claro y Gris oscuro), se puede usar 2 paletas de 4 colores para los sprites (siendo el primero el transparente). Para la Game Boy COLOR, estás limitaciones varían ligeramente, por ejemplo, poseemos 8 paletas de 4 colores para los sprites.

Ahora que ya sabemos esto, podemos pasar a dibujar los tiles que formaran nuestros sprites (imagenes de 8x8 pixels). Un sprite de 8x8 pixels usará un tile y otro de 8x16 pues usará dos. Para crear nuestros tiles usaremos el programa de Harry Mulder incluido en la carpeta TOOLS llamado GBTD (Game Boy Tile Designer). El programa es muy sencillo de usar, contiene las típicas herramientas de lápiz, cubo de pintura, espejados, etc.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/cpa02.png)

De todas formas, siempre podéis dibujar vuestros tiles en cualquier programa de dibujo, copiar en el portapapeles y pegarlos en el GBTD. Siempre que respetéis esta paleta que os enseño no habrá problema al importar.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/gbtd_colors.bmp)

Cuando tengamos nuestros tiles listos, deberemos exportarlos. Para ello, vamos al menu "FILE->EXPORT TO". En "TYPE" elegimos "GBDK C FILE" y en en "FILENAME", pues la ruta donde vayamos a escribir nuestro código, por ejemplo "C:\gbdk\examples\03_sprites_A". La sección de "SETTINGS" debereis elegir el nombre al que le vamos a poner al vector de salida, la cantidad de tiles a guardar (en mi caso de 0 a 3), el formato de "GAME BOY 4 COLOR" y que se exporten los tiles como una unidad.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/cap03.png)

Si abrimos el fichero "export.c" creado, podremos ver el resultado de nuestros tiles convertidos:

Código: [Seleccionar]
unsigned char tile_data[] =
{
  0xFF,0xFF,0x81,0xFF,0x8D,0xF3,0xBD,0xC3,
  0x8D,0xF3,0x8D,0xF3,0x81,0xFF,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xBD,0xC3,0x8D,0xF3,
  0xB1,0xCF,0xBD,0xC3,0x81,0xFF,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xBD,0xC3,0x8D,0xF3,
  0x9D,0xE3,0x8D,0xF3,0xBD,0xC3,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xAD,0xD3,0xBD,0xC3,
  0x8D,0xF3,0x8D,0xF3,0x81,0xFF,0xFF,0xFF
};

Recordad siempre añadir "CONST" delante de todo para asegurarnos el compilador mete este vector en ROM y no en RAM.

Una vez que ya tenemos los tiles, podemos empezar con nuestro "main.c", en mi caso, en la carpeta "C:\gbdk\examples\03_sprites_A"

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

// los tiles que usaran los sprites
const unsigned char tile_data[] =
{
  0xFF,0xFF,0x81,0xFF,0x8D,0xF3,0xBD,0xC3,
  0x8D,0xF3,0x8D,0xF3,0x81,0xFF,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xBD,0xC3,0x8D,0xF3,
  0xB1,0xCF,0xBD,0xC3,0x81,0xFF,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xBD,0xC3,0x8D,0xF3,
  0x9D,0xE3,0x8D,0xF3,0xBD,0xC3,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xAD,0xD3,0xBD,0xC3,
  0x8D,0xF3,0x8D,0xF3,0x81,0xFF,0xFF,0xFF
};

//////////////////////////////////////////////////////
// punto de entrada
//////////////////////////////////////////////////////
void main(){

    // modo de sprites a 8x8 pixels
    SPRITES_8x8;

Elegimos el tamaño de sprites de 8x8, no se pueden mezclar, todos deben ser del mismo tamaño (8x8 u 8x16).

Citar
    // carga los tiles de los sprites, posicion, cantidad de tiles y los tiles
    set_sprite_data( 0, 4, tile_data);

Cargamos en VRAM los tiles de los sprites especificando posición en memoria, la cantidad de tiles y el vector de los tiles. Podemos almacenar hasta 256 tiles para los sprites, hay que tener en cuenta que la zona de memoria de 128 a 255 es compartida con la memoria del fondo, lo veremos en detalle cuando lleguemos a estos.

Citar
    // asigna a cada sprite un tile, sprite (0-39), posicion del tile
    set_sprite_tile( 0, 0 );
    set_sprite_tile( 1, 1 );
    set_sprite_tile( 2, 2 );
    set_sprite_tile( 3, 3 );

Asignamos a un sprite un tile, especificando el número de sprite (0-39) y la posición en VRAM del tile (0-255)

Citar
    // mueve el sprite a la posicion x, y
    move_sprite( 0, 20, 20 );
    move_sprite( 1, 28, 20 );
    move_sprite( 2, 36, 20 );
    move_sprite( 3, 44, 20 );

Movemos los sprites a una posición de la pantalla, especificando el número de sprite (0-39) y la coordenada X/Y (la pantalla de la consola es de 160x144 pixels).

Citar
    // muestra los sprites
    SHOW_SPRITES;

    while(1)    ;
}

Por último mostramos los sprites y entramos en un bucle infinito. El código completo quedaría así:

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

const unsigned char tile_data[] =
{
  0xFF,0xFF,0x81,0xFF,0x8D,0xF3,0xBD,0xC3,
  0x8D,0xF3,0x8D,0xF3,0x81,0xFF,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xBD,0xC3,0x8D,0xF3,
  0xB1,0xCF,0xBD,0xC3,0x81,0xFF,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xBD,0xC3,0x8D,0xF3,
  0x9D,0xE3,0x8D,0xF3,0xBD,0xC3,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xAD,0xD3,0xBD,0xC3,
  0x8D,0xF3,0x8D,0xF3,0x81,0xFF,0xFF,0xFF
};


//////////////////////////////////////////////////////
// punto de entrada
//////////////////////////////////////////////////////
void main(){

    // modo de sprites a 8x8 pixels
    SPRITES_8x8;

    // carga los tiles de los sprites, posicion, cantidad de tiles y los tiles
    set_sprite_data( 0, 4, tile_data);

    // asigna a cada sprite un tile, sprite (0-39), posicion del tile
    set_sprite_tile( 0, 0);
    set_sprite_tile( 1, 1);
    set_sprite_tile( 2, 2);
    set_sprite_tile( 3, 3);

    // mueve el sprite a la posicion x, y
    move_sprite( 0, 20, 20 );
    move_sprite( 1, 28, 20 );
    move_sprite( 2, 36, 20 );
    move_sprite( 3, 44, 20 );

    // muestra los sprites
    SHOW_SPRITES;

    while(1)    ;
}


Ya podríamos crear el "compile.bat" con el mismo texto de hasta ahora y obtener el siguiente resultado:

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

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/bgb00003.bmp)

COLOR

El siguiente paso que vamos a abarcar es darle color a nuestros sprites.

Primero añadiremos las paletas que vamos a utilizar, recordad que podemos cargar hasta 8 para los sprites.

Código: [Seleccionar]
const UWORD sprite_palette[] = {
RGB_RED, RGB_DARKRED, RGB_GREEN, RGB_DARKGREEN,
RGB_BLUE, RGB_DARKBLUE, RGB_YELLOW, RGB_DARKYELLOW,
RGB_CYAN, RGB_AQUA, RGB_PINK, RGB_PURPLE,
RGB_LIGHTGRAY, RGB_DARKGRAY, RGB_WHITE, RGB_LIGHTFLESH,
RGB_BLACK, RGB_BROWN, RGB_ORANGE, RGB_TEAL
};

En "include\cgb.h" tenéis la siguiente definición de los colores basados en la paleta por defecto EGA:

#define RGB_RED        RGB(31,  0,  0)
#define RGB_DARKRED    RGB(15,  0,  0)
#define RGB_GREEN      RGB( 0, 31,  0)
#define RGB_DARKGREEN  RGB( 0, 15,  0)
#define RGB_BLUE       RGB( 0,  0, 31)
#define RGB_DARKBLUE   RGB( 0,  0, 15)
#define RGB_YELLOW     RGB(31, 31,  0)
#define RGB_DARKYELLOW RGB(21, 21,  0)
#define RGB_CYAN       RGB( 0, 31, 31)
#define RGB_AQUA       RGB(28,  5, 22)
#define RGB_PINK       RGB(11,  0, 31)
#define RGB_PURPLE     RGB(21,  0, 21)
#define RGB_BLACK      RGB( 0,  0,  0)
#define RGB_DARKGRAY   RGB(10, 10, 10)
#define RGB_LIGHTGRAY  RGB(21, 21, 21)
#define RGB_WHITE      RGB(31, 31, 31)

#define RGB_LIGHTFLESH RGB(30, 20, 15)
#define RGB_BROWN      RGB(10, 10,  0)
#define RGB_ORANGE     RGB(30, 20,  0)
#define RGB_TEAL       RGB(15, 15,  0)

Ya dentro de nuestro "main.c" colocamos el código siguiente:

Código: [Seleccionar]
    if( _cpu == CGB_TYPE ){

         // carga las paletas de los sprites, paleta inicial, numero de paletas a cargar y datos
        set_sprite_palette( 0, 4, &sprite_palette[0] );

        //  carga la paleta de cada sprite (numero de sprite, numero de paleta)
        set_sprite_prop( 0, 0 );
        set_sprite_prop( 1, 1 );
        set_sprite_prop( 2, 2 );
        set_sprite_prop( 3, 3 );
    }

Si detectamos que estamos en una Game Boy COLOR (CGB_TYPE), cargamos las paletas de los sprites y luego asignamos a cada sprite una paleta. Es recomendable hacer la comprobación para que nuestra rom sea 100% compatible con la Game Boy clásica. Con "set_sprite_prop" no solo podemos elegir la paleta, tambien podemos cambiar otras propiedades de los sprites como su espejado (flip) usando S_FLIPX (bit 6 a 1 -> 00100000 o 0x20U) o S_FLIPY (bit 7 a 1 -> 01000000 o 0x40U), su prioridad respecto al fondo con S_PRIORITY (bit 8 a 1 -> 10000000 o 0x80U) o en modo monocromo elegir entre las dos posibles paletas para los sprites, OBJ1PAL o OBJ0PAL. Hablando de paletas, por defecto, GBDK carga en modo Game Boy Clásica las paletas con la secuencia BLANCO, GRIS CLARO, GRIS OSCURO y NEGRO en las 3 paletas, podemos cambiar este orden haciendo:

Citar
BGP_REG = OBP0_REG = OBP1_REG = 0xE4U; // 0xE4U seria la normal -> 11100100, 0xFFU seria todo oscuro -> 11111111, etc.

Usando las opciones de debug de los emuladores incluidos podremos verlas.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/cap04.png)

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

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

const unsigned char tile_data[] =
{
  0xFF,0xFF,0x81,0xFF,0x8D,0xF3,0xBD,0xC3,
  0x8D,0xF3,0x8D,0xF3,0x81,0xFF,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xBD,0xC3,0x8D,0xF3,
  0xB1,0xCF,0xBD,0xC3,0x81,0xFF,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xBD,0xC3,0x8D,0xF3,
  0x9D,0xE3,0x8D,0xF3,0xBD,0xC3,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xAD,0xD3,0xBD,0xC3,
  0x8D,0xF3,0x8D,0xF3,0x81,0xFF,0xFF,0xFF
};


const UWORD sprite_palette[] = {
RGB_RED, RGB_DARKRED, RGB_GREEN, RGB_DARKGREEN,
RGB_BLUE, RGB_DARKBLUE, RGB_YELLOW, RGB_DARKYELLOW,
RGB_CYAN, RGB_AQUA, RGB_PINK, RGB_PURPLE,
RGB_LIGHTGRAY, RGB_DARKGRAY, RGB_WHITE, RGB_LIGHTFLESH,
RGB_BLACK, RGB_BROWN, RGB_ORANGE, RGB_TEAL
};


//////////////////////////////////////////////////////
// punto de entrada
//////////////////////////////////////////////////////
void main(){

    // modo de sprites a 8x8 pixels
    SPRITES_8x8;

    // carga los tiles de los sprites, posicion, cantidad de tiles y los tiles
    set_sprite_data( 0, 4, tile_data);

    // asigna a cada sprite un tile, sprite (0-39), posicion del tile
    set_sprite_tile( 0, 0);
    set_sprite_tile( 1, 1);
    set_sprite_tile( 2, 2);
    set_sprite_tile( 3, 3);

    if( _cpu == CGB_TYPE ){

         // carga las paletas de los sprites, paleta inicial, numero y datos
        set_sprite_palette( 0, 4, &sprite_palette[0] );

        //  carga la paleta de cada sprite (numero de sprite, numero de paleta)
        set_sprite_prop( 0, 0 );
        set_sprite_prop( 1, 1 );
        set_sprite_prop( 2, 2 );
        set_sprite_prop( 3, 3 );
    }

    // mueve el sprite a la posicion x, y
    move_sprite( 0, 20, 20 );
    move_sprite( 1, 28, 20 );
    move_sprite( 2, 36, 20 );
    move_sprite( 3, 44, 20 );

    // muestra los sprites
    SHOW_SPRITES;

    while(1)    ;
}

Por último debemos hacer un cambio más, en nuestro "compile.bat" debemos modificar la linea de comandos del "lcc".

Citar
lcc -Wl-yp0x143=0x80 -o rom.gb main.c
pause
bgb.exe rom.gb

Con esto hemos dado valor a 0x143 para que sea CGB-compatible (0x80). Ya podemos compilar la rom y obtener el siguiente resultado:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/bgb00004.bmp)


BANCOS

Como comenta xzakox en su tutorial de ensamblador: "la memoria principal de la gameboy, mapeada en un espacio de 16 bit, nos permite direccionar directamente 64K (2^16 = 65536). En este espacio de direcciones, tenemos que direccionar todos los bloques de memoria a los que la gameboy necesita acceder, esto es, la RAM, la ROM del cartucho, la RAM interna del cartucho para los juegos que graban partidas, la memoria de vídeo, etc. Para la ello los diseñadores de la GameBoy mapearon la memoria en diferentes bloques necesarios, como la RAM interna o la memoria de video, dejando dos bloques de 16K para el acceso a la ROM de los juegos, y un bloque de 8K para el acceso a la RAM de los juegos (partidas guardadas). Como muchos juegos empezaron a requerir mas de 32K de ROM o de 8K de RAM de guardado, se empezó a emplear una técnica denominada “Banking”, en la que la ROM del juego se divide en diversos bloques que se puedan independizar (los gráficos o sonidos de cada pantalla por ejemplo), que se van mapeando en el bloque de acceso a la memoria según sean necesarios. En la GameBoy, esto se diseñó de la siguiente manera; tenemos un bloque fijo de 16K(donde programamos la lógica principal del juego), y luego, mediante ciertas instrucciones (dependiendo del chip de mapping que usemos en nuestro cartucho), podemos ir intercambiando bancos de 16K en el otro bloque disponible."

Debido a esto, es necesario pensar en ir guardando todo lo que no sea la lógica del juego, en bancos de memoria diferentes al primero, para ello usaremos el mapper MBC1 soportado por las GBDK. En realidad no es tan complicado como suena.

Si recordais al principio cuando exportamos los tiles que dibujamos en GBTD, se nos creó un fichero llamado "export.c" que es donde estaba el vector de los tiles que copiamos en nuestro main. Lo que vamos a hacer es renombrarlo a "tiles.c" y compilarlo aparte del "main.c" para a la hora de generar la rom, poder elegir en que banco de memoria guardarlo.

Simplemente debemos modificar en "main.c" donde copiamos el contenido del vector de esto:

Código: [Seleccionar]
const unsigned char tile_data[] =
{
  0xFF,0xFF,0x81,0xFF,0x8D,0xF3,0xBD,0xC3,
  0x8D,0xF3,0x8D,0xF3,0x81,0xFF,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xBD,0xC3,0x8D,0xF3,
  0xB1,0xCF,0xBD,0xC3,0x81,0xFF,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xBD,0xC3,0x8D,0xF3,
  0x9D,0xE3,0x8D,0xF3,0xBD,0xC3,0xFF,0xFF,
  0xFF,0xFF,0x81,0xFF,0xAD,0xD3,0xBD,0xC3,
  0x8D,0xF3,0x8D,0xF3,0x81,0xFF,0xFF,0xFF
};

A esto:

Código: [Seleccionar]
extern const unsigned char tile_data[];

Y que justo antes de cargar estos tiles en VRAM, debemos especificar en que banco hemos de acceder con:

Código: [Seleccionar]
// saltamos al banco de memoria 2
SWITCH_ROM_MBC1(2);

set_sprite_data( 0, 4, tile_data );

El fichero "compile.bat" si que sufrirá más cambios .

Citar
lcc -c -o main.o main.c

Ahora solo creamos el objeto de main.c

Citar
lcc -Wf-bo2 -c -o  tiles.o tiles.c

Creamos el objeto de tiles.c especificando en que banco se colocará con -Wf-boX (en este caso el banco 2)

Citar
lcc -Wl-yp0x143=0x80 -Wl-yt1 -Wl-yo4 -o rom.gb main.o tiles.o

Y ya podemos crear nuestra rom, con -Wl-ytX especificamos que será una ROM con MBC1, los distintos tipos posibles son:

0 : ROM ONLY
1 : ROM+MBC1
2 : ROM+MBC1+RAM
3 : ROM+MBC1+RAM+BATTERY
5 : ROM+MBC2
6 : ROM+MBC2+BATTERY


Con -Wl-yoX especificamos el numero de bancos que tendrá nuestra ROM, en este caso, 4. Podemos poner hasta 32 (512 KB) con el mapper MBC1, siendo el primer banco el 1, así que empezar a meter vuestros datos en el dos.

Citar
pause
bgb.exe rom.gb

Acostumbraos a usar "Banking", no es difícil y muchos seguro que ya lo conoceis si programais para ordenadores de 8 bits, máquinas posteriores como Mega Drive pueden direccionar 32 megabits sin banking (4 megabytes), cosa que se agradece pero en cambio otras supuestamente más poderosas como Super Nintendo hay que volver a utilizarlo así que no está de más practicar.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 19 Septiembre 2014, 07:49:34

METASPRITES

Algunos ya habreis cabilado que eso de trabajar con sprites de 8x8 o como mucho de 8x16 es una puñeta si quieres hacer personajes grandes y vistosos... lo suyo es acudir a metasprites. ¿Y qué es un metasprite? Pues "simplemente" un sprite formado por múltiples sprites. Para ello, vamos a recurrir a unas rutinas que el señor Shen Mansell escribió para facilitarnos la vida http://shen.mansell.tripod.com/games/gameboy/gameboy.html (http://shen.mansell.tripod.com/games/gameboy/gameboy.html).

No voy a explicar línea a línea como están escritas estas rutinas, pero si os voy a enseñar un ejemplo de como usarlas. Por ello, os he subido este fichero con todo lo necesario dentro https://dl.dropboxusercontent.com/u/33369593/tutosGB/03_B_metasprites.rar (https://dl.dropboxusercontent.com/u/33369593/tutosGB/03_B_metasprites.rar) (rutinas, gráficos...).

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

// rutinas de manejo de metasprites (sprite formado por varios sprites)
#include "lib_support/char_utils.h"

Enlazamos con las rutinas de Shen para el uso de metasprites.

Código: [Seleccionar]
// tamaño del sprite
#define SPRITE_00_W 3
#define SPRITE_00_H 4

#define SPRITE_00_S SPRITE_00_W*SPRITE_00_H

Definimos el tamaño en tiles de nuestro metasprite, 3x4 tiles en nuestro caso.

Código: [Seleccionar]
// tiles de los sprites
extern unsigned char sprite01_tiledata[];
extern unsigned char sprite02_tiledata[];
extern unsigned char sprite03_tiledata[];
extern unsigned char sprite04_tiledata[];
extern unsigned char sprite05_tiledata[];
extern unsigned char sprite06_tiledata[];

Enlazamos los tiles de los distintos frames que tendrá nuestro metasprite.

Código: [Seleccionar]
// estructura basica de un personaje, id, posicion, grafico
struct PG{
UBYTE id;
UBYTE x;
UBYTE y;
UBYTE graphic;
};

// jugador
struct PG player;

// metasprite del jugador
UBYTE sprPlayer;

Nos creamos un estructura para un "jugador" y variables minimas de control para su metasprite.

Código: [Seleccionar]
//////////////////////////////////////////////////////
//
//  void playerMoving( UBYTE keys )
//  mueve el metasprite del jugador
//
//////////////////////////////////////////////////////
void playerMoving( UBYTE keys ){

if( keys & J_DOWN )
if( player.y != 104 )
            ++player.y; // 112 = 144 - (altura sprite * 8)

if( keys & J_UP )
if( player.y != 0 )
            --player.y;

if( keys & J_LEFT )
if( player.x != 0 )
            --player.x;

if( keys & J_RIGHT )
if( player.x != 136 )
            ++player.x; // 136 = 144 - (ancho sprite * 8)


    moveSprite( player.id, player.x, player.y, SPRITE_00_W, SPRITE_00_H);

    return;
}

Esta función llamada desde "main()" recibirá las teclas pulsadas y llamará a las rutinas de movimiento del metasprite, modificando primero la estructura del "jugador".

Código: [Seleccionar]
//////////////////////////////////////////////////////
//
//  void updatePlayerAnimation(){
//  cambia la animacion del meta sprite del jugador
//
//////////////////////////////////////////////////////
void updatePlayerAnimation(){

    static UBYTE _timer2 = 0;
_timer2++;

if( _timer2 == 61)
        _timer2 = 0;

if( _timer2 == 0)
changeSprGraphics( 0, sprite01_tiledata, SPRITE_00_S );
else if( _timer2 == 10 )
changeSprGraphics( 0, sprite02_tiledata, SPRITE_00_S );
else if( _timer2 == 20 )
changeSprGraphics( 0, sprite03_tiledata, SPRITE_00_S );
else if( _timer2 == 30 )
changeSprGraphics( 0, sprite04_tiledata, SPRITE_00_S );
else if( _timer2 == 40 )
changeSprGraphics( 0, sprite05_tiledata, SPRITE_00_S );
else if( _timer2 == 50 )
changeSprGraphics( 0, sprite06_tiledata, SPRITE_00_S );
}

Esta función llamada desde "main()" simplemente animará nuestro metasprite.

Código: [Seleccionar]
//////////////////////////////////////////////////////
//
//  void main(){
//  punto de entrada
//
//////////////////////////////////////////////////////
void main(){

    UBYTE keys;

    // desactiva la pantalla
    DISPLAY_OFF;
    disable_interrupts();

    // sprites de 8x8
    SPRITES_8x8;

    // esconde todo
    HIDE_SPRITES;
    HIDE_BKG;
    HIDE_WIN;

    // carga del sprite del personaje
    sprPlayer = loadSpriteGraphics( sprite01_tiledata, SPRITE_00_S );
    player.id = setupSprite( sprPlayer, SPRITE_00_W, SPRITE_00_H );
    player.x = 10;
    player.y = 72;
    moveSprite( player.id, player.x, player.y, SPRITE_00_W, SPRITE_00_H);

Ya en "main()", cargamos los tiles de metasprite indicando sus tiles y tamaño con "loadSpriteGraphics" recibiendo su metasprite que usaremos después con "setupSprite" para darle valores, recibiendo su id necesario para posteriormente moverlo con "moveSprite". La parte de desactivación de la pantalla es para evitar basura durante el proceso hasta que finalice, es recomendado hacerlo cuando vayamos a hacer grandes cambios en la pantalla.

Código: [Seleccionar]
    SHOW_BKG;
    //SHOW_WIN;
    SHOW_SPRITES;
    DISPLAY_ON;
    enable_interrupts();

    // bucle infinito
    while(1) {
// sincroniza la pantalla
wait_vbl_done();

// lee el pad
keys = joypad();

        // mueve el jugador
        playerMoving( keys );

        //  cambia la animacion del meta sprite del jugador
updatePlayerAnimation();
    }
}

Ya dentro del bucle infinito, simplemente vamos controlando las pulsaciones de los botones y llamamos a las funciones de movimiento y animación del metasprite. Recordad que como acceden a la VRAM, hay que hacerlo DESPUÉS del blanqueo con "wait_vbl_done();"

El código completo de "main.c" quedaría así:

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

// rutinas de manejo de metasprites (sprite formado por varios sprites)
#include "lib_support/char_utils.h"

// tamaño del sprite
#define SPRITE_00_W 3
#define SPRITE_00_H 4

#define SPRITE_00_S SPRITE_00_W*SPRITE_00_H

// tiles de los sprites
extern unsigned char sprite01_tiledata[];
extern unsigned char sprite02_tiledata[];
extern unsigned char sprite03_tiledata[];
extern unsigned char sprite04_tiledata[];
extern unsigned char sprite05_tiledata[];
extern unsigned char sprite06_tiledata[];

// estructra basica de un personaje, id, posicion, grafico
struct PG{
UBYTE id;
UBYTE x;
UBYTE y;
UBYTE graphic;
};

// jugador
struct PG player;

// sprite del jugador
UBYTE sprPlayer;

//////////////////////////////////////////////////////
//
//  void playerMoving( UBYTE keys )
//  mueve el meta sprite del jugador
//
//////////////////////////////////////////////////////
void playerMoving( UBYTE keys ){

    if( keys & J_DOWN )
        if( player.y != 104 )
            ++player.y; // 112 = 144 - (altura sprite * 8)

    if( keys & J_UP )
if( player.y != 0 )
            --player.y;

    if( keys & J_LEFT )
if( player.x != 0 )
            --player.x;

    if( keys & J_RIGHT )
if( player.x != 136 )
            ++player.x; // 136 = 144 - (ancho sprite * 8)

    moveSprite( player.id, player.x, player.y, SPRITE_00_W, SPRITE_00_H);

    return;
}


//////////////////////////////////////////////////////
//
//  void updatePlayerAnimation(){
//  cambia la animacion del meta sprite del jugador
//
//////////////////////////////////////////////////////
void updatePlayerAnimation(){

    static UBYTE _timer2 = 0;
_timer2++;

    if( _timer2 == 61)
        _timer2 = 0;

if( _timer2 == 0)
changeSprGraphics( 0, sprite01_tiledata, SPRITE_00_S );
else if( _timer2 == 10 )
changeSprGraphics( 0, sprite02_tiledata, SPRITE_00_S );
else if( _timer2 == 20 )
changeSprGraphics( 0, sprite03_tiledata, SPRITE_00_S );
else if( _timer2 == 30 )
changeSprGraphics( 0, sprite04_tiledata, SPRITE_00_S );
else if( _timer2 == 40 )
changeSprGraphics( 0, sprite05_tiledata, SPRITE_00_S );
else if( _timer2 == 50 )
changeSprGraphics( 0, sprite06_tiledata, SPRITE_00_S );
}


//////////////////////////////////////////////////////
//
//  void main(){
//  punto de entrada
//
//////////////////////////////////////////////////////
void main(){

    UBYTE keys;

    // desactiva la pantalla
    DISPLAY_OFF;
    disable_interrupts();

    // sprites de 8x8
    SPRITES_8x8;

    // esconde todo
    HIDE_SPRITES;
    HIDE_BKG;
    HIDE_WIN;

    // carga del sprite del personaje
    sprPlayer = loadSpriteGraphics( sprite01_tiledata, SPRITE_00_S );
    player.id = setupSprite( sprPlayer, SPRITE_00_W, SPRITE_00_H );
    player.x = 10;
    player.y = 72;
    moveSprite( player.id, player.x, player.y, SPRITE_00_W, SPRITE_00_H);

    SHOW_BKG;
    //SHOW_WIN;
    SHOW_SPRITES;
    DISPLAY_ON;
    enable_interrupts();

    // bucle infinito
    while(1) {
// sincroniza la pantalla
wait_vbl_done();

// lee el pad
keys = joypad();

        // mueve el jugador
        playerMoving( keys );

        //  cambia la animacion del meta sprite del jugador
        updatePlayerAnimation();
    }
}

Un posible "compile.bat" sencillo sería este:

Citar
lcc -c -o  sprite_data.o pics/sprite_data.c
lcc -c -o char_utils.o lib_support/char_utils.c
lcc -c -o main.o main.c
lcc -o rom.gb main.o char_utils.o sprite_data.o
pause
bgb.exe rom.gb

Y ya tenemos nuestro metasprite de 3x8 tiles moviéndose de forma sencilla.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/bgb00005.bmp)


DEBERES
Esta lección creo que ha quedado muy completita asi que seguro que estais deseosos de hacer múltiples pruebas. Aparte de las típicas, os recomendaría añadir al ejemplo de metasprites soporte de color, banking, flip y soporte para sprites de 8x16, a ver quien es el primero en hacerlo ;)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: kalzakath en 19 Septiembre 2014, 08:40:27
Olé tú. Una versión em pdf para la página principal de fasebonus para cuándo?
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Balthier en 19 Septiembre 2014, 09:13:30
A ver wi lo del Banking me ha quedado claro. Básicamente tenemos varios bloques de memoria en los cuales almacenamos datos como sprites o sonidos y los vamos intercambiando según  los vamos precisando no?

Es como si tuviera un mueble con varios cajones. En un cajón tenemos calcetines, en otro calzones, en otro bragas, etc... Y cuando queremos acceder a ese contenido lo hacemos mediante la intrucción precisa?
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: josepzin en 19 Septiembre 2014, 12:26:01
Muy interesante y muy bien explicado!
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: karkayu en 19 Septiembre 2014, 14:46:43
Esta todo genial!! Voy a intentar hacer experimentos este finde :)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Victor en 19 Septiembre 2014, 16:25:13
Completito, completito. Lo de los metaSprites me ha encantado, que te lo había pedido ya  ^-^

Una duda tras una lectura rápida (seguro que luego vienen más).
¿Porque declaras 4 bancos si realmente solo usas 2?
¿Los bancos se numeran a partir del 1 o el 0? Porque estás usando el 2 para los tiles, imagino que en el 1 está el main y en el 0 y el 3 (o en el 3 y el 4) ¿no hay nada?

Esta noche intentaré darle caña, aunque sea con una mano :P
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 19 Septiembre 2014, 17:27:57
A ver wi lo del Banking me ha quedado claro. Básicamente tenemos varios bloques de memoria en los cuales almacenamos datos como sprites o sonidos y los vamos intercambiando según  los vamos precisando no?

Es como si tuviera un mueble con varios cajones. En un cajón tenemos calcetines, en otro calzones, en otro bragas, etc... Y cuando queremos acceder a ese contenido lo hacemos mediante la intrucción precisa?

En resumidas cuentas... si xDD Me ha encantado el ejemplo de los cajones!

Completito, completito. Lo de los metaSprites me ha encantado, que te lo había pedido ya  ^-^

Una duda tras una lectura rápida (seguro que luego vienen más).
¿Porque declaras 4 bancos si realmente solo usas 2?
¿Los bancos se numeran a partir del 1 o el 0? Porque estás usando el 2 para los tiles, imagino que en el 1 está el main y en el 0 y el 3 (o en el 3 y el 4) ¿no hay nada?

Esta noche intentaré darle caña, aunque sea con una mano :P

Cuando compilo, si creo bancos impares me da error, asi que supongo que se deben crear de esta forma... Se numero a partir del 1, asi que hay que empezar a usar desde el 2! El ejemplo es que lo usaba para otra cosa donde si que tenia cosas en los bancos 3 y 4... de ahi el tema de los bancos, cosas del copy/paste :P

El tema de los metasprites ya lo ves, por dentro siguen siendo de 8x8/8x16, a eso me refería...

Me alegro que os haya molado, no ha sido poco curro de investigacion!
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 26 Septiembre 2014, 08:38:25
TUTORIAL 4: FONDOS

En el tutorial anterior comentamos lo que era un sprite, en este vamos a tratar el fondo o background. Se trata de una capa formada por 32x32 tiles capaz de moverse en las coordenadas X/Y, siendo la parte visible en pantalla de 20x18 tiles (160x144 pixels). En las opciones de debug de los emuladores incluidos se puede este fondo, el cuadrado rojo representa el área visible de la pantalla y como podéis ver, el mapa es algo más grande que ésta:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt05.png)

Anteriormente también comentamos que en la VRAM, la memoria de video, podíamos distinguir 2 zonas, una para los tiles de los sprites (hasta 256) y otra para el fondo (hasta 256) pudiendo haber un total máximo de 384, ¿qué quiere decir esto? Pues desgraciadamente, la segunda mitad del área reservada para sprites y fondos es común, quedando a nuestra elección como usarla. Es decir, desde la posición 0 a 127 de la zona de sprites, solo podremos meter tiles para sprites, en la posición 0 a 127 de la zona de fondos, solo podremos meter tiles para fondos, pero en la zona 128-255 de ambos... ¡hay que tener muy controlado que ponemos! Lo veremos mucho más claro en el ejemplo que vamos a hacer, una representación visual de la VRAM sería esta:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt07.bmp)

Vamos a empezar con algo, simplemente vamos a dibujar una imagen del tamaño de la pantalla, para eso usaremos este homenaje al aniversario de la consola hecha por el amigo Felipe Monge:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/gb_logo-01%202.bmp)

Primero habrá que convertirla al formato de la consola, usaremos en PCX2GB que puse en la carpeta TOOLS. La imagen recordad que no puede esta formada por más de 256 tiles, ser un PCX y usar la paleta siguiente, que no es la misma que usamos en el tutorial anterior para el GBTD:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/pcx2gb_colors.bmp)

Hay multitud de conversores, siempre podéis ir probando y elegir el que más os guste, pero este para empezar está bien. Este por ejemplo es en HTML5 y funciona más o menos bien:

http://www.chrisantonellis.com/gameboy/gbtdg/ (http://www.chrisantonellis.com/gameboy/gbtdg/)

Podemos convertir la imagen de dos formas diferentes, tal cual, usando la linea de comandos:

Citar
pcx2gb n d fichero.pcx tiles.c

La imagen de esta forma ocupa 380 tiles. Solo podríamos dibujarla si sobrepasamos los tiles delimitados al fondo.

O de forma optimizada, reduciendo los tiles repetidos y creando un mapa de estos con la linea:

Citar
pcx2gb o d fichero.pcx tiles.c map.c

De esta forma, ahora la imagen ocupa 131 tiles, bastantes menos como podéis observar.

Para dibujar la imagen en el primer caso, podríamos usar una de las funciones incluidas en "drawing.h", "draw_image"(data). Usando esta función, usaremos la VRAM completa, es decir, los 384 tiles, ya que las funciones de "drawing.h" usan cada tile de la VRAM simulando un framebuffer, o mejor dicho, cada tile de la memoria es una posición en la pantalla. Esto es un gran problema a la hora de usarlo en un juego, ya que por ejemplo, no nos quedan tiles libres para los sprites.

El código completo sería este:

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

#include "2.c"

///////////////////////////////////////////////
//  punto de entrada
///////////////////////////////////////////////
void main(){

    draw_image( tiledata );

    // bucle infinito
    while(1) {
// sincroniza con el blanqueo vertical para dibujar los graficos y pone los contadores (timers)
wait_vbl_done();
    }
}

Siendo "2.c" el nombre del fichero que nos ha generado el conversor de la imagen. Recordad poner const delante del vector que nos genera.

Para el segundo método, usando un mapa de tiles, también es muy simple, simplemente cargamos los tiles en VRAM con set_bkg_data( posición en VRAM, numero de tiles, tiles), luego el mapa con set_bkg_tiles( x, y, ancho, alto, mapa) y por último los mostramos con SHOW_BKG.

El código completo sería este:

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

#include "tiles.c"
#include "map.c"

///////////////////////////////////////////////
//  punto de entrada
///////////////////////////////////////////////
void main(){

    // carga los tiles - posicion, numero, tiles
    set_bkg_data( 0, 131, tiledata);

    // carga el mapa de tiles - x, y, ancho, alto y mapa
    set_bkg_tiles( 0, 0, 20, 18, tilemap);

    // muestra el fondo
    SHOW_BKG;

    // bucle infinito
    while(1) {
// sincroniza con el blanqueo vertical para dibujar los graficos y pone los contadores (timers)
wait_vbl_done();
    }
}

Observar la enorme diferencia de usar mapas de tiles frente a usar la imagen tal cual convertida. Comprobad también como nuestra imagen al tener 131 tiles, se pasa 3 de los 128, por lo que pasan automáticamente a la zona común.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt08.png)

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt06.png)


SCROLL DEL FONDO
Ahora que ya tenemos el fondo dibujado, ahora vamos a moverlo. Para ello podemos usar la función "move_bkg". Prácticamente el código es el mismo, creamos unas variables para el control del pad, otras para las posición del scroll, las actualizamos con el pad y se las pasamos a "move_bkg". Las librerías también incluyen la función "scroll_bkg" que realizan el scroll de forma relativa a su posición actual.

El código quedaría así:

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

#include "tiles.c"
#include "map.c"

///////////////////////////////////////////////
//  punto de entrada
///////////////////////////////////////////////
void main(){

    UBYTE i, bposx, bposy; // control del pad y scroll del fondo

    set_bkg_data( 0, 131, tiledata); //111
    set_bkg_tiles( 0, 0, 20, 18, tilemap);

    SHOW_BKG;

    // bucle infinito
    bposx = bposy = 0;
    while(1) {

// lee el pad
        i = joypad();

        // modificamos la posicion
        if(i & J_UP)
            bposy -= 1;
        if(i & J_DOWN)
            bposy += 1;
        if(i & J_LEFT)
            bposx -= 1;
        if(i & J_RIGHT)
            bposx += 1;

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

        // movemos el scroll
        move_bkg( bposx, bposy);
    }
}


Como se ve en el debug del emulador, hemos movido el área visible de la pantalla por el mapa y cuando llegamos al borde superior/inferior o derecho/ziquierdo, aparece por el otro extremo.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt09.png)


PLANO WINDOW
Antes comentaba que solo había un plano de fondo o "BACKGROUND" y esto no es del todo cierto. También existe otro plano que se superpone al que conocemos llamado ventana (WINDOW). El problema que tiene es que es opaco completamente y prácticamente se limita a su uso como marcador. Su funcionamiento es prácticamente igual al fondo normal, para ver su uso, vamos a crear unas funciones que nos permitan dibujar texto en ambas capas.

Vamos a utilizar esta bonita fuente y la convertiremos con el conversor online comentado más arriba:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/font01.bmp)

http://www.chrisantonellis.com/gameboy/gbtdg/ (http://www.chrisantonellis.com/gameboy/gbtdg/)

Como únicamente queremos los tiles sin optimizar los repetidos, desmarcaremos las opciones "Generate Tile Map" y "Tile Quantization" y elegiremos como formato de salida "C Format (GBDK)". Guardamos su contenido en un fichero llamado "font.c" y ya tenemos listos nuestros tiles de la fuente en formato ASCII, si queréis añadir minúsculas o caracteres especiales, buscad la tabla ASCII y añadirlos, yo lo he dejado lo más reducido posible (64 tiles).

Creamos nuestro "main.c" y escribimos:

Código: [Seleccionar]
#include <gb/gb.h>
#include "font.c"

static const unsigned char string00[] = "CARACOLA";

// posicion de los tiles del texto
#define FONT_OFFSET 128

Añadimos los tiles de la fuente, una cadena de caracteres en ROM y la posición de la VRAM donde guardaremos los tiles de la fuente.

Código: [Seleccionar]
/////////////////////////////////////////////////////
//
//  void drawString(char str[], UBYTE x, UBYTE y){
//  dibuja la cadena str en la posicion x, y
//  en BKG si flag es 0 y en WIN si es 1
//  si una palabra no entra en la linea, la dibuja
//  en la siguiente
//
/////////////////////////////////////////////////////
void drawString( char *str, UBYTE x, UBYTE y, UBYTE flag ){

    UBYTE posx, strx, nextlen;
    UBYTE posy, e;
    UBYTE c;

    strx = 0;
    posx = x;
    posy = y;

    // mientras la cadena no termine
    while(str[strx] != 0){

        // comprueba la longitud de la palabra actual de la cadena
        nextlen = 0;
        for( e = strx; (str[e] != ' ') && (str[e] != 0); e++)
            nextlen++;

        // si no cabe en pantalla bajamos de linea
        if ( posx + nextlen > 20){
            posx = 0;
            posy++;
        }

        // dibuja la palabra en la posicion que corresponda
        for(;(str[strx] != ' ') && (str[strx] != 0); strx++){
            c = str[strx] + FONT_OFFSET - 32;
            if( !flag )
                set_bkg_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            else
                set_win_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            posx++;
        }

        // dibuja un espacio en blanco entre las palabras de la cadena
        if ( posx != 0 ){
            c = ' ' + FONT_OFFSET - 32;
            if( !flag )
                set_bkg_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            else
                set_win_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            posx++;
        }

        // si no es el final de la cadena incrementamos la posicion
        if(str[strx] != 0 )
          strx++;
    }
}

Con esta función, dibujaremos la cadena de texto que se le pase, en la posición X/Y indicada en el plano BACKGROUND si flag es "0" con "set_bkg_tiles" o en WINDOW si es "1" con "set_win_tiles". Como veis, los tiles son comunes en ambos planos.

Código: [Seleccionar]
///////////////////////////////////////////////
//  punto de entrada
///////////////////////////////////////////////
void main(){

    UBYTE i, bposx, bposy;

    // cargamos los tiles de la fuente
    set_bkg_data( FONT_OFFSET, 64,(unsigned char *)font);

    // dibujo la cadena en el fondo
    drawString( "HOLA", 1, 10, 0);

    // tb puedo dibujar cadenas desde rom
    drawString(string00, 6, 10, 0);

    // esta como no cabe entera baja a la siguiente linea
    drawString(string00, 13, 11, 0);

    // dibujo la cadena en el fondo
    drawString( "HOLA WINDOWS", 0, 0, 1);

    // muestra el BKG
    SHOW_BKG;
    SHOW_WIN; // WIN se suporpone a BKG y usa sus mismos tiles, para dejar ver a BKG hay que moverla primero

    // bucle infinito
    bposx = 8; bposy = 128;
    while(1){

        // lee el pad
        i = joypad();

        // modificamos la posicion
        if(i & J_UP)
            bposy -= 1;
        if(i & J_DOWN)
            bposy += 1;
        if(i & J_LEFT)
            bposx -= 1;
        if(i & J_RIGHT)
            bposx += 1;

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

// movemos el scroll de la ventana
        move_win( bposx, bposy);
    }
}

Ya en el "main()", dibujamos varias cadenas en el fondo y en la ventana desde RAM y ROM. En el bucle infinito controlamos el pad y movemos la ventana para ver como se suporpone al fondo.

El código completo quedaría así:

Código: [Seleccionar]
#include <gb/gb.h>
#include "font.c"

static const unsigned char string00[] = "CARACOLA";

// posicion de los tiles del texto
#define FONT_OFFSET 128

/////////////////////////////////////////////////////
//
//  void drawString(char str[], UBYTE x, UBYTE y){
//  dibuja la cadena str en la posicion x, y
//  en BKG si flag es 0 y en WIN si es 1
//  si una palabra no entra en la linea, la dibuja
//  en la siguiente
//
/////////////////////////////////////////////////////
void drawString( char *str, UBYTE x, UBYTE y, UBYTE flag ){

    UBYTE posx, strx, nextlen;
    UBYTE posy, e;
    UBYTE c;

    strx = 0;
    posx = x;
    posy = y;

    // mientras la cadena no termine
    while(str[strx] != 0){

        // comprueba la longitud de la palabra actual de la cadena
        nextlen = 0;
        for( e = strx; (str[e] != ' ') && (str[e] != 0); e++)
            nextlen++;

        // si no cabe en pantalla bajamos de linea
        if ( posx + nextlen > 20){
            posx = 0;
            posy++;
        }

        // dibuja la palabra en la posicion que corresponda
        for(;(str[strx] != ' ') && (str[strx] != 0); strx++){
            c = str[strx] + FONT_OFFSET - 32;
            if( !flag )
                set_bkg_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            else
                set_win_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            posx++;
        }

        // dibuja un espacio en blanco entre las palabras de la cadena
        if ( posx != 0 ){
            c = ' ' + FONT_OFFSET - 32;
            if( !flag )
                set_bkg_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            else
                set_win_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            posx++;
        }

        // si no es el final de la cadena incrementamos la posicion
        if(str[strx] != 0 )
          strx++;
    }
}

///////////////////////////////////////////////
//  punto de entrada
///////////////////////////////////////////////
void main(){

    UBYTE i, bposx, bposy;

    // cargamos los tiles de la fuente
    set_bkg_data( FONT_OFFSET, 64,(unsigned char *)font);

    // dibujo la cadena en el fondo
    drawString( "HOLA", 1, 10, 0);

    // tb puedo dibujar cadenas desde rom
    drawString(string00, 6, 10, 0);

    // esta como no cabe entera baja a la siguiente linea
    drawString(string00, 13, 11, 0);

    // dibujo la cadena en el fondo
    drawString( "HOLA WINDOWS", 0, 0, 1);

    // muestra el BKG
    SHOW_BKG;
    SHOW_WIN; // WIN se suporpone a BKG y usa sus mismos tiles, para dejar ver a BKG hay que moverla primero

    // bucle infinito
    bposx = 8; bposy = 128;
    while(1){

        // lee el pad
        i = joypad();

        // modificamos la posicion
        if(i & J_UP)
            bposy -= 1;
        if(i & J_DOWN)
            bposy += 1;
        if(i & J_LEFT)
            bposx -= 1;
        if(i & J_RIGHT)
            bposx += 1;

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

// movemos el scroll de la ventana
        move_win( bposx, bposy);
    }
}

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt10.png)


DEBERES
Con esto doy por terminada la primera parte del tutorial de los fondos, para el próximo trataremos el color y como ejemplo os explicaré las pautas para romper la limitación de tamaño del plano de 32x32 tiles y hacer un scroll más grande a base de mapas de tiles. Como deberes os pongo que aprendais a usar los conversores listados y añadais sprites al fondo y ventana.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Victor en 26 Septiembre 2014, 22:36:05
Genial como siempre.
Como conversor le tengo echado el ojo al png2gb que seamos sinceros, los png están mejor soportados que los pcx en los editores modernos:
https://github.com/LuckyLights/png2gb

A ver si acabo con tu tuto y lo pruebo también.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 27 Septiembre 2014, 09:14:45
Anda, ese no lo conocía, lo tienes por ahí compilado para windows? Parece que solo está el fuente ahí. Yo la verdad es que uso sobretodo el online en html5 que puse, que excepto por el conteo de tiles que no me aclaro, funciona muy bien.

Ah, la semana que viene no está claro que haya tuto, estoy muy liado con el trabajo y debo investigar aún cosas...
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Victor en 27 Septiembre 2014, 13:36:15
Para linux sin problemas, pero he tratado de compilarlo en Windows y me lanza fallos por todos lados. Tendré que echarle un ojo al código despacio.

Tú a tu ritmo, que lo primero es lo primero.

Además, con esto ya hay bastante para enredar ;D
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Balthier en 27 Septiembre 2014, 14:39:53
Como si tienes que parar meses Lucho, encimq de que lo haces de manera altruista, nadie te va a exigir nada.  ;)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Victor en 28 Septiembre 2014, 16:50:43
No veas el pcx2gb.
Falla en Win7 32bits. Me dice que el sistema no es compatible con pantalla completa. Con PowerShell, omitiendo 3 veces consigues hacerlo funcionar pero tela...
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 28 Septiembre 2014, 21:39:40
Ah, pues utiliza mejor el de html5 aunque ese no soporta pcx.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Victor en 29 Septiembre 2014, 19:07:25
Vale, tengo un "bug" en el editor web.

El pcx2gb deja el tile 00 completamente en blanco, lo que hace que en el ejemplo de mover la imagen, el resto este en blanco.
El conversor web no. Mete el primer tile de la imagen en el 00, lo que hace que al mover la imagen, el resto se vea con ese tile.

Iba a adjuntar ejemplo con el código y compilados para que se vea más claro, pero no me deja el foro. Luego meto un link de dropbox.

Lo cachondo es que en ambos casos, la imagen ocupa 131 tiles, a pesar de que no hay ningún tile en blanco en el 2º caso, imagino que el pcx2gb busca un tile en blanco para meter en el 00 y a partir de ahí selecciona los demás; y el conversor web es lineal. Empieza por el primer tile 8x8 y sigue hasta el final.

No tiene mayor gravedad. Pero hay que tenerlo en cuenta a la hora de diseñar los mapas, si esperabas que salieran en blanco.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Victor en 29 Septiembre 2014, 22:03:53
No me deja editar
El link:
https://dl.dropboxusercontent.com/u/11800236/pcx_vs_web.zip
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 02 Octubre 2014, 20:23:42
TUTORIAL 4: FONDOS (II)

Ahora vamos a tratar el color en los mapas de tiles. Prácticamente se hace igual que en modo clásico pero añadiendo paletas y un mapa que indica que paleta usa cada tile.

Un poquito de teoría, la Game Boy Color usa una paleta de 15-bits RGB (32,768 colores). En pantalla, sin usar trucos, podremos llegar hasta 56 colores, 8 paletas de 4 colores para los fondos, más otras 8 de 3 colores para los sprites (el primer color de cada paleta de 4 es el transparente). Por truco, me refiero a cambiar las paletas en cada scanline (o incluso a mitad de scanline), pudiendo llegar a 10000 colores a la vez, pero para pantallas estáticas únicamente.

Vamos a utilizar esta imagen como ejemplo, pasarla a mapa de tiles optimizado con vuestro conversor preferido y los enlazamos en nuestro main.c:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/1.bmp)

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

#include "pcx2gb/tiles.c"
#include "pcx2gb/map.c"

Como con los sprites, definimos nuestras paletas:

Código: [Seleccionar]
// paletas
const UWORD bkg_palette[] = {
RGB_RED, RGB_DARKRED, RGB_GREEN, RGB_DARKGREEN,
RGB_BLUE, RGB_DARKBLUE, RGB_YELLOW, RGB_DARKYELLOW,
RGB_CYAN, RGB_AQUA, RGB_PINK, RGB_PURPLE,
RGB_LIGHTGRAY, RGB_DARKGRAY, RGB_WHITE, RGB_LIGHTFLESH,
RGB_BLACK, RGB_BROWN, RGB_ORANGE, RGB_TEAL
};

Estos colores son los que trae definidos las libreras, lo que no impide que uséis el que queráis de la la paleta de los 32768 usando este formato "0x7fff, 0x531c, 0x7da0, 0x0c63..."

Ahora vamos a definir el mapa de color, simplemente especificamos que paleta va a usar cada tile de nuestro mapa de esta forma:

Código: [Seleccionar]
// mapa de color para el fondo
unsigned char cgb_map[] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
};

En principio hay que hacerlo a mano ya que no conozco ninguna utilidad que permita crear estos mapas, si alguien la conoce por favor que lo comente y lo edito.

Ya en nuestro "main()", cargamos los tiles y el mapa como vimos en el tutorial anterior:


Código: [Seleccionar]
void main(){

    set_bkg_data( 0, 99, tiledata);

    // mapa de tiles, x, y, ancho, alto y mapa
    set_bkg_tiles( 0, 0, 20, 18, tilemap);

Y al igual que en el tutorial de sprites a color, comprobamos que estamos en una GB COLOR, cambiamos al banco 1 de la VRAM (exclusivo de este modelo), allí cargamos el mapa de color con "set_bkg_tiles" y cargamos las paletas para el fondo con "set_bkg_palette". Recordad, podemos cargar hasta 8 paletas para el fondo y otras 8 para los sprites:

Código: [Seleccionar]
    if( _cpu == CGB_TYPE ){

        VBK_REG = 1;

// posicion x, posicion, y, tamaño x, tamaño y, mapa
        set_bkg_tiles(0, 0, 20, 18, cgb_map);
        VBK_REG = 0;

        // carga las paletas del fondo, paleta inicial, numero y datos
        set_bkg_palette( 0, 5, &bkg_palette[0] );
    }

Mostramos el fondo y entramos en un bucle infinito para terminar:

Código: [Seleccionar]
    SHOW_BKG;

// bucle infinito
while(1) {
// sincroniza con el blanqueo vertical para dibujar los graficos y pone los contadores (timers)
wait_vbl_done();
}
}

El código completo quedaría así:

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

#include "pcx2gb/tiles.c"
#include "pcx2gb/map.c"

// paletas
const UWORD bkg_palette[] = {
RGB_RED, RGB_DARKRED, RGB_GREEN, RGB_DARKGREEN,
RGB_BLUE, RGB_DARKBLUE, RGB_YELLOW, RGB_DARKYELLOW,
RGB_CYAN, RGB_AQUA, RGB_PINK, RGB_PURPLE,
RGB_LIGHTGRAY, RGB_DARKGRAY, RGB_WHITE, RGB_LIGHTFLESH,
RGB_BLACK, RGB_BROWN, RGB_ORANGE, RGB_TEAL
};

// mapa de color para el fondo
unsigned char cgb_map[] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
};

///////////////////////////////////////////////
//  punto de entrada
///////////////////////////////////////////////
void main(){

    set_bkg_data( 0, 99, tiledata);

    // mapa de tiles, x, y, ancho, alto y mapa
    set_bkg_tiles( 0, 0, 20, 18, tilemap);

    if( _cpu == CGB_TYPE ){

        VBK_REG = 1;
        set_bkg_tiles(0, 0, 20, 18, cgb_map);
        VBK_REG = 0;

        // carga las paletas del fondo, paleta inicial, numero y datos
        set_bkg_palette( 0, 5, &bkg_palette[0] );
    }

    SHOW_BKG;

// bucle infinito
while(1) {
// sincroniza con el blanqueo vertical para dibujar los graficos y pone los contadores (timers)
wait_vbl_done();
}
}

Ya podemos crear la rom, no olvidéis añadir soporte de color al compilador con:

Código: [Seleccionar]
lcc -Wa-l -c -o  main.o main.c
lcc -Wl-yp0x143=0x80 -o rom.gb main.o

Y obtenemos este resultado, observar las diferentes paletas en el menú de debug:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt11.png)

Ah, la cpu de la GB COLOR puede trabajar en un modo más rápido que la normal, lo podemos activar con "cpu_fast(void)"


SCROLLER
Por último y como ejemplo, vais a hacer una rutina de scroll grande. Como ya comenté, el mapa del fondo solo puede ser de 32x32 tiles (256x256 pixels), si queremos hacer uno más grande, lo normal en un juego, nosotros con nuestras manitas deberemos programarlo. Y lo mejor, lo vais a hacer vosotros solitos con las directrices que os voy a dar.

Primero con el editor GBTD, dibujaremos los tiles que formarán el mapa, usaremos los mismos del tutorial de sprites.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/cpa02.png)

Después, con el editor GBMB incluido en la carpeta TOOLS, crearemos el mapa, elegimos en propiedades un tamaño 64x20 tiles y el tileset:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt12.png)

Luego lo dibujamos tile a tile con sus herramientas de lápiz y cubo de pintura. Cuando acabemos lo exportamos así:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt13.png)

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt14.png)

Convertimos los tiles y el mapa. Ya en el "main.c" los enlazamos:

extern unsigned char tile_data[];
extern unsigned char map_data[];

Deberemos saber nuestro tamaño del mapa, con un #define por ejemplo:

Código: [Seleccionar]
#define MapSizeX 64

Declaremos dos variables para controlar el scroll en el eje X:

Código: [Seleccionar]
UBYTE ScrollX = 0; // Contador de Scroll en X, hasta 255 tiles (2040 pixels), si quieres más grande... pues UINT16
BYTE SCXCnt = 0; // para el incremento/decremento de tile

Cargamos los tiles en VRAM:

Código: [Seleccionar]
// tiles del fondo, posicion inicial, numero y tiles
set_bkg_data( 0, 4, &tile_data);

Y ahora dibujaremos el fragmento del mapa que se vería en pantalla y dos columnas más (22x18):

Código: [Seleccionar]
// carga el mapa inicial
Cnt = 0;
for( tempa = 0; tempa != 18; tempa++ ){ // parte visible de la pantalla (144 pixels = 18 tiles)

// mapa de tiles, x, y, ancho, alto y mapa
set_bkg_tiles( 0, tempa, 22, 1, &(map_data+Cnt)); // el mapa maximo en memoria es 32 x 32
Cnt = Cnt + MapSizeX; // incrementa Cnt con el tamaño X del mapa para que se cargue la proxima fila
}

Si miramos la VRAM sería algo así:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt15.png)

Ahora pasaríamos a nuestro bucle infinito, controlamos el pad para incrementar el scroll y lo moveremos como vimos en el tutorial anterior, pero con scroll_bkg, es decir, por incrementos y no posición absoluta:

Código: [Seleccionar]
// modificamos el scroll y actualizamos sus contadores
if(( i & J_LEFT ) && ( ScrollX != 0)){
        scroll_bkg( -1, 0 );
        SCXCnt--;
}

if(( i & J_RIGHT ) && ( ScrollX < MapSizeX - 20 )){
        scroll_bkg( 1, 0 );
        SCXCnt++;
}

Vale, ahora simplemente nos faltaría por implementar el redibujado de la columna que toque. La idea es que cuando nos movamos un tile (controlado por SCXCnt), deberiamos dibujar la columna siguiente que tocara del mapa. Visualmente sería así:

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt16.png)

Código: [Seleccionar]
// al avanzar un tile comprueba si hay que actualizar el mapa
if( SCXCnt == 8 ){

        ScrollX++;      // incrementamos el tile
        SCXCnt = 0; // reseteamos el contador del scroll

        // comprobamos que tile habria que poner 2 tiles a su derecha
        Cnt = ScrollX + 21;
        tempb = Cnt % 32;

        // lo repetimos el alto del mapa (32) o la parte que vamos a usar de este (18)
        for( tempa = 0; tempa != 18; tempa++ ){

                // cargamos los tiles: x, y, ancho, alto y mapa
                set_bkg_tiles( tempb , tempa, 1, 1, &(map_data+Cnt)); // cuando se llega al extremo del mapa (32x32) se empieza a contar por el 0

                // incrementamos el contador para impedir cargar los tiles incorrectos
                Cnt = Cnt + MapSizeX;
        }
}

Ahora nos queda el supuesto de retroceder un tile "if( SCXCnt == -8 )", que sería exáctamente igual menos los valores que tomarían Cnt y ScrollX, pensad cuales son (en vez de a la derecha, pues a la izquierda).

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt17.png)

Y listo, no hay más, con esto podreís hacer el scroll tan grande como os permita ScrollX. Esta rutina modificándola debidamente, se puede adaptar a cualquier consola que trabaje en tiles como Megadrive, Nes, Master System, Super Nes... la idea es la misma adaptándose al tamaño del mapa en VRAM y resolución de la pantalla.

DEBERES
Pues os propongo añadir un marcador fijo en el plano WINDOW, un metasprite caminando por la pantalla, color y desplazamiento en el eje Y. Con esto ya podeís hacer vuestro Zelda jejeje
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: realbrucest en 03 Octubre 2014, 11:28:25
Ya sabes que por lo pronto voy a tardarme en dar el salto a la otra acera con lo agustico que se está programando para la megadrive.
Pero como opción al "espionaje industrial" esa explicación de cómo programar la rutina de scroll para mapeados grandes es especialmente cojonuda  ;D

Además comentarte que cojonudos cada uno de los tutos de gameboy, que ya me vale a mí no haberlo hecho hasta ahora  :-[
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: falvarez en 04 Octubre 2014, 01:26:35
Hola, pocket_lucho.

Lo primero de todo, felicitarte por el tutorial. Porque, aunque esté enfocado a la Gameboy, muchos de los conceptos son aplicables a la mayoría de sistemas.

Y, yendo al turrón, hace tiempo que empecé a estudiar sobre cómo desarrollar para GBA. Aunque es algo que tengo parado desde hace meses por falta de tiempo, donde justo me quedé fue en cómo enfocar la rutina para manejar un mapeado que excediera el tamaño máximo que ofrece el hardware, que es justo lo que comentas en el último capítulo del tutorial. Ya tenía algo hecho totalmente por software pero quería exprimir las posibilidades del hardware.

Lo que me ha parecido entender es que, gracias a tu enfoque, al hacer scroll redibujas sólo una columna en vez de tener que redibujar toda la pantalla. Mi pregunta es, ¿por qué has escogido pintar 2 columnas más? Suponiendo un scroll píxel a píxel, eso te ahorraría tener que redibujar 15 de las 16 veces, ¿correcto? ¿Por qué no, entonces, pintar más columnas de golpe. ¿O es que lo he entendido mal y se me escapa algo?

Muchas gracias y un cordial saludo.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 04 Octubre 2014, 10:12:55
Hola Falvarez! Bienvenido por aqui! Pues si, como has visto, la idea es que esto funcione en cualquier chisme que trabaje con mapas de tiles y si van en GB... en cualquier hardware superior pues mejor aun!

Lo de dibujar 2 columnas más inicialmente es pq yo redibujo una columna entera al avanzar una (un tile), una vez cada 8 pixels, si solo dibujara una... pillaría la que voy a actualizar, si lo modificas a una lo podrás comprobar, mejor dos. Aparte solo puedo dibujar tiles completos, no pixels uno a uno. Eso sirve para tener margen tanto si avanza a la derecha como a la izquierda. Si el scroll fuera únicamente en un sentido, si que dibujaría el mapa completo al inicio y actualizaría la columna más lejana, pero como no es el caso, dibujo eso, un pelín fuera del rango visible y solo una vez al avanzar un tile, por eso al redibujar reinicio SCXCnt = 0;

Esta es la forma más simple que se me ha ocurrido (pero seguro que no la más eficaz), luego ya cada uno que la adapte a sus propias necesidades ;)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 09 Octubre 2014, 19:23:04
TUTORIAL 6: SONIDO

En esta parte del tutorial vamos a poder conseguir hacer sonar tanto música como efectos de sonido en la consola. Para ello voy a contar con la ayuda de David Sánchez "Murciano".

Hay que aclarar que no va a ser un tutorial para el aprendizaje de la composición con trackers, ya que veremos que al no haber uno dedicado para Game Boy y tener que utilizar el formato .MOD, cada uno puede utilizar el tracker con el que más cómodo esté.

El player que utilizaremos para la música es obra de Antonio Niño Díaz https://github.com/AntonioND/gbt-player (https://github.com/AntonioND/gbt-player) y consta de un conversor de .MOD a GBT (Game Boy Tracker) y del player que hará que suene la música en la consola.

Así que nos vamos a centrar en las limitaciones con las que tenemos que lidiar y sobre todo, vamos a ver un caso práctico reconocible para que veáis como se escucha el conjunto de música y sfx.

La Game Boy tiene 4 canales: 2 de onda cuadrada, 1 de WAVE y 1 canal de ruido.

En el ejemplo que vamos a ver he usado sólo los 3 primeros canales, ya que por el poco tiempo que he tenido para hacer las pruebas, no me convenció ningún sonido de batería con el canal 4 así que decidí ir a la práctico y dejar sonando la melodía bien con sólo 3 canales.

Yo utilizo para editar los .MOD el Milky Tracker http://www.milkytracker.org/ (http://www.milkytracker.org/). Vamos a abrir el “template.mod” del ejemplo, aunque si queréis profundizar más en el tema, en el paquete del player también vienen ejemplos prácticos.

(https://dl.dropboxusercontent.com/u/33369593/tutosGB/capt18.png)

Como véis, tenemos que crear un .MOD con sólo 4 canales. Cosas a tener en cuenta, como por ejemplo la velocidad. No se pueden modificar los BPM. Sólo se puede modificar la velocidad así que si queremos modificarla en cualquier parte de la composición tendremos que utilizar el comando FXX.

Si os fijáis, tenemos una ayuda muy importante con los instrumentos, ya que en el ejemplo que viene con el player los tenemos definidos y nombrados con el canal a utilizar. Así nos hacemos una idea rápida de que instrumentos utilizar en cada uno de los 4 canales.

IMPORTANTE: El resultado final en la consola difiere de como se escucha en el tracker, así que os tocará ir compilando a menudo para ver si el sonido que estáis consiguiendo es de vuestro gusto. Pero ya os digo que por las pocas pruebas que he hecho, la GameBoy hace su magia y siempre me gusta más como suena en la consola que en el tracker.

Siguiendo con las limitaciones que nos encontramos a la hora de utilizar este player, copio las instrucciones que vienen con el player para que os hagáis una idea de por donde van los tiros.

Código: [Seleccionar]
                         FREQUENCIES
                         -----------

You can use notes from C3 to B8.

                         INSTRUMENTS
                         -----------

+----------------------------------------------------------------+
|CHANNEL|RANGE|                      NOTES                       |
+-------+-----+--------------------------------------------------+
|   1   | 1-4 |                                                  |
|   2   | 1-4 |                                                  |
|   3   | 8-15|Volume is usually a bit lower than other channels.|
|   4   |16-31|Doesn't change with frequency (always C5).        |
+-------+-----+--------------------------------------------------+

                           EFFECTS
                           -------

0xy - Arpeggio. Only channels 1, 2 and 3.

Bnn - Jump to pattern in order nn (in hexadecimal).

Cnn - Sets the volume to nn (in hexadecimal). Valid values from 00h to 40h.
      Channel 3 can only be set to 0%, 25%, 50% and 100%. Others can be set
      in a range of 0-Fh.

Dnn - Ends this pattern and jumps to position nn (in decimal) in next pattern.
      If used the last step of a pattern it will jump two patterns, not one!

E8n - Sets the panning to n (in hexadecimal).
      Left --- Both --- Right
      0123   456789AB    CDEF

ECn - Cut Note after n ticks. If n > speed or n = 0, it won't work.

Fnn - Sets speed to nn (in hexadecimal). Valid values are 01h to 1Fh.
      The higher the value, the slower the song. BPM speed not supported.

Effects are limited in channel 3 when setting a new note (only half of them
are available). It shouldn't be a problem since the effects that can't be
used are control commands that can be used by other channels.

**********************************************************************
* You should set volume and instrument whenever you put a new note!! *
* You should set instrument whenever you change volume in CH3!!      *
* You should always put an instrument whenever you use arpeggio!!    *
**********************************************************************

Tenemos el rango de notas que podemos utilizar, los instrumentos como os he comentado más arriba y los efectos que podemos utilizar.

Algo muy importante es que cada vez que pongamos una nota debe ir acompañada de su correspondiente volumen e instrumento.

Uno de los bugs conocidos se presenta si usamos el comando DXX, si lo usamos al final de un patrón, no saltará al siguiente como debería, sino que salta dos patrones.

Y poco más, en esa lista vienen los efectos que son standard en este tipo de archivos y que se pueden utilizar con este player.


CÓDIGO
Ahora que ya sabemos como debe ser nuestro fichero musical, vamos a escribir el código para reproducirlo.

En nuestro "main.c", enlazamos a las cabeceras de las GBDK como siempre (gb.h), a las funciones de dibujado para el texto (drawing.h), a la del player de música (gbt_player.h) y al fichero de música convertido (ya veremos como compilarlo):

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

// libreria musical Antonio Niño Díaz
#include "mod2gbt/gbt_player.h"

extern const unsigned char * song_Data[];

Ya en la función "main()", desactivamos las interrupciones, cargamos la canción con "gbt_play", activamos la reproducción en bucle y hacemos que cuando ocurra la interrupción VBL se ejecute la función de actualización del player de música con "add_VBL(gbt_update)". Añadimos la interrupción VBL con "set_interrupts(VBL_IFLAG)" y activamos las interrupciones:

Código: [Seleccionar]
void main(){

    disable_interrupts();       // desactiva las interrupciones

    gbt_play(song_Data, 2, 7);  // reproduce la cancion, en banco indicado y a la velocidad dada
    gbt_loop(0);                // activa/desactiva el loop

    add_VBL(gbt_update);        // actualiza el player, ha de ejecutarse cada frame (cambia a banco 1)

    set_interrupts(VBL_IFLAG);  // añade la interrupcion VBL
    enable_interrupts();        // activa las interrupciones

Ya para terminar, añadimos un texto de debug con las funciones que vimos en el primer tutorial y entramos en un bucle infinito:

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

    // bucle infinito
    while(1){
        // sincroniza con el blanqueo vertical para dibujar los graficos y pone los contadores (timers)
        wait_vbl_done();
    }

El tracker musical se guarda en el banco 2 (junto más cosas), por lo que hay que modificar la compilación para añadir soporte de banking como ya vimos en los tutoriales anteriores. Además, cada vez que se actualiza en "wait_vbl_done()", cambia a ese banco, por lo que si tenemos gráficos en otros bancos, recordad que hay que cambiar a su banco primero. Como podéis observar, empezamos con la conversión del fichero ".mod" y lo compilamos junto con nuestro código:

Código: [Seleccionar]
mod2gbt\mod2gbt mod2gbt/template.mod song -c 2
move output.c mod2gbt
lcc -c -o main.o main.c
lcc -c -o output.o mod2gbt/output.c
lcc -c -o gbt_player.o mod2gbt/gbt_player.s
lcc -c -o gbt_player_bank1.o mod2gbt/gbt_player_bank1.s
lcc -Wl-yt1 -Wl-yo4 -o rom.gb main.o output.o gbt_player.o gbt_player_bank1.o
del *.o
bgb.exe rom.gb
pause

El código completo quedaría así:

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

// libreria musical Antonio Niño Díaz
#include "mod2gbt/gbt_player.h"

extern const unsigned char * song_Data[];

///////////////////////////////////////////////
//  punto de entrada
///////////////////////////////////////////////
void main(){

    disable_interrupts();       // desactiva las interrupciones

    gbt_play(song_Data, 2, 7);  // reproduce la cancion, en banco indicado y a la velocidad dada
    gbt_loop(0);                // activa/desactiva el loop

    add_VBL(gbt_update);        // actualiza el player, ha de ejecutarse cada frame (cambia a banco 1)

    set_interrupts(VBL_IFLAG);  // añade la interrupcion VBL
    enable_interrupts();        // activa las interrupciones

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

    // bucle infinito
    while(1){
        // sincroniza con el blanqueo vertical para dibujar los graficos y pone los contadores (timers)
        wait_vbl_done();
    }
}

El fuente con todo lo necesario para compilar lo teneis listo en este fichero:

https://dl.dropboxusercontent.com/u/33369593/tutosGB/06_musica.rar (https://dl.dropboxusercontent.com/u/33369593/tutosGB/06_musica.rar)


SFX
Como se ha dicho al principio, la GB posee 4 canales. Desgraciadamente, al contrario que la música no hay ningún editor mágico de efectos de sonido y tocará hacerlos a mano. Si conoceis algo mejor, por favor indicarlo y lo añadimos al tutorial.

En la carpeta DOCS, he metido un fichero llamado "GBSOUND.txt" con la información que he encontrado del sonido. Básicamente para hacer efectos de sonido vamos a escribir sobre los registros de cada canal:

Canal 1, (tono y portamento)
NR10-NR14

Canal 2, (tono)             
NR21-NR24

Canal 3, (onda programable) 
NR30-NR34

Canal 4, (ruido)             
NR41-NR44

Para saber lo que hace cada registro os recomiendo mirar detenidamente la documentación y la sección de sonido del tutorial en ensamblador de xzakox donde vienen explicados de uno en uno, básicamente duración, envolvente y frecuencia:

http://wiki.ladecadence.net/doku.php?id=tutorial_de_ensamblador#hola_sonido (http://wiki.ladecadence.net/doku.php?id=tutorial_de_ensamblador#hola_sonido)

Tambien debemos prestar atención a estos registros:

NR50, "Vin (input line on cart connector) / Main Output Volume Control" o volumen principal de las salidas izquierda y derecha, que iniciaremos a 0x77U. Este registro permite añadir un canal extra desde el cartucho.

NR51, "Sound Output terminal select (1: enabled; 0: disabled)" o selección de salida de cada canal que iniciaremos a 0x00U.

NR52, "Master control and status flags" o encendido/apagado general del sonido, escribir 00h en este registro, ahorrará un 16% o más de pilas, lo iniciaremos a 0xF8U.

Vamos a hacer un programa que reproduzca varios SFX de esta forma, escribiendo en los registros de cada canal.

Como antes, enlazamos a las cabeceras de las GBDK como siempre (gb.h), a las funciones de dibujado para el texto (drawing.h).

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

Desde "main()", creamos varias variables para controlar el pad y si hay algun sonido reproduciendose, para evitar repeticiones si dejamos el botón pulsado. Dibujamos además un texto de debug.

Código: [Seleccionar]
main(){
    UBYTE input, busy = 0, bIn_progress = 0;

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


Iniciamos los registros de audio antes comentados:

Código: [Seleccionar]
    NR52_REG = 0xF8U;
    NR51_REG = 0x00U;
    NR50_REG = 0x77U;

Y desde el bucle infinito, comprobamos las pulsaciones de los botones y llamamos a las distintas funciones de cada SFX:

Código: [Seleccionar]
// bucle infinito
    while(1){

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

        input = joypad();

        // sonidos de una nota
    if(input & J_A && busy == 0){
            busy = 1;
            sound_00();
        }

        if(input & J_B && busy == 0){
            busy = 1;
            sound_01();
        }

        if(input & J_SELECT && busy == 0){
            busy = 1;
            sound_02();
        }

        // sonido de dos notas
        if(input & J_START && busy == 0){
            busy = 1;
            bIn_progress = sound_03(bIn_progress);
        }

        if( bIn_progress )
             bIn_progress = sound_03(bIn_progress);


        // control para que los sonidos no se sigan reproduciendo si se deja el boton pulsado
        if( !( input & J_B ) && !( input & J_A ) && !( input & J_START ) && !( input & J_SELECT ) && busy == 1 )
            busy = 0;
}

Estas funciones, se limitan a escribir en los registros de cada canal que indicamos antes, especificando duración, envolvente, frecuencia...

Código: [Seleccionar]
//////////////////////////////////////////////////////////////////////////////////////////////
//
//  void sound_0X(void){
//  sonidos de una nota
//  se hacen escribiendo a pelo en los registros de cada canal
//
//////////////////////////////////////////////////////////////////////////////////////////////
void sound_00( void ){

    NR10_REG = 0x34U; // el 4º bit indica si la freq se incrementa o decrece

    // bits 5 a 7  indican el retraso del barrido
    NR11_REG = 0x80U;
    NR12_REG = 0xF0U;
    NR13_REG = 0x0AU; // 8 bits de frecuencia mas bajos
    NR14_REG = 0xC6U; // los primeros 3 bits son los 3 bits mas altos de la frecuencia
    NR51_REG |= 0x11;
}

void sound_01( void ){

    NR41_REG = 0x00;
    NR42_REG = 0xE1;
    NR43_REG = 0x22;
    NR44_REG = 0xC3;
    NR51_REG = 0x88U;
}

void sound_02( void ){

    NR10_REG = 0x04U;
    NR11_REG = 0xFEU;
    NR12_REG = 0xA1U;
    NR13_REG = 0x8FU;
    NR14_REG = 0x86U;
    NR51_REG = 0xF7;
}

//////////////////////////////////////////////////////////////////////////////////////////////
//
//  void sound_03( UBYTE bIn_progress ){
//  sonidos de dos nota
//  se hacen escribiendo a pelo en los registros de cada canal
//
//////////////////////////////////////////////////////////////////////////////////////////////
UBYTE sound_03( UBYTE bIn_progress ){

    // esta el sonido 2 reproduciendose?
    if( NR52_REG & 0x02 ){
return 0x01;
    }

    // el sonido 2 no esta reproduciendose, pero ya se ha tocado la primera nota
    else if( bIn_progress ){
NR21_REG = 0x80U;
NR22_REG = 0x73U;
NR23_REG = 0x9EU;
NR24_REG = 0xC7U;
NR51_REG |= 0x22;
        return 0x00;
    }
    // toca la primera nota
    else{
NR21_REG = 0xAEU;
NR22_REG = 0x68U;
NR23_REG = 0xDBU;
NR24_REG = 0xC6U;
NR51_REG |= 0x22;
return 0x01;
    }
}

El código completo quedaría así:

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

///////////////////////////////////////////////
//
//  void sfxInit( void )
//  inicializa el chip de sonido para los sfx
//
///////////////////////////////////////////////
void sfxInit( void ){

    NR52_REG = 0xF8U;
    NR51_REG = 0x00U;
    NR50_REG = 0x77U;
}

//////////////////////////////////////////////////////////////////////////////////////////////
//
//  void sound_0X(void){
//  sonidos de una nota
//  se hacen escribiendo a pelo en los registros de cada canal
//
//////////////////////////////////////////////////////////////////////////////////////////////
void sound_00( void ){

    NR10_REG = 0x34U; // el 4º bit indica si la freq se incrementa o decrece

    // bits 5 a 7  indican el retraso del barrido
    NR11_REG = 0x80U;
    NR12_REG = 0xF0U;
    NR13_REG = 0x0AU; // 8 bits de frecuencia mas bajos
    NR14_REG = 0xC6U; // los primeros 3 bits son los 3 bits mas altos de la frecuencia
    NR51_REG |= 0x11;
}

void sound_01( void ){

    NR41_REG = 0x00;
    NR42_REG = 0xE1;
    NR43_REG = 0x22;
    NR44_REG = 0xC3;
    NR51_REG = 0x88U;
}

void sound_02( void ){

    NR10_REG = 0x04U;
    NR11_REG = 0xFEU;
    NR12_REG = 0xA1U;
    NR13_REG = 0x8FU;
    NR14_REG = 0x86U;
    NR51_REG = 0xF7;
}

//////////////////////////////////////////////////////////////////////////////////////////////
//
//  void sound_03( UBYTE bIn_progress ){
//  sonidos de dos nota
//  se hacen escribiendo a pelo en los registros de cada canal
//
//////////////////////////////////////////////////////////////////////////////////////////////
UBYTE sound_03( UBYTE bIn_progress ){

    // esta el sonido 2 reproduciendose?
    if( NR52_REG & 0x02 ){
return 0x01;
    }

    // el sonido 2 no esta reproduciendose, pero ya se ha tocado la primera nota
    else if( bIn_progress ){
NR21_REG = 0x80U;
NR22_REG = 0x73U;
NR23_REG = 0x9EU;
NR24_REG = 0xC7U;
NR51_REG |= 0x22;
        return 0x00;
    }
    // toca la primera nota
    else{
NR21_REG = 0xAEU;
NR22_REG = 0x68U;
NR23_REG = 0xDBU;
NR24_REG = 0xC6U;
NR51_REG |= 0x22;
return 0x01;
    }
}

///////////////////////////////////////////////
//  punto de entrada
///////////////////////////////////////////////
void main(){

    UBYTE input, busy = 0, bIn_progress = 0;

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

    // inicia los registros para los sfx
    sfxInit();

    // bucle infinito
    while(1){

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

        input = joypad();

        // sonidos de una nota
    if(input & J_A && busy == 0){
            busy = 1;
            sound_00();
        }

        if(input & J_B && busy == 0){
            busy = 1;
            sound_01();
        }

        if(input & J_SELECT && busy == 0){
            busy = 1;
            sound_02();
        }

        // sonido de dos notas
        if(input & J_START && busy == 0){
            busy = 1;
            bIn_progress = sound_03(bIn_progress);
        }

        if( bIn_progress )
             bIn_progress = sound_03(bIn_progress);


        // control para que los sonidos no se sigan reproduciendo si se deja el boton pulsado
        if( !( input & J_B ) && !( input & J_A ) && !( input & J_START ) && !( input & J_SELECT ) && busy == 1 )
            busy = 0;
}
}

Podriamos reproducir música y efectos a la vez de esta forma pero claro, los canales no se deben pisar, asi que podemos hacer que nuestra canción no use cierto canal o usarlo para un canal de acompañamiento y reproducir por ese los SFX.

DEBERES
Por ejemplo, crear un modulo que no use cierto canal y añadir SFX que suenen por ese canal.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 09 Octubre 2014, 20:14:04
Con este doy por terminada la parte técnica, lo que queda será parte práctica y tardará un poquillo en prepararse... si tenéis alguna sugerencia sobre algún tuto más ya sabéis ;)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: jrll en 18 Octubre 2014, 22:44:47
Muchas gracias por el tutorial. Menudas curradas que te pegas  ;)
Yo voy a ver si me pongo con ello, que me interesaría ver si logro hacer algo en Game Boy.
Además, me llegó ayer el everdrive, y así puedo probarlo en la propia máquina.

Qué grande, pocket_lucho.  ^-^
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Balthier en 19 Octubre 2014, 15:53:15
Pregunta desde la ignorancia, lo del banking no lo soportan todos los emuladores?¿ estaba usando varios emuladores GBA que también tiraban roms de GB y GBC, pero al meterme en el tuto del banking estos emuladores no mostraban nada en pantalla al correr la rom.

He estado loco una hora repasando el .bat y el código, no encontraba el fallo tampoco en el código hasta que probe el emulador "bgb" y ha ido a la primera.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: falvarez en 19 Octubre 2014, 21:35:09
Hola, pocket_lucho.

Otra duda, más de logística. He visto en el primer post que usas CodeBlocks. ¿Lo usas como simple editor de texto o como IDE? Me refiero a que al dar al botón de "compilar" te lance directamente el compilador donde lo tengas, y que sea capaz de localizar las librerías y te autosugiera los nombres de las funciones del SDK. No sé si me explico.

Gracias. Saludos.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 19 Octubre 2014, 23:34:13
Holaaa! Pues lo tengo configurado para las SGDK de Megadrive, en GB lo uso solo como editor, se podría si... pero no he tenido tiempo xD
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 19 Octubre 2014, 23:36:50
Pregunta desde la ignorancia, lo del banking no lo soportan todos los emuladores?¿ estaba usando varios emuladores GBA que también tiraban roms de GB y GBC, pero al meterme en el tuto del banking estos emuladores no mostraban nada en pantalla al correr la rom.

He estado loco una hora repasando el .bat y el código, no encontraba el fallo tampoco en el código hasta que probe el emulador "bgb" y ha ido a la primera.

Ostras, pues puede ser. Yo es que solo pruebo las cosas en BGB y en menor medida en no$gb. Tb lo pruebo en consola con el everdrive de vez en cuando, por lo que puedo confirmar al 100% que el banking funciona, debe ser algún problema con los emus de GBA si.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: HyLian en 27 Octubre 2014, 12:06:05
Magnífico tutorial y magnífico el taller del pasado Sabado en RetroConsolas Alicante.

Tuve la suerte de estar por allí y en apenas hora y media aprendimos un monton sobre el desarrollo para la pequeña de Nintendo.

Gracias por todo este trabajo :)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 27 Octubre 2014, 19:10:54
Me alegro que gustase!!! En breve en cuanto Fran suba el streaming pongo todo el material para disfrute de los que no pudieron asistir!

Gracias a vosotros por seguir el tuto!
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: martian en 28 Octubre 2014, 22:09:39
Tambien asistí al Taller de Programacion GB en Retro Alicante y la verdad es que pocket_lucho se lo curró un huevaco con las explicaciones y se hizo bastante ameno el tema (me quito el sombrero maestro). Vamos que salí de allí con ganas de hacerme un castlevania lo menos y lo peor es que encima me lo creia :D

Tengo un proyecto que estoy desarrollando mientras aprendo (a raticos) a programar para Amstrad CPC pero lo voy a pasar a GB porque ahora veo mas factible terminarlo en la pequeña de nintendo. Ey igual un dia lo veis publicado en 1985alternativo jajaja
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 29 Octubre 2014, 17:19:44
Pues ya sabes en donde tienes que enseñar lo que hagas primero! ;)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: kalzakath en 29 Octubre 2014, 17:43:09
Pocket_lucho, me estoy escuchando los programas de FaseBonus antiguos (soy seguidor del Podcast desde finales del 2013, por lo que tenía tarea acumulada) y  la semana pasada escuché un programa en el que tenías 10.000 ptas para comprar juegos de consola y me ha sorprendido que pusiste la GB a parir  ;D Cómo cambian las cosas. Yo estoy como Martian, de aquí salen dos Castlevanias mínimo! Luego a ver qué pasa.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 29 Octubre 2014, 18:27:31
Y sigo pensando que la pantalla de la GB hasta la color se ve fatal xDDD (En Super GB tb se genial!). Si es que no se puede hacer caso a lo que diga xDD
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: ManiacMorden en 30 Octubre 2014, 09:14:08
Buenas!

Ante todo, quisiera dar las gracias al señor Poket_Lucho por haberse currado estos pedazo de tutoriales. La tienes enorme, colega!

Por el momento he tenido tiempo de seguir todos los tutoriales salvo el del audio, que lo reservo para más adelante cuando ya tenga más familiarizado todo lo anterior.

Como otros tantos desarrolladores intentando hacer videojuegos, padezco del síndrome de MuñonesEnVezDeManos; con lo cual, eso de pintar sprites, fondos o cualquier otra cosa... complicado. Sin embargo, estoy dándole la tabarra a mi novia para que me dibuje cuatro cositas, a ver si por ahí avanzo a alguna parte XDD. Si acaba saliendo cualquier cosa de todo este tema, seréis los primeros en saberlo!

Gracias de nuevo, y a ver si la gente se anima a compartir lo que ha cacharreado con todo esto!
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Balthier en 30 Octubre 2014, 21:21:30
A ver si alguno me puede guiar con la función de setup de sprites para metasprites. Más o menos entiendo cómo funciona, pero me hace dudar la siguiente comprobación:

Código: [Seleccionar]
[b]if( LCDC_REG & 0x04U )[/b]{
_cu_mode = 2;
_cu_size2 = _cu_size>>1;
}else
_cu_size2 = _cu_size;

for( _cu_i = 0; _cu_i != _cu_size2; ++_cu_i ){
if( _cu_x == width ){
            _cu_x = 0;
_cu_y++;
}

A donde se refiere exactamente el "LCDC & 0x04U"¿?
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 30 Octubre 2014, 21:22:43
Yo creo que va por lo que hablamos del tamaño de sprites 8x8 o 8x16...
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Balthier en 30 Octubre 2014, 21:35:46
El tema es probe a cambiarlo con alguna otra sentencia random como por ewjemplo if(!HIDE_SPRITES) y sigue funcionando perfectamente. xD
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 30 Octubre 2014, 21:53:03
Pq a lo mejor estas en 8x8, prueba a quitar eso usando sprites de 8x16 a ver...
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Balthier en 30 Octubre 2014, 22:19:21
Efectivamente con sprites de 8x16 hace "extraños" al intentar mostrarlos en pantalla. Entonces damos por hecho que se refiere a cuando el modo de SPRITES esté puesto a 8x8.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: ManiacMorden en 31 Octubre 2014, 06:13:00
Buenas!

Mirando en un documento de especificaciones de la consola:
http://www.emulatronia.com/doctec/consolas/gameboy/gameboy.txt (http://www.emulatronia.com/doctec/consolas/gameboy/gameboy.txt)
(el mismo documento está disponible en muchos otros sitios, creo)

vemos que:
Citar
Address  - $FF40
Name     - LCDC
Contents - LCD Control (R/W)

[...]

Bit 2 - OBJ Construction
0: 8*8
1: 8*16

Definitivamente se refiere al tamaño de los sprites :)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 31 Octubre 2014, 20:12:56
Pues misterio resuelto entonces!!

Por cierto, vídeo grabado del taller de GB del RetroConsolas Alicante... http://vertice.cpd.ua.es/126068 (http://vertice.cpd.ua.es/126068) El material lo tenéis aquí https://dl.dropboxusercontent.com/u/33369593/gbdk.rar (https://dl.dropboxusercontent.com/u/33369593/gbdk.rar)

No me tiréis piedras que estaba bajo los efectos de drogas duras (frenadol, jarabe de la tos... xD).
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 31 Octubre 2014, 20:21:56
Ah, descargarse el RAR con el material es interesante ya que allí está la versión en PDF de los tutos todos juntitos en un único fichero!
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Balthier en 31 Octubre 2014, 20:42:54
Lo del pdf vendrá  genial.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: GameMaster en 31 Octubre 2014, 20:52:20
el video esta disponible para descarga o en youtube ? gracias
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 31 Octubre 2014, 21:35:37
En la web del link hay un botón para descargar... 2 gigas creo que son xDD
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Balthier en 01 Noviembre 2014, 09:55:53
El enlace que has puesto con lo del PDF no es el correcto. EL GBDK y el pdf están en esta dirección: http://tinyurl.com/o4eesw6 (http://tinyurl.com/o4eesw6)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 01 Noviembre 2014, 11:20:55
Tb vale no? Lo corrijo por si acaso, el PDF suelto aqui: https://dl.dropboxusercontent.com/u/33369593/tutosGB/Taller%20GBDK.pdf
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: stage7 en 18 Noviembre 2014, 00:05:29
Hola, pocket_lucho:

En primer lugar gracias por ofrecer algo como este cursillo por la patilla ya que lo que es en GB me cuesta horrores tener los recursos a mano y con esto lo he podido centralizar un poco.

En segundo vaya por delante que soy prácticamente un negado en lenguajes compilados (soy más de PHP y JS, pero guardad los tomates, por favor) y en programar consolas y me metí hace poco a investigar sobre GB a resultas de comprar un Everdrive. Por supuesto empecé con GBDK y no voy a decir qué tengo pensado hacer con todo esto pero sí que me gustaría aprovecharlo, por lo que me surgen un par de dudas de entrada y leyendo los tutoriales por encima.

1) Tenía entendido que por alguna limitación, no sé si del GBDK o del LCC, el tamaño máximo de las ROMs que podía compilar era de 32 kilobytes, sin embargo hay algún ejemplo en el curso que compila a 64 o a 128 kilobytes, y Antonio Niño tiene demos a 256 kilobytes (¡esa Second Reality!). ¿Cómo es esto posible? ¿Bank switching? ¿Zonas separadas para lógica y tiles? ¿Permite esto crear juegos más complejos o la lógica va a estar igual de limitada a 32 kilobytes?

2) Con la música tengo aproximaciones distintas a las habituales. De las pocas pruebas que he hecho hasta ahora siempre he compuesto mi música programada a pelo en MML (Music Macro Language), y compilada a ROM usando XPMCK, pero nunca he llegado a trastear lo suficiente como para ver si el reproductor que incorpora XPMCK se puede incorporar a la cadena de compilado de GBDK ya que me resulta más cómodo "programar" la música (o sacarla al formato nativo GBS de Game Boy) que componerla sobre tracker y compilarla a GBT. ¿Sabes si es posible utilizar alternativas como ésta para meter música en homebrew en lugar de MOD2GBT? Ya de la gente que consigue reproducir música salida del Littlesounddj no digo nada, esos tipos para mí juegan en otra liga.

Gracias por tu trabajo y por tomarte el tiempo de responder lo que puedas saber de esto.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 03 Diciembre 2014, 18:47:29
Holaaa! Disculpa la tardanza, no habia visto el mensaje xD

1: La respuesta es banking por supuesto, usando esto que yo sepa se pueden hacer roms con las GBDK de hasta 512 kb!

2: Buff, ahí si que no te puedo decir nada.., sobre GBDK solo he encontrado para añadir música el tema del MD2GBT, pero vamos, viendo otros sistemas rero de la época que conozco, tarde o temprano te tendrás que meter con trackers... tampoco sno tan difíles hombre!

Cualquier cosa más ya sabes ;)

Un saludo!
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: retromaquinitas en 03 Enero 2015, 22:23:30
Buenas a todos,

Todo un honor poder dejar mis líneas en este foro. Algunos ya me conoceréis, otros no tanto (tampoco es que sea nadie importante), pero a lo que vamos. Llevaba tiempo con ganas de ponerme con la programación de alguno de nuestros queridos trastos y aunque mi fin "final" será tocar algo más de NES, con la que hace tiempo me puse en ensamblador, es cierto que a la que hay que ponerse con los tiles, diseños, colores y demás todo se complica. O más que complicar, es simplemente más trabajo.

Aprovechando la situación, me he animado a empezar con Game Boy con este tutorial de Pocket Lucho. Y la verdad, es todo un hallazgo, porque la parte inicial de setup, que suele ser la más pesada, se hace en un momento - y luego todo es seguir el tutorial y animarse a toquetear. Tengo que añadir que el propio GBDK trae algunos ejemplos muy interesantes (y didácticos) que también va bien aprovechar.

Os muestro a continuación el trabajo hecho hasta ahora, para ver si os animáis a publicar vuestros avances. Este es el trabajo de, aproximadamente, dos días. Empecé con la idea de programar un juego bastante distinto de lo que se puede ver ahora, pero he ido optando por la simplicidad por el simple hecho de poder ver algo en funcionamiento. No tengo ni idea de diseño, con lo que soy consciente que si quisiera seguir necesitaría ayuda de alguien más capaz en dibujo y con más visión artística. Menos idea musical tengo todavía, así que el capítulo de música ni lo he empezado ni implementado. Pero cogiendo de un sitio y de otro al menos tengo algo que muestra unos marcadores, tiene una sensación de velocidad por el movimiento del background, un personajillo o nave que se mueve horizontalmente y que, además, puede disparar un proyectil. No hay enemigos ni nada más por ahora.

Pues aquí voy, he intentado comentar como buenamente he podido; notad que hay reciclaje de código y de "mecánica" de varios lados, especialmente de los propios ejemplos de Pocket Lucho y de los dos ejemplos más "juego" del paquete (galaxy y dscan). Creo que es una buena forma de ver una manera distinta de encajar las piezas que nos ha dado Lucho:


En sprites.c, solo tengo las tiles que hice yo. Que no haría falta tenerlas por separado. Son la araña y el disparo.

Código: [Seleccionar]
/* Start of tile array. */
const unsigned char sprite_data[] =
{
  0x00,0x00,0x02,0x00,0x32,0x20,0x09,0x01,
  0x05,0x01,0x02,0x07,0x75,0x4E,0x0B,0x0D,
  0x00,0x00,0x40,0x00,0x4C,0x04,0x90,0x80,
  0xA0,0x80,0x40,0xE0,0xAE,0x72,0xD0,0xB0,
  0xD0,0xB0,0xAE,0x72,0x40,0xE0,0x90,0x80,
  0x08,0x00,0x08,0x08,0x00,0x00,0x00,0x00,
  0x0B,0x0D,0x75,0x4E,0x02,0x07,0x09,0x01,
  0x10,0x00,0x10,0x10,0x00,0x00,0x00,0x00,
  0x00,0x00,0x80,0x80,0x80,0x00,0x80,0x00,
  0x40,0x80,0x80,0x00,0x80,0x00,0x80,0x00,
  0x00,0x00,0x01,0x01,0x01,0x00,0x01,0x00,
  0x02,0x01,0x01,0x00,0x01,0x00,0x01,0x00
};

/* End of SPRITES.C */

El resto está en main.c, que reconozco que no es ni de lejos un código limpio, ni eficiente, ni a prueba de bombas. De la facultad ya me habrían echado, pero ¡hay que empezar por algún lado!

Código: [Seleccionar]
#include <gb/gb.h>
#include "sprites.c"

#define FONT_OFFSET 128

/////////////////////////////////////////////////////
//
//  listado de tiles.
//  std_data y bkg_data/bkg_tiles han sido tomadas del ejemplo galaxy.c de GBDK
//  fonts viene de la imagen del tutorial de Pocket Lucho
//  sprites es de creacion propia, con la araña y el disparo
// 
/////////////////////////////////////////////////////

const unsigned char std_data[] = {

  /* Basic tiles (0xFC to 0xFF) */
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
  0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};


const unsigned char bkg_data[] = {

  /* Tile 0x00 */
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xF7,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xDF,0xFF,0xEF,0xFF,0xFF,0xF7,0xFF,0xFB,0xFF,0xFD,0xFF,0xFE,0xFE,0xFF,

  /* Tile 0x08 */
  0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xFE,0x7C,0x39,
  0xFF,0xFF,0xF7,0xFF,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFD,
  0xBB,0x01,0xC7,0x83,0xC7,0x83,0xC7,0x83,0xBB,0x01,0x7C,0x39,0x7D,0xFE,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
  0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFB,0xAF,0x77,0x27,0x8F,0xDF,0x8F,0x27,0x8F,

  /* Tile 0x10 */
  0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFB,0xFF,0xF7,0xEF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xBF,0xFF,0xDF,0xEF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFE,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xAF,0x77,0xFF,0xFB,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,

  /* Tile 0x18 */
  0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0x7D,0xFE,0x7C,0x39,
  0xFF,0xFF,0xF7,0xFF,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0x7F,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFD,

  /* Tile 0x20 */
  0xFF,0xFF,0xDF,0xFF,0xEF,0xFF,0xFF,0xF7,0xFF,0xFB,0xFE,0xFD,0xFD,0xFE,0xFE,0xFF,
  0xAB,0x11,0xC7,0x83,0x83,0xC7,0xC7,0x83,0xAB,0x11,0x7C,0x39,0x7D,0xFE,0xFE,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFB,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0x7F,
  0xFB,0xFF,0xFF,0xFD,0xFE,0xFE,0xFE,0xFF,0xFE,0xFE,0xFF,0xFD,0xFB,0xFF,0xFF,0xFF,
  0xEF,0xFF,0xFF,0xDF,0x3F,0xBF,0x3F,0x7F,0x3F,0xBF,0xFF,0xDF,0xEF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFB,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFD,0xFE,0xFE,0xFD,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,

  /* Tile 0x28 */
  0xF7,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};

/*
 * Image size: 0x40 x 0x40
 * Number of tiles (total - unique): 0x40 - 0x2D
 */

const unsigned char bkg_tiles[] = {
  0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC,
  0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A,
  0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC,
  0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14,
  0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC,
  0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20,
  0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26,
  0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
};

const unsigned char font[] ={
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x38,0x08,0x38,0x08,0x38,0x08,0x38,0x08,0x38,0x38,0x38,0x08,0x38,0x08,0x38,0x38,
  0x00,0x00,0x36,0x12,0x36,0x12,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x3E,0x02,0x7F,0x3D,0xFF,0x66,0xFF,0x5A,0xF7,0x52,0xFF,0x61,0xFF,0xBF,0x7F,0x41,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x1E,0x02,0x1C,0x14,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
  0x18,0x08,0x3C,0x04,0xFF,0x01,0xFE,0x82,0x7E,0x02,0x7E,0x12,0x7E,0x3A,0x66,0x66,
  0x00,0x00,0x0C,0x04,0x18,0x08,0x18,0x08,0x18,0x08,0x18,0x08,0x1C,0x14,0x0C,0x0C,
  0x00,0x00,0x18,0x08,0x1C,0x14,0x0C,0x04,0x0C,0x04,0x0C,0x04,0x1C,0x0C,0x18,0x18,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x18,0x08,0x18,0x08,0x7E,0x02,0x7E,0x6E,0x18,0x08,0x18,0x18,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x04,0x1C,0x04,0x1C,0x14,0x18,0x08,
  0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x02,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x04,0x1C,0x04,0x1C,0x1C,
  0x00,0x00,0x06,0x02,0x0E,0x02,0x1E,0x06,0x3C,0x0C,0x78,0x18,0x70,0x30,0x60,0x60,
  0x7E,0x02,0xFF,0x39,0xE7,0x21,0xE7,0x21,0xE7,0x21,0xE7,0x21,0xFF,0x83,0x7E,0x7E,
  0x1C,0x04,0x3C,0x04,0x3C,0x24,0x1C,0x04,0x1C,0x04,0x1C,0x04,0x3E,0x02,0x3E,0x3E,
  0x7E,0x02,0xFF,0x39,0xC7,0xC1,0x1E,0x02,0x7C,0x0C,0xF0,0x30,0xFF,0x01,0xFF,0xFF,
  0x7E,0x02,0xFF,0x39,0xC7,0xC1,0x3E,0x02,0x3F,0x39,0xC7,0x01,0xFF,0x83,0x7E,0x7E,
  0x0E,0x02,0x1E,0x02,0x3E,0x12,0x6E,0x22,0xFF,0x01,0xFF,0xF3,0x1F,0x01,0x1F,0x1F,
  0xFE,0x02,0xFE,0x3E,0xE0,0x20,0xFE,0x02,0xFF,0xF9,0xE7,0x21,0xFF,0x83,0x7E,0x7E,
  0x7E,0x02,0xFF,0x39,0xE7,0x27,0xFE,0x02,0xFF,0x39,0xE7,0x21,0xFF,0x83,0x7E,0x7E,
  0x7F,0x01,0xFF,0x79,0x8E,0x82,0x1C,0x04,0x1C,0x04,0x1C,0x04,0x1C,0x04,0x1C,0x1C,
  0x7E,0x02,0xFF,0x39,0xE7,0x21,0x7F,0x03,0xFF,0x39,0xE7,0x21,0xFF,0x83,0x7E,0x7E,
  0x7E,0x02,0xFF,0x39,0xE7,0x21,0x7F,0x01,0x0F,0x09,0xFF,0x39,0xFF,0x83,0x7E,0x7E,
  0x00,0x00,0x1C,0x04,0x1C,0x04,0x1C,0x1C,0x1C,0x04,0x1C,0x04,0x1C,0x1C,0x00,0x00,
  0x00,0x00,0x1C,0x04,0x1C,0x04,0x1C,0x1C,0x1C,0x04,0x1C,0x04,0x1C,0x14,0x18,0x08,
  0x00,0x00,0x0C,0x04,0x18,0x08,0x18,0x08,0x18,0x08,0x18,0x08,0x1C,0x14,0x0C,0x0C,
  0x00,0x00,0x00,0x00,0x7F,0x01,0x7F,0x7F,0x7F,0x01,0x7F,0x7F,0x00,0x00,0x00,0x00,
  0x00,0x00,0x18,0x08,0x1C,0x14,0x0C,0x04,0x0C,0x04,0x0C,0x04,0x1C,0x0C,0x18,0x18,
  0x3C,0x04,0x7E,0x3A,0x66,0x22,0x4E,0x46,0x1C,0x0C,0x18,0x18,0x18,0x08,0x18,0x18,
  0x7E,0x02,0xFF,0x7D,0xFF,0x41,0xFF,0x41,0xFF,0x41,0xFF,0x7D,0x7F,0x03,0x7E,0x7E,
  0x1C,0x04,0x1C,0x04,0x3E,0x02,0x3E,0x1A,0x7F,0x01,0x7F,0x3D,0xF7,0x10,0xFF,0xFF,
  0xFE,0x02,0xFF,0x99,0x77,0x11,0x7E,0x02,0x7F,0x19,0x77,0x11,0xFF,0x03,0xFE,0xFE,
  0x3E,0x02,0x7F,0x19,0x77,0x11,0x77,0x17,0x77,0x11,0x77,0x11,0x7F,0x43,0x3E,0x3E,
  0xFE,0x02,0xFF,0x99,0x77,0x11,0x77,0x11,0x77,0x11,0x77,0x11,0xFF,0x03,0xFE,0xFE,
  0xFE,0x02,0xFF,0x9D,0x73,0x13,0x7C,0x04,0x7C,0x1C,0x72,0x10,0xFF,0x03,0xFE,0xFE,
  0xFE,0x02,0xFF,0x9D,0x73,0x13,0x7C,0x04,0x7C,0x1C,0x70,0x10,0xF8,0x08,0xF8,0xF8,
  0x7E,0x02,0xFF,0x39,0xE7,0x21,0xE7,0x27,0xEF,0x21,0xEF,0x29,0xFF,0x81,0x7F,0x7F,
  0xFF,0x00,0x77,0x11,0x77,0x11,0x7F,0x01,0x77,0x11,0x77,0x11,0xFF,0x00,0x77,0x77,
  0x3E,0x02,0x3E,0x26,0x1C,0x04,0x1C,0x04,0x1C,0x04,0x1C,0x04,0x3E,0x02,0x3E,0x3E,
  0x1F,0x01,0x0F,0x03,0x0E,0x02,0x0E,0x02,0xEE,0x22,0xEE,0x22,0xFE,0x86,0x7C,0x7C,
  0xFF,0x09,0x7F,0x13,0x7C,0x04,0x78,0x08,0x7C,0x04,0x7E,0x12,0xFF,0x09,0xFF,0xFF,
  0xF0,0x00,0xF0,0x90,0x70,0x10,0x70,0x10,0x70,0x10,0x73,0x11,0xFF,0x03,0xFE,0xFE,
  0xE7,0x24,0xFF,0x99,0x7F,0x01,0x7F,0x01,0x7F,0x19,0x7F,0x19,0xFF,0x18,0xFF,0xFF,
  0xE7,0x20,0x77,0x11,0x7F,0x09,0x7F,0x01,0x7F,0x11,0x7F,0x19,0xF7,0x14,0x77,0x77,
  0x7E,0x02,0xFF,0x39,0xE7,0x21,0xE7,0x21,0xE7,0x21,0xE7,0x21,0xFF,0x83,0x7E,0x7E,
  0xFE,0x02,0x7F,0x19,0x77,0x11,0x77,0x11,0x7F,0x03,0x7E,0x1E,0xF8,0x08,0xF8,0xF8,
  0x7E,0x02,0xFF,0x39,0xE7,0x21,0xE7,0x21,0xFF,0x25,0xFF,0x3B,0xFF,0x85,0x7E,0x7E,
  0xFE,0x02,0xFF,0x99,0x77,0x11,0x7E,0x02,0x7F,0x19,0x77,0x11,0xFF,0x08,0xFF,0xFF,
  0x7E,0x02,0xFF,0x39,0xE7,0x27,0xFE,0x82,0x7F,0x79,0xE7,0x21,0xFF,0x83,0x7E,0x7E,
  0x7E,0x00,0xFF,0x66,0x1D,0x05,0x1C,0x04,0x1C,0x04,0x1C,0x04,0x3E,0x02,0x3E,0x3E,
  0xFF,0x10,0xFF,0x99,0x77,0x11,0x77,0x11,0x77,0x11,0x77,0x11,0x7F,0x43,0x3E,0x3E,
  0xE7,0x21,0xE7,0xA3,0x7E,0x12,0x7E,0x56,0x3C,0x04,0x3C,0x2C,0x18,0x08,0x18,0x18,
  0xFF,0x18,0xFF,0x99,0x7F,0x19,0x7F,0x01,0x7F,0x01,0x7F,0x19,0x77,0x35,0x63,0x63,
  0xF7,0x10,0xFF,0x99,0x7E,0x42,0x3C,0x24,0x3E,0x02,0x7F,0x19,0xF7,0x10,0xF7,0xF7,
  0xF7,0x10,0xF7,0x91,0x7E,0x42,0x3C,0x24,0x1C,0x04,0x1C,0x04,0x3E,0x02,0x3E,0x3E,
  0x7F,0x01,0xFF,0x73,0x1C,0x04,0x38,0x08,0x70,0x10,0xE2,0x20,0xFF,0x03,0xFE,0xFE,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0xFF,0x00,0x7F,0x7F,0xE7,0x20,0x77,0x11,0x7F,0x09,0x7F,0x11,0xF7,0x14,0x77,0x77,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x02,0x7E,0x7E};

/*
 * Image size: 0x10 x 0x70
 * Number of tiles (total - unique): 0x1C - 0x1C
 */
 
UBYTE time;         /* Global "time" value (counter) */
fixed bposx, bposy; /* Background position (fixed point) */
fixed bspx, bspy;   /* Background speed (fixed point) */
fixed sposx, sposy; /* Sprite position (fixed point) */
fixed sspx, sspy;   /* Sprite speed (fixed point) */

UBYTE pf, px, pp, pl,pbombs,plives; /*contadores diversos, de vidas, bombas, etc. Sin uso por ahora */
UWORD pw;
UWORD ps;


UBYTE missilex,missiley; /*posicion del mísil*/

void scroll();


(sigue a continuación, aunque los ficheros adjuntos están en este post)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: retromaquinitas en 03 Enero 2015, 22:24:31
Código: [Seleccionar]
/////////////////////////////////////////////////////
//  (del ejemplo de Pocket Lucho, lo aprovecharé en varios sitios)
//  void drawString(char str[], UBYTE x, UBYTE y){
//  dibuja la cadena str en la posicion x, y
//  en BKG si flag es 0 y en WIN si es 1
//  si una palabra no entra en la linea, la dibuja
//  en la siguiente
//
/////////////////////////////////////////////////////
void drawString( char *str, UBYTE x, UBYTE y, UBYTE flag ){

    UBYTE posx, strx, nextlen;
    UBYTE posy, e;
    UBYTE c;

    strx = 0;
    posx = x;
    posy = y;

    // mientras la cadena no termine
    while(str[strx] != 0){

        // comprueba la longitud de la palabra actual de la cadena
        nextlen = 0;
        for( e = strx; (str[e] != ' ') && (str[e] != 0); e++)
            nextlen++;

        // si no cabe en pantalla bajamos de linea
        if ( posx + nextlen > 20){
            posx = 0;
            posy++;
        }

        // dibuja la palabra en la posicion que corresponda
        for(;(str[strx] != ' ') && (str[strx] != 0); strx++){
            c = str[strx] + FONT_OFFSET - 32;
            if( !flag )
                set_bkg_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            else
                set_win_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            posx++;
        }

        // dibuja un espacio en blanco entre las palabras de la cadena
        if ( posx != 0 ){
            c = ' ' + FONT_OFFSET - 32;
            if( !flag )
                set_bkg_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            else
                set_win_tiles( posx, posy, 1, 1, (unsigned char *) &c);
            posx++;
        }

        // si no es el final de la cadena incrementamos la posicion
        if(str[strx] != 0 )
          strx++;
    }
}

//scroll para el background. Adaptación de galaxy.c

void scroll()
{
  /* Update background */
  bposx.w += bspx.w;
  bposy.w += bspy.w;
  SCX_REG = bposx.b.h;
  SCY_REG = bposy.b.h;
}

//muestra los diversos contadores: de nivel, de puntuación, de vidas y de bombas. Sin uso todavía.
//en realidad la mayoría de estas funciones no son necesarias por ahora;
//pero está preparado para cuando haga falta.

void show_level( UBYTE i )
{
  unsigned char level[1];

  if( i < 9 ) {
    level[0] = 0x31+i;
  } else {
    level[0] = 0x41+i-9;
  }
  //set_win_tiles( 19, 0, 1, 1, level );
  drawString("LV", 8, 0, 1);
  drawString(level, 10, 0, 1);
  //set_level( i );
}

void show_lives( UBYTE i )
{
  unsigned char lives[1];

  if( i < 9 ) {
    lives[0] = 0x31+i;
  } else {
    lives[0] = 0x41+i-9;
  }
  drawString("L", 12, 0, 1);
  drawString(lives, 13, 0, 1);
}

void show_bombs( UBYTE i )
{
  unsigned char bombs[1];

  if( i < 9 ) {
    bombs[0] = 0x31+i;
  } else {
    bombs[0] = 0x41+i-9;
  }
  drawString("B", 15, 0, 1);
  drawString(bombs, 16, 0, 1);
}

void show_score( UWORD s )
{
  UWORD m;
  UBYTE i, n, f;
  unsigned char score[6];

  f = 0; m = 10000;
  for( i=0; i<5; i++ ) {
    n = s/m; s = s%m; m = m/10;
    if( (n==0)&&(f==0) ) {
      score[i] = 0x20;      /* ' ' */
    } else {
      f = 1;
      score[i] = 0x30+n;    /* '0' - '9' */
    }
  }
  score[5] = 0x30;      /* '0' */
  drawString(score, 1, 0, 1);
  //set_win_tiles( 4, 0, 6, 1, score );
}

//inicializa

void init_score()
{
  ps = 0;
  show_score( ps );
  pp = 0; pl = 0;
  show_level( pl );
  pbombs=2;plives=2;
  show_lives(plives);
  show_bombs(pbombs);
}

//animación para el mísil

void animar_missile()
{
missiley=missiley-8;
move_sprite( 4, missilex, missiley );
move_sprite( 5, missilex-8, missiley );
}

//////////////////////////////////////////////////////
//
//  void main(){
//  punto de entrada
//
//////////////////////////////////////////////////////
void main(){

UBYTE i,j,winposx, winposy,c;
    UBYTE PosX = 80;
/* Initialize the background */
set_bkg_data(0xFC, 0x04, std_data);
set_bkg_data(0x00, 0x2D, bkg_data);
// cargamos los tiles de la fuente
set_bkg_data( FONT_OFFSET, 64,(unsigned char *)font);
  /*
   * Draw the background (y poner su correspondiente velocidad)
   *
   * Width  = 0x100 = 0x20 * 8
   * Height = 0x100 = 0x20 * 8
   */
  for(i = 0; i < 32; i+=8)
for(j = 0; j < 32; j+=8)
  set_bkg_tiles(i, j, 8, 8, bkg_tiles);
  bposx.w = 0;
  SCX_REG = 0;
  bposy.w = 0;
  SCY_REG = 0;
  bspx.w = 0x0000UL;
  bspy.w = 0xF800UL;
 
//aquí preparo la ventana. De base, lo pongo "en blanco". No creo que sea la forma más limpia de hacerlo.
c = ' ' + FONT_OFFSET - 32;
for( i=0; i<=20; i++ ) {
set_win_tiles( i, 0, 1, 1, FONT_OFFSET);
}
init_score();

//preparo los sprites
set_sprite_data( 0, 6, sprite_data);
set_sprite_tile( 0, 0);
set_sprite_tile( 1, 1);
set_sprite_tile( 2, 2);
set_sprite_tile( 3, 3);
set_sprite_tile( 4, 4);
set_sprite_tile( 5, 5);


//y coloco la nave (o araña). El argumento está por definir, jaja.
move_sprite( 0, 72, 136 );
move_sprite( 1, 80, 136 );
move_sprite( 2, 80, 144 );
move_sprite( 3, 72, 144 );


//muestro todo
        SHOW_BKG;
SHOW_WIN;
SHOW_SPRITES;
DISPLAY_ON;
enable_interrupts();

// bucle infinito

//las posiciones de la window (que solo se vea una línea) y el mísil no tiene posición.
winposx = 0; winposy = 136;
missiley=0;
while(1) {
// sincroniza la pantalla
for(i = 0; i < 4; i++)
wait_vbl_done();
time++;

//ejecuto scroll.

scroll();

//la velocidad del scroll se puede modificar con arriba/abajo mientras se presiona B.
//Está chulo. Incluso se invierte.
i = joypad();
if(i & J_B) {
  if(i & J_UP)
bspy.w -= 0x0010UL;
  if(i & J_DOWN)
bspy.w += 0x0010UL;
}

        // mueve el jugador
// mueve el sprite a la posicion x, y, siempre respectando el límite.
// lo hago a saltos de 16 aposta. La idea original para el juego tenía que ser así.
if(( i & J_LEFT )&& ( PosX > 16)){
PosX=PosX-16;
move_sprite( 0, PosX-8, 136 );
move_sprite( 1, PosX, 136 );
move_sprite( 2, PosX, 144 );
move_sprite( 3, PosX-8, 144 );
}
if(( i & J_RIGHT )&& ( PosX < 158)){
PosX=PosX+16;
move_sprite( 0, PosX-8, 136 );
move_sprite( 1, PosX, 136 );
move_sprite( 2, PosX, 144 );
move_sprite( 3, PosX-8, 144 );
}

//si se pulsa A, se dispara un mísil. Mantengo la posición X original almacenada
//para que el mísil no se mueva con la nave.
if(( i & J_A )){
missilex=PosX;
missiley=128;
move_sprite( 4, missilex, missiley );
move_sprite( 5, missilex-8, missiley );
}

//siempre que el mísil no haya llegado "al final", sigo animándolo.
if (missiley>0){
animar_missile();
}

//la ventana se tiene que mover para que no tape el background
move_win( winposx, winposy);
}
}

Pues eso es todo. Os adjunto los dos ficheros usados (en el post anterior), se puede compilar como cualquiera de los .bat de otros ejemplos del tutorial. El resultado debería ser el siguiente:

https://vine.co/v/OdeTDKwvdqE (https://vine.co/v/OdeTDKwvdqE)

Muchas funciones quedan todavía para implementar y la idea que tendría en mente es algo distinta. Ahora faltará más tiempo.

El caso es que si yo he podido hacer esto en unas cuantas horas, aquí hay más de uno que sabe mucho más que yo y que será capaz de programar el próximo Link's Awakening en unos pocos meses ;)

Espero que os animéis a subir más cosillas y así las vamos probando,

Marçal.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 04 Enero 2015, 12:52:49
Muchas gracios Marçal! Seguro que es muy util para animar a más gente a subir más cosas! A ver si subo la parte de sram y ya teneis todo lo necesario para hacer un juego completo ;)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: kalzakath en 13 Enero 2015, 02:38:26
Buenas Pocket, me he estado dando de cabezazos un par de horas intentando mover unos sprites por pantalla mientras hacía un marcador en Background Window, como en el ejemplo 6 del Tutorial. Después he visto el post de Marçal y digo, voy a ver cómo lo resuelve él, y me ocurre lo que adjunto, se ven los sprites pero no se ven los backgrounds.

¿Puede ser que tenga mal configurado el emulador?


EDITO: En casa con W7 me funciona bien, quizá sea problema del W8...
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: anjuel en 04 Febrero 2015, 12:27:22
Luchooo! gracias por el tuto, gracias a él y al señor na_th_an que me ha echado una mano he podido seguirlo y entenderlo :lol:

Deseando el siguiente capítulow! O0
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 05 Febrero 2015, 08:09:41
Muchas gracias tio! La verdad es que programar la maquineta en C es bastante sencillo ;) A ver si saco un rato y añado el capítulo de la sram y fin del tutorial!
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Jaji en 14 Abril 2015, 15:58:30
una preguntilla, sabeis si hay algun tracker que se acerque mas al sonido GB que el Milky¿?
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: D_Skywalk en 16 Abril 2015, 09:11:48
El otro día me dio un venazo de ponerme a trastear la gameboy y recordé algún comentario fugaz en fasebonus sobre este tutorial ¡¡ES FANTÁSTICO!! :)

En el vídeo alguno dice que el gbdk funciona igual en linux, pero claro al tener sus añitos en 64bits da problemas. He juntado varios repositorios para hacer una versión de gbdk compatible con la última ubuntu/64bits y la comparto en este paquetito: https://www.dropbox.com/s/jxw9u95xxsbgq4p/gbdk-linux-kit64_1.0.tar.bz2?dl=0 (https://www.dropbox.com/s/jxw9u95xxsbgq4p/gbdk-linux-kit64_1.0.tar.bz2?dl=0)

Sólo tenéis que editar el fichero devkit.sh con la ruta donde lo hayáis descomprimido y luego al ejecutarlo tendréis el entorno cargado. A parte he dejado en el primer ejercicio un compile.sh para que lo tengáis de referencia. Por supuesto para los emuladores necesitaréis tener instalado wine.

una preguntilla, sabeis si hay algun tracker que se acerque mas al sonido GB que el Milky¿?
http://www.delek.com.ar/deflemask (http://www.delek.com.ar/deflemask) va perfecto y es multiplataforma :)

Un Saludo y lo dicho, gracias pocket por el currele :D
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: D_Skywalk en 08 Junio 2015, 22:27:23
Como en mi convivencia con los compiladores de C retro he visto muchas cosas raras he hecho unas pruebas para ver que tipo de peculiaridades tiene el gbdk...
Estas pruebas que no tienen por que ser concluyentes, pero si ayudan a alguien más pues aquí quedan  O0


Pruebas de tamaño:
Código: [Seleccionar]
  if(level == 0)
    {
          ....
    }
    else if(level == 1)
    {
          ....
    }

a esta estructura:
Código: [Seleccionar]
    switch(level)
    {
        case 0:
                ....
            break;
        case 1:
                ....
            break;
    }
El código generado es 7 bytes menor.

Curioso lo de los bucles, este for ocupa ~19bytes...
Código: [Seleccionar]
for( x = 0; x != 18; x++ )
{
    ....
}
Igual que este while...
Código: [Seleccionar]
x = 0;
while( x != 18)
{
    ....
    x++;
}
Pero un do, while ocupa 2 bytes más :?
Código: [Seleccionar]
x = 0;
do
{
    ....
    x++;
}while( x != 18);
... curioso, no?

Sin embargo, si os valiera empezar desde el valor final...
Código: [Seleccionar]
x = 18;
do
{
    ....
} while(--x);
El código generado es 4 bytes menor

Luego hay que tener cuidado por que no vale para todas las situaciones pero...
Código: [Seleccionar]
if( ScrollXCnt == 8 )
Código: [Seleccionar]
if( ScrollXCnt & 8 )El código generado es 2 bytes menor.

Esto es un clásico pero si el módulo es potencia de dos...
Código: [Seleccionar]
temp = dx % 32;
Código: [Seleccionar]
temp = dx & (32 - 1);El código generado es 10 bytes menor.

Código: [Seleccionar]
#define ANCHO 64
...
dx = dy + dz + 21 + (ANCHO * 18);
Podría parecer lo mismo que...
Código: [Seleccionar]
#define ANCHO 64
...
dx = dy + dz + (21 + (ANCHO * 18));
¡Pues no! este es 8 bytes menor. Asi que intentad agrupar las constantes.

Código: [Seleccionar]
if(dx == 0)
Código: [Seleccionar]
if(!dx)El código generado es 5 bytes menor.


Luego sin diferencias en tamaño, pero quizás pudieran necesitar unas más ciclos que otras son:
Código: [Seleccionar]
dx = dy = 0;
dz++;
...
if ((dx == 1)&&(dy == 2))
...
if (dz < 1)
...
respecto a:
Código: [Seleccionar]
dx = 0;
dy = 0;
dz = dz + 1;
...
if (dx == 1) {
  if (dy == 2) {
...
if(dz != 1) //según la doc esto seria más rápido aunque ocupe lo mismo
...

Estas son las pruebas suyas las conclusiones ;)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: pocket_lucho en 08 Junio 2015, 23:26:48
Muy buenas pruebas! A ver si añado ciertas cosas que he aprendido, como la prioridad de los sprites que es rara de cojones...
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: anjuel en 08 Junio 2015, 23:27:41
Eso, que hay ganas de seguir el tuto y hacer alguna cosa :-)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: kalzakath en 08 Junio 2015, 23:48:12
Yo lo tengo parado porque en invierno programé un poquito con un portátil con w8 y no compilaba bien...

Enviado desde mi Amiga 500

Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: jrll en 09 Junio 2015, 10:00:49
Yo tengo pensado ponerme en serio con este tutorial cuando termine de refinar mis conocimientos básicos de C.
A ver si ahora con el verano puedo ponerme a mirarlo con tranquilidad y, si no se me hace muy cuesta arriba, lograr hacer algo para la Game Boy.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: luckpro en 09 Junio 2015, 12:32:56
El maravilloso mundo de los compiladores... son raros de cojones jejejeje.

En cualquier caso creo que el hecho de que ocupe menos bytes en memoria no tiene porque significar que vaya más rápido el juego, así que yo trataría de hacer el juego completo y que funcione bien y si no entra en memoria entonces buscaría este tipo de optimizaciones.

Dale caña que estamos ansiosos por ver resultados ;-)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: jrll en 09 Junio 2015, 13:37:37
Por cierto, pocket_lucho, ¿tienes algún juego en desarrollo para Game Boy actualmente?
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: doragasu en 09 Junio 2015, 14:49:40
No siempre es así, pero normalmente cuando ocupa menos también es más rápido. En muchas arquitecturas hacer los bucles descendentes y acabando en 0 es más rápido porque es más rápido (y ocupa menos espacio) hacer la comparación con 0, que hacerla con cualquier otro valor (utilizas la instrucción de salto condicional dependiendo del flag Z, y te ahorras la comparación con un valor específico). Algunas arquitecturas como el 68000 incluso tienen una instrucción que decrementa un registro y salta según el valor del flag Z.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: D_Skywalk en 09 Junio 2015, 16:55:31
En cualquier caso creo que el hecho de que ocupe menos bytes en memoria no tiene porque significar que vaya más rápido el juego
Claro, la idea no es ir contando el byte en cada función que hagas, pero en las que son clave o donde creas que ciertas optimizaciones mejoran el gameplay, saber con que puedes "jugar" ;)

Tirando de media, un algoritmo 10 bytes menor será bastante más rápido que el largo (mismo tipo de bucle, sin unloop).

No siempre es así, pero normalmente cuando ocupa menos también es más rápido. En muchas arquitecturas hacer los bucles descendentes y acabando en 0 es más rápido porque es más rápido (y ocupa menos espacio) hacer la comparación con 0
Recuerdo las cosas raras que hacia el compilador del speccy, en este la que más me ha sorprendido ha sido lo de "!0" vs "x == 0", que haya una diferencia de 5 bytes O_O!

Me gusta optimizar mi C, por que creo que un C bien escrito tampoco está tan lejano a un ASM mediocre como el que pudiera llegar a programar yo XD

Bueno, mientras pocket se anima a seguir, voy a ver que hago con este scroll über optimizado :)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: livekraft en 27 Junio 2015, 08:49:36
Lo guardaré en el marcador del navegador para leer con calma todo por la mañana.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Mills en 12 Noviembre 2015, 19:28:42
Espero que no esté abandonado este hilo :)

Yo empecé a programar en C con GBDK, ni soy programador ni nada parecido, pero conseguí cosas muy buenas.

Hice esa demo tan fea, que intenta imitar a "second reality" que lei unos mensajes atras... (y los puristas del ASM casi me mandan a la hoguera jaja), pero bueno, se demostró que algo se podia hacer con este GBDK.

He llegado a "dominar" un poco la creación de mapas y de mod's con el software de antonio, pero uno tiene sus límites.

Voy a poner un link con todo el source de lo que conseguí.

Primero del "second reality": en el utilicé todo lo que sabía del GBDK. Lo estaba mejorando, pero como todos los efectos al final son videos imitando los efectos originales, es muy costoso ir frame a frame componiendolos. Asi que si a alguien le interesa, aquí lo dejo, esta desordenado y no funcionan todas las escenas, hay que ir probando una a una con la variable "program" porque las fui cambiando.

El video final es solo una sucesion de imagenes que dibujan la pantalla completa, y es lento, Pero algunas de las escenas pueden utilizar solo un set de tiles, y después reordenarlos para formar frames a 60FPS. Un programa que puede convertir un video en un set de tiles y varios mapas, es el "cosmigo pro motion" pero no es gratis y aun consiguiendolo, no he sido capaz de convertir un video para Game Boy.


El segundo es el efecto highcolour, que puede mostrar imágenes con muchos colores en GBC, para convertir la imagen se necesita el highcolor converter, espero que aún esté por la red.

El tercero es una escena con vectores, a medias....

El cuarto es un ejemplo de como reproducir wav en gameboy, hay una carpeta con conversores, las instrucciones creo que están en inglés.

El último es un efecto que se ve en muchos demos, para mover cada scan line de forma independiente y producir efectos como ondas o en este caso un efecto 3D.

Todos han llegado a funcionar en mi game boy color con un cartucho usb de 8 Megas(dividido en dos memorias de 4, asi que un demo de 8 no se puede cargar, pero ningun juego original era mayor de 4...).

https://dl.dropboxusercontent.com/u/757056/GBC/TESTS.rar


Todos los sources son un poco desastre, además yo no soy programador jaja, pero espero que sirvan, y desde luego se pueden mejorar mucho y hacerlos más rápidos.

Existe un optimizador para GBTD y GBMB llamado Gameman039a.exe para reducir el tamaño de imagenes convertidas en fondos.


Por cierto, nunca conseguí el scroll en mapas grandes, me da error en la parte que no comprendo... justamente aqui:
Código: [Seleccionar]
set_bkg_tiles( 0, tempa, 22, 1, &(map_data+Cnt));


Ese & da error y los mapas los he creado con las mismas herramientas y estan declarados igual que en el ejemplo, a ver si me ayudais, porque pensaba hacer un "mario" con un fondo bastante grande.

Saludos
Título: TUTORIAL 1985ALTERNATIVO EN C DE LA GAMEBOY : SCROLL DE FONDOS GRANDES
Publicado por: Mills en 18 Noviembre 2015, 20:12:27
Tomando ideas de este tutorial, de la parte de scroll, conseguí hacerlo en la game boy con GBDK, aunque de manera un poco diferente.

Lo que he hecho, es rellenar sólamente una columna/fila, (la que va a aparecer en la pantalla). Además lo hace en dos fases o frames, ya que si lo hago en uno, es demasiado lento para GBDK.

De momento funciona solo es scroll hacia adelante, como en el primer super mario land, sin posibilidad de volver hacia atrás. Pero no hay impedimento para que funcione en todas direcciones, de hecho lo he probado para medir el uso de cpu, aunque no se vea bien.

[attach=1]

En la imagen adjunta, vemos un mapa de 128x128 moviendose, y la CPU utilizada, tanto en DMG(verde) como en CGB (naranja) con diferentes supuestos:

1-No está rellenando columnas  /filas
Tenemos practicamente toda la CPU libre.

2-Está rellenando sólamente una columna / fila
Cada 8 frames ,al movernos 8 píxeles, rellena una columna o una fila que va a aparecer en la pantalla. Esto ocurre si nos movemos sólamente en una única dirección (horizontal o vertical).

Si estamos en CGB, necesitamos casi el doble de CPU, para rellenar también las paletas de cada posición.

3-Está rellenando una columna y una fila
Esto ocurre si nos movemos en dos direcciones a la vez, (en diagonal), con lo que rellenamos la columna y la fila que van a aparecer, y requiere mas o menos el doble de CPU.

Optimización
Podemos hacer que cada línea se dibuje en un máximo de 4 frames, ya que si nos movemos en diagonal, necesitaremos 8 frames, 4 para una fila y los 4 siguientes para una columna por ejemplo.



Subiré el source mañana o pasado :)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Colivenc en 09 Diciembre 2016, 21:33:38
Primero de todos felicitar al autor del hilo por su excelente trabajo.

Buenas me presento, soy un programador que ha empezado a hacer sus pinitos con esta consola. No se si el hilo sigue vivo, pero os aseguro de que lo visito asiduamente.

Os paso un vídeo de mi proyecto, o mas bien, mis primeras pruebas conteste SDK
https://www.youtube.com/watch?v=CA_iFVuBfGo (https://www.youtube.com/watch?v=CA_iFVuBfGo)

A margen de eso, me estoy encontrado con problemas para usar la función malloc(), directamente peta todo, pese a que compila (Con advertencias) Si alguien pudiera echarme un cable se lo agradecería.

Saludos
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: luckpro en 12 Diciembre 2016, 08:48:27
No he usado aun el sdk de gameboy, pero dime que te ocurre con el malloc a ver si puedo ayudarte en algo.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Colivenc en 18 Diciembre 2016, 13:45:56
No he usado aun el sdk de gameboy, pero dime que te ocurre con el malloc a ver si puedo ayudarte en algo.
Bueno sencillamente que el compilador lanza el warning "function 'malloc' implicit declaration", pese que aque tengo añadidas las librías <stdlib.h> y luego el juego peta por todos lados.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: luckpro en 19 Diciembre 2016, 10:44:05
A mi nunca me ha dado un error parecido pero por el mensaje y por lo que comenta la gente por internet se ve que...

- o estas llamando al malloc antes de incluir la stdlib.

- o estas modificando la definición del malloc después de incluir la stdlib (quizás alguna otra lib que incluyas la este modificando) recuerda que la definición de malloc es void *malloc(size_t) si tus libs no deberían tener otra cosa diferente. Entra dentro de tu stdlib a ver que tiene.

- o tienes el include del malloc dentro de un ifdef o condicionales de este tipo.


De todas formas es un warning no un error. ¿Te falla siempre cuando ejecuta el malloc? ¿has probado a poner un numero más pequeño de memoria, 2 o 3 bytes (lo mismo esta petando por sobrescribir memoria que no debe)?


Ánimo, a ver si lo puedes solucionar.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Colivenc en 01 Enero 2017, 18:02:50
A mi nunca me ha dado un error parecido pero por el mensaje y por lo que comenta la gente por internet se ve que...

- o estas llamando al malloc antes de incluir la stdlib.

- o estas modificando la definición del malloc después de incluir la stdlib (quizás alguna otra lib que incluyas la este modificando) recuerda que la definición de malloc es void *malloc(size_t) si tus libs no deberían tener otra cosa diferente. Entra dentro de tu stdlib a ver que tiene.

- o tienes el include del malloc dentro de un ifdef o condicionales de este tipo.


De todas formas es un warning no un error. ¿Te falla siempre cuando ejecuta el malloc? ¿has probado a poner un numero más pequeño de memoria, 2 o 3 bytes (lo mismo esta petando por sobrescribir memoria que no debe)?


Ánimo, a ver si lo puedes solucionar.

No hay solución. Es tan sencillo como se usando el GBDK no se pueden alojar datos en el heap.
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Colivenc en 01 Enero 2017, 18:09:11
Por otro lado estoy documentado parte de mis impresiones y vivencias usando el GBDK, así que me gustaria compartir esta información que creo que es de interes general.

http://4way-studio.blogspot.com.es/2016/12/super-pepetoni-making-off-programacion.html (http://4way-studio.blogspot.com.es/2016/12/super-pepetoni-making-off-programacion.html)
http://4way-studio.blogspot.com.es/2016/12/super-pepetoni-making-off-2-combate.html (http://4way-studio.blogspot.com.es/2016/12/super-pepetoni-making-off-2-combate.html)
http://4way-studio.blogspot.com.es/2017/01/super-pepetoni-making-off-3-sprites.html (http://4way-studio.blogspot.com.es/2017/01/super-pepetoni-making-off-3-sprites.html)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: josepzin en 11 Diciembre 2017, 13:13:45
Dejo este enlace aquí, que está relacionado: Making a Game Boy game in 2017: A "Sheep It Up!" Post-Mortem (part 1/2)

https://www.gamasutra.com/blogs/DoctorLudos/20171207/311143/Making_a_Game_Boy_game_in_2017_A_quotSheep_It_Upquot_PostMortem_part_12.php

(https://www.gamasutra.com/db_area/images/blog/311143/sheepitup.gif)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Jose81 en 24 Junio 2018, 04:42:14
Buenas, alguien tendrá un link funcional del paquete con extras?
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: RetroSwan en 01 Mayo 2019, 16:05:58
Saludos a todos. Lo primero dar las gracias por este hilo. desde que escuché un antiguo podcast donde se hablaba de este hilo, me entró la curiosidad, y aunque nunca he programado, para mi un "hola mundo" -también a raíz de ésto he leído/visto algo de programación e C- ha sido toda una satisfacción. El problema es que los enlaces del principio están caídos y aunque he podido buscarlos por otros sitios, no encuentro el "pandocs.txt" que se supone que es una especie de manual de la librería de Nintendo. estaría muy agradecido si alguien lo resubiera o me lo mandara.
Muchísimas gracias por despertarme la curiosidad
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: RetroSwan en 05 Mayo 2019, 17:57:05
Atención a este señor, que aunque está en inglés es bastante revelador:

https://www.youtube.com/channel/UCMMhSfBStEti-Lqzs30HYWw (https://www.youtube.com/channel/UCMMhSfBStEti-Lqzs30HYWw)
Título: Re:TUTORIAL 1985ALTERNATIVO SOBRE PROGRAMACION EN C DE LA GAMEBOY
Publicado por: Zael en 05 Mayo 2019, 18:14:25
¡Hola @RetroSwan, bienvenido a FaseBonus! Como tú dijiste, por desgracia parece que los enlaces de este hilo están ya caducados.

Si estás interesado en programar para Gameboy te recomiendo que le preguntes al compañero Imanolea, que está programando un juego tremendo llamado Last Crown Warriors. Aquí puedes ver el hilo de su juego...


(http://www.fasebonus.net/foro/index.php?action=dlattach;topic=38300.0;attach=17357;image)

http://www.fasebonus.net/foro/index.php?topic=38300.0


Seguro que él te podrá dar enlaces de documentación y tutoriales para programar en C en Gameboy. Si no consigues contactar con él a través del Foro búscalo a través de su blog, Twitter o demás, seguro que podrá ayudarte.

Y si te decides a empezar algún proyecto no dudes ponerlo por aquí en el Foro, aunque está un poco "caído" ya aún quedamos unos cuantos con ganas de compartir hobbies por aquí.

¡Saludos y bienvenido!



P.D.: Si quieres, también puedes presentarte formalmente y contarnos un poco más sobre ti y tus aficiones en el hilo de presentaciones del Foro... ¡Bienvenido!  :)

http://www.fasebonus.net/foro/index.php?board=4.0