Programacion en DS. Sprites, rotacion y escalado.

Hola!
Poquita cosa hoy, ya que las funciones de rotacion y escalado del sprite son tan simples como indicarle al OAM (Object Attribute Memory) que Rotset de los 32 disponibles por pantalla queremos asignarle al sprite y luego solo decirle al rotset correspondiente que valor queremos para el angulo y escalado.
Como las Libnds usan valores para la rotacion de entre -32768 y 32768, he decidido pegarle un bitshift para poder usar valores entre -512 y 512 (suficientes digo yo), ademas decorregir que los valores positivos giren a la derecha y los negativos a la izquierda (en las libnds se interpreta al reves, que cosas). El factor de escalado se mueve entre el 0 y el 512, siendo 256 el valor central, que equivale a una escala del 100%
 

 
Los valores de escalado que usan la libnds me han parecido correctos, salvo que para ellos el 512 significava reducir la escala, la cual cosa he invertido, siendo 0 el valor mas pequeño y 512 el mayor.
Como novedad comentaros que dentro de la carpeta DOCS del proyecto encontrareis un documento de WORD con el manual que estoy realizando de esta libreria. Ademas el manual indica en que archivo se encuentra cada funcion, para asi ayudaros a localizarla si quereis aprender como la he realizado.
 
Los pequeños fallos en el escalado de sprites son normales, ya que el efecto esta realizado de manera aleatoria y no contempla el tamaño maximo del sprite para rotaciones.
 
La descarga de proyecto de hoy: NightFox’s Lib para Libnds 20090430
 
Un cordial saludo y os recuerdo que podeis dejarme vuestras dudas y sujerencias en los comentarios.
 
Hasta la proxima

NightFox

Programacion en DS. Fondos (casi) Infinitos en todas direcciones. (Beta)

Hola,
Entrada cortita. Os dejo un video sobre como va funcionando el tema de mover un fondo casi infinito en cualquier direccion. La teoria es muy similar a la que os comente en la anterior entrada. Como supongo que habra algun bug, dado que tengo que testearlo con mas fondos, de momento disfrutar de el video que os dejo
 

 
y la descarga del proyecto tal como lo tengo ahora.
He añadido soporte para el Pad de la DS, con el que moveremos el scroll de la pantalla de arriba.
 
Descarga del Proyecto: NightFox Lib para Libnds 20090426
 
Un cordial saludo y si podeis testearlo con vuestros fondos, me hareis un favor.
 
NightFox

Programacion en DS. Fondos muy largos (casi infintos)

¡Hola!
Pues vamos avanzando. Estos días he estado trabajando en solucionar una de las limitaciones más grandes de la DS. El tamaño de los fondos. Como sabéis, el tamaño máximo de los fondos en la DS es de 512×512 pixeles, esto son, dos pantallas. En algunos juegos esto puede pasar desapercibido y no ser un problema, pero en juegos con scroll, plataformas, mata marcianos, rpg’s, pues si es un problema (¿Os imagináis un Castlevania o un R-Type con decorados de solo 2 pantallas de largo?).
La solución, engañar a la DS. Vale si, ¿pero cómo? Fácil, le daremos el cambiazo cuando este despistada.
Si repasáis los anteriores tutoriales, sabéis que los fondos se dividen en 3 partes, los tiles, el mapa y la paleta. El problema lo tenemos con el tamaño del mapa, que es el que le dice a la DS donde tiene que colocar cada tile del fondo en la pantalla y que como mucho puede ser de 512×512 pixeles (64×64 tiles). Dado que los tiles y la paleta van a su bola, mientras no usemos más tiles de los que caben en memoria, nuestro fondo, si nos lo montamos bien, puede ser virtualmente infinito (vamos, mientras tengamos RAM libre…).
Pongamos por ejemplo que vamos a hacer un juego de plataformas de desplazamiento horizontal y que como mucho, tenga una pantalla de alto (entre 192 y 256 pixeles de alto). A la DS le informaremos cuando creamos el fondo que usara un mapa del tipo BG_64x32 (64 tiles de largo, 32 tiles de alto). Esto configura la VRAM para guardar dos bloques consecutivos de 32×32 tiles, (es decir, dos veces lo necesario para llenar una pantalla entera). Ahora imaginemos que tenemos nuestro fondo muy largo de, por ejemplo, 2000 pixeles. Ala, loco, pero si acabas de decir que lo maximo que podemos cargar son 512… Pues ahí es cuando tenemos que engañar a la DS cuando este despistada.
Le hemos dicho a la DS que nuestro fondo es de 512×256 (es mentira, pero es lo que mas se acerca a la realidad) con lo cual, nos configurara los bancos de VRAM para mapas en dos bloques de 32×32 tiles, llamemoslos bloque 0 y bloque 1. Si el fondo esta al principio de todo, en pantalla veremos el contenido del bloque 0 y a la derecha, oculto quedara el contenido del bloque 1.
Internamente en VRAM, el bloque 0 iria de la posicion 0 a la 2047 (32x32x2 = 2048) que es el resultado de multiplicar 32 tiles de ancho por 32 tiles de alto por 2, ya que cada tile ocupa 2 bytes de memoria. El bloque 1 iria de la posicion 2048 a la 4095. Con lo que 1 set entero ocupa 4096 bytes de memoria (4kb).
Ahora si nos movemos hacia la derecha, se empezara a mostrar el contenido del bloque 1, pero al cabo de moverse 256 pixeles, se acabo lo que se dava y se nos termina el mapa. En ese punto, es cuando le daremos el cambiazo.
Cuando GRIT nos convierte los mapas, los coloca en el archivo en ese formato, bloques consecutivos de 32×32 pixeles. Como tenemos todo el mapa en RAM dividido en bloques, es facil, cada vez que te desplaces 256 pixeles (1 bloque) sencillamente actualizaremos el contenido de la VRAM.
Al principio, cuando creamos el fondo, copiamos a la VRAM el contenido del buffer en RAM comprendido entre las posiciones 0 y 4095 (dos bloques). Cuando llegamos a la posicion 256 del mapa ¿que hacemos? Facil, volver a copiar desde la RAM dos bloques, pero empezando en la posicion 2048, asi que copiariamos en la VRAM el contenido de los bloques 1 y 2. ¿Nos movemos hasta el pixel 512? Pues copiamos el contenido de dos bloques empezando en la posicion 4096, copiando asi el contenido de los bloques 2 y 3.
Para hacer esto mas facil, he calculado que según la posicion del fondo, me diga que bloque esta en pantalla, el calculo, es muy sencillo:
 
bloque = (int)(x / 256);

 (luego ya lo pasare a bitshit)
 
Para no estar constantemente copiando datos, creamos otra variable de control, del tipo bloque_anterior.
Con un:
 
if (bloque != bloque_anterior) {
            posicion_inicio_en_ram = 2048 * bloque;
            bloque_anterior = bloque;
}
 
Asi solo copiaremos los datos en caso de cambiar de bloque en pantalla.
Haciendo esto lo que hacemos es que cambiamos el contenido del bloque 0 por el del 1 y el del bloque 1 por el del 2.
Ahora solo falta retroceder el scroll lo necesario para que cuadre
 
sx = x – (bloque * 256);
 
Y pasarle el resultado al registro de scroll.
 
En resumen, lo que hacemos es movernos el equivalente a 1 pantalla, copiar lo que vemos actualmente a la pantalla que hemos dejado atras, movernos a la posicion original y copiar el nuevo contenido a la pantalla que ahora nos queda delante.
Parece un poco lioso, asi que si no lo acabais de pillar, me dejais un comentario y mirare explicarlo de otra manera.

El codigo que he puesto aquí es meramente informativo, en el proyecto adjunto esta el de verdad con sus comentarios.
En caso de que el scroll fuera vertical, pues es lo mismo, solo que controlando el cambio de bloque por la coordenada Y.
 Aquí teneis el video de el resultado
 

 

Internamente la DS organiza la VRAM para mapas como sigue (en tiles)
512×256 = (32×32) + (32×32)
256×512 = (32×64)
 
Lo complicado viene cuando queremos movernos en ambas direcciones y usamos el setup de mapas en modo 512×512, ya que la memoria se configura en 4 bloques a la vez de 32×32, es decir (32×32)+ (32×32)+ (32×32)+ (32×32) y es en lo que me empezare a pelear mañana.
 
De momento, aquí os dejo el proyecto listo para vuestro disfrute y aprendizaje.
 
Descargar: NightFox’s Lib para Libnds 20090423
 
Un cordial Saludo y hasta la siguiente entrada
 
NightFox

Programacion en DS. Sprites animados, ahorro de VRAM

Hola!
 
En la entrada de ayer os enseñe la teoria del uso de Sprites animados.
En el ejemplo de ayer teniamos un problema grave (es un decir) de cara a la conservacion de recursos.
Nuestro personaje tenia un tamaño de 32×64 pixeles, eso son 2048 bytes por frame. Dado que la animacion tenia 12 frames esto nos da 24576 bytes, vamos 24kb.
Dado que la DS tiene poca VRAM y nosotros le hemos asignado 128kb por pantalla para los Sprites, nos damos cuenta que si todos los Sprites animados ocupan esa barbaridad, lo llevamos claro. Solucion, mantener en RAM los frames no utilizados, teniendo solo en VRAM el que queramos usar (con lo que pasaremos de ocupar 24kb a 2kb). Problema, (siempre tiene que haber alguno, ¿no?) todos los sprites que usen ese Grafico, mostraran el mismo frame de animacion, asi que vosotros sobre la marcha vereis segun que Sprites que os conviene mas.
 

 
En este video, si os fijais (si no, ejecutais la rom compilada del proyecto, que para algo esta) vereis como los sprites de la pantalla superior van al unisono mostrando el mismo frame y que los de la pantalla inferior van a su bola. La diferencia es que los 4 personajes de la pantalla superior nos consumen 2kb contra los 24kb que consumen lo de la inferior.
 
En mi libreria he añadido un parametro a la funcion:
 
void NF_VramSpriteGfx(u8 screen, u16 ram, u8 vram, bool keepframes);
 
El parametro "keepframes" indicara si deseamos conservar los frames en RAM (true) o copiarlos todos en VRAM (false).
Si queremos usar la primera opcion y mantenerlos en RAM, tener en cuenta (logicamente) que no podremos borrarlos de ahi mientras los usemos.
 
La funcion de animacion de sprites ha quedado al final como sigue:
 

// Funcion NF_SpriteFrame();

void NF_SpriteFrame(u8 screen, u8 id, u8 frame) {

// Verifica el rango de Id’s de Sprites

if ((id < 0) || (id > 127)) {

NF_Error(106, "Sprite", 127);

}

// Verifica el rango de frames del Sprite

if (frame > NF_SPRITEOAM[screen][id].lastframe) {

NF_Error(106, "Sprite frame", NF_SPRITEOAM[screen][id].lastframe);

}

 

// Si debes de copiar el nuevo frame desde la RAM a la VRAM…

if (NF_SPR256VRAM[screen][id].keepframes) {

// Variables temporales

char* source; // Puntero de origen

u32 destination = 0; // Puntero de destino

u16 ramid = 0; // Slot de RAM donde se encuentra el Gfx

// Calcula el origen y destino del nuevo frame a copiar

ramid = NF_SPR256VRAM[screen][NF_SPRITEOAM[screen][id].gfxid].ramid;

source = NF_BUFFER_SPR256GFX[ramid] + (NF_SPRITEOAM[screen][id].framesize * frame);

destination = NF_SPR256VRAM[screen][NF_SPRITEOAM[screen][id].gfxid].adress;

// Copialo

memcpy((void*)destination, source, NF_SPRITEOAM[screen][id].framesize);

} else { // Si todos los frames ya estan en VRAM…

// Calcula la direccion del Gfx del frame

u32 adress = 0;

adress = NF_SPR256VRAM[screen][NF_SPRITEOAM[screen][id].gfxid].adress + (NF_SPRITEOAM[screen][id].framesize * frame);

NF_SPRITEOAM[screen][id].gfx = (u32*)adress;

}

}
 
Y eso es todo por hoy.
Aqui la descarga del proyecto: NightFox’s Lib 20090419 
 
Un saludos a todos,
 
NightFox

Programacion en DS. Animacion basica de Sprites

Hola!
 
Pues si, como os prometi, hoy tenemos animaciones.
La cosa es mas bien tonta, os cuento:
Para crear un Sprite animado debemos hacer una tira, del ancho de nuestro sprite y del alto equivalente a la altura del mismo por el numero de frames. Asi, si queremos crear un personaje animado, que mide 32×64 pixeles y que tendrá 5 frames, nuestro grafico medira 32×320. Asi es que colocaremos cada frame encima del otro, sin espacios.
La DS coloca los tiles de este grafico en fila, uno detrás del otro. Para poder crear una animación, necesitaremos saber 3 cosas,
 
1. El puntero donde se guarda este grafico
2. El tamaño en bytes de cada frame
3. Cuantos frames tiene la animación (para no pasarnos)
 
Vale, como cuando cargamos el grafico desde la VRAM, pido que metáis el alto y ancho en pixeles y sabiendo que la DS carga los graficos convertidos en tiles de 8×8 pixeles, haremos lo siguiente:
 
tiles_ancho = ancho / 8
tiles_alto = alto / 8
total_tiles = tiles_ancho * tiles_alto
tamaño_en_bytes_del_frame = (tiles_ancho * tiles_alto) * 64
 
Vale, después de esta empanada mental, os cuento el porque de estas “mates?”
Dividimos por 8 para saber el numero de tiles del frame, por que cada tile son 8 pixeles.
Sabiendo cuanto mide en tiles el sprite, multiplicamos la anchura por la altura y sabremos el numero total de tiles que tiene el sprite, por lo tanto, cuanto mide en tiles el frame.
Luego viene multiplicar por 64, ¿Por qué? Puesto que tenemos que calcular lo que ocupara en la VRAM cada frame, este se guarda en tiles y cada tile es de 8×8 pixeles, pues es evidente, 8 X 8 = 64.
Asi que nuestro sprite de 32×64 seria:
32 / 8 = 4
64 / 8 = 8
8 * 4 = 32
32 * 64 = 2048
 
Veis, ahora sabemos que cada frame de nuestro sprite ocupa 2048 bytes (2kb).
Como cuando cargamos el Grafico en memoria, mis funciones guardan el tamaño en bytes del mismo, asi que para saber cual será el ultimo frame de la animación, asumiendo que el primero es 0, haremos lo siguiente:
(tamaño_total / tamaño_frame) – 1
 
Esto seria:
10240 / 2048 = 5
5 – 1 = 4
Asi pues, el primer frame de la animación será 0 y el ultimo 4.
Empezamos por 0 por razones practicas que explicare ahora mismo.
Supongamos que cuando cargamos el grafico en VRAM este queda cargado en la posición 1024 (por ejemplo, no es real la dirección).
Cuando creamos el sprite, las funciones (o tu si lo haces a mano) le cuentan al OAM (Object Attribute Memory)  que el sprite es de 32×64 pixeles y que el grafico se encuentra en la posición 1024.
Como le has dicho que es de 32×64, la DS solo lee de la VRAM los tiles necesarios para mostrar ese Sprite de ese tamaño, dejando el resto de tiles de la animación de ese sprite en la VRAM sin tocarlos.
¿Como mostraremos el frame que queramos? fácil, cambiando la dirección donde empieza a leer los tiles en el OAM.
Sabiendo que frame queremos mostrar, lo que ocupa cada frame en bytes y la dirección de inicio, es fácil
 
dirección = 1024 + (frame * tamaño)
 
Eso es:
 
dirección = 1024 + (3 * 2048)
dirección = 7168
 
Como la DS seguirá cargando los tiles para mostrar un sprite de 32×64, mostrara el 4to fotograma (el primero es 0 el primero). Asi que para cambiar de frame en la animación, solo es cuestión de multiplicar, sumar y pasarle el resultado a la OAM.
 
Mi función usa una cosa algo mas avanzada para el calcula, llamado bitshift
 
u8 width = 0;
u8 height = 0;
width = (NF_SPR256GFX[ram].width >> 3);  
// (width / 8)
height = (NF_SPR256GFX[ram].height >> 3);
// (height / 8)
NF_SPR256VRAM[screen][vram].framesize = ((width * height) << 6); // ((width * height) * 64)

 
Dado que la DS no tiene unidad de coma flotante, quiere decir que se le da fatal lo de dividir, asi que siempre que puedas, usa el bitshift para hacer divisiones o multiplicaciones de base 2
(X / 8 es lo mismo que X >> 3 y X * 64 seria X << 6).
 
Y poquita cosa mas, os dejo un video de cómo van las animaciones y el proyecto completo ^^
 

 
 

A si, la función que he creado para cambiar de frame es:
 

void NF_SpriteFrame(u8 screen, u8 id, u8 frame);
Cambia el frame de un Sprite

Debes especificar la pantalla, el Id del sprite y el frame
 
Descarga del proyecto aquí: NightFox’s lib 20090418
 
 
Un saludo
 
NightFox

Programacion en DS. Sprites

Hola!
Mas cosas que he hecho con las LIBNDS. Los Sprites.
Antes que nada y en vistas de las descargas de los proyectos (casi nulas) y los (ninguno) comentarios y debido a que prefiero en ese caso invertir mi tiempo en desarrollar que en hacer tutoriales que no se mira ni dios, voy a optar por ir publicando los proyectos de la libreria que estoy haciendo para DS, que total, a los que realmente les interese, con lo que he comentado el codigo aprenderan a programar en libnds y los demas, pues seguro que usaran sin miramientos las funciones de mi libreria, con lo que todos contentos y yo mas descansado.
Eso si, cualquier duda, ruego o suplica, a los comentarios, que los respondere encantado (o no).
 
Dicho esto, hoy tocan: LOS SPRITES
 
Despues depegarme 3 dias, he conseguido hacer unas funciones minimamente decentes para la creacion y movimiento de Sprites en pantalla.
Ya puestos a liarla, la liamos gorda, eso es, un engine que permite cargar desde la FAT a RAM hasta 256 graficos para la creacion de sprites, 64 paletas para estos y la autogestion de la VRAM cuando creemos estos Sprites.
 
He estado realizando pruebas cargando 5 graficos diferentes con 5 paletas (o sea, al igual que los fondos, a tocado usar paletas extendidas) y he puesto en pantalla, repartido entre las diferentes capas de fondos, hasta 128 sprites por pantalla (el tope del hardware de la DS) sin probemas.
 
Aqui os dejo un  par de videos, con 128 y 25 sprites respectivamente.
 

 
4 fondos y 128 sprites por pantalla.
 
 
 
4 fondos y 25 sprites por pantalla.
 
Siento la calidad de los videos, pero al youtube tanto movimiento se le ha atragantado ^^.
 
Algunos cambios respecto la anterior version:
He tenido que cambiar la asignacion de algunos bancos de la VRAM para paletas extendidas, al final la configuracion queda como sigue:
 
Banco A
———-
Uso: Fondos de la pantalla superior
Tamaño: 128kb
Define: VRAM_A_MAIN_BG
Direccion a la VRAM virtual:
0x06000000
 
Banco B
———-
Uso: Sprites de la pantalla superior
Tamaño: 128kb
Define: VRAM_B_MAIN_SPRITE_0x06400000
Direccion a la VRAM virtual:
0x06400000
 

Banco C
———-
Uso: Fondos de la pantalla inferior
Tamaño: 128kb
Define:
VRAM_C_SUB_BG
Direccion a la VRAM virtual:
0x06200000
 
Banco D
———-
Uso: Sprites de la pantalla inferior
Tamaño: 128kb
Define:
VRAM_D_SUB_SPRITE
Direccion a la VRAM virtual:
0x06600000
 
Banco E
———-
Uso: Paletas extendidas para fondos, pantalla superior
Tamaño: 64kb (Solo pueden usarse los primeros 32kb para paletas)
Define (modo escritura):
VRAM_E_LCD
Define (modo lectura):
VRAM_E_BG_EXT_PALETTE
Direccion a la VRAM virtual: 0x06880000
 
Banco F
———-
Uso: Paletas extendidas para Sprites, pantalla superior
Tamaño: 16kb (Solo pueden usarse los primeros 8kb para paletas)
Define (modo escritura):
VRAM_F_LCD
Define (modo lectura):
VRAM_F_SPRITE_EXT_PALETTE
Direccion a la VRAM virtual: 0x06890000
 
 
Banco H
———-
Uso: Paletas extendidas para fondos, pantalla inferior
Tamaño: 32kb
Define (modo escritura):
VRAM_H_LCD
Define (modo lectura): VRAM_H_SUB_BG_EXT_PALETTE

Direccion a la VRAM virtual:
0x06898000
 
Banco I
———-
Uso: Paletas extendidas para Sprites, pantalla inferior
Tamaño: 16kb (Solo pueden usarse los primeros 8kb para paletas)
Define (modo escritura):
VRAM_I_LCD
Define (modo lectura):
VRAM_I_SUB_SPRITE_EXT_PALETTE
Direccion a la VRAM virtual: 0x068A0000
 
 
Solo mencionar que esta es la configuracion de VRAM que yo he creido mas acertada en plan "libreria todoterreno", pero cada uno se la puede reconfigurar segn sus necesidades.
 
Mas novedades.
En la carpeta GRIT, vereis que teneis un nuevo archivo .BAT llamado "Sprites". Es un simple script para que GRIT convierta nuestros archivos BMP (debeis de colocarlos en esa carpeta) a sprites. El resultado despues de ejecutarlo se coloca en la carpeta "Sprites".
 
Comentaros tambien que por alguna razon, el sistema FCSR que usa no$gba deja de funcionar aleatoriamente, asi que definitivamente, recomiendo usar ideas como alternativa para testeo.
En la carpeta ideas teneis el emulador, la utilidad DLDI y un .BAT para parchear el binario compilado para que funcione con Ideas y FAT.
Si quereis poner vuestro graficos, colocarlos en la carpeta "NFlib" dentro de la carpeta "Ideas".
 
Funciones añadidas.
De momento, teneis las siguientes funciones para la creacion y manejo de sprites:
 

// Funcion NF_InitSpriteBuffers()
void NF_InitSpriteBuffers(void);
// Inicializa los buffers y estructuras de datos de los Buffers para almacenar Sprites
// Usala antes de cargar cualquier Sprites
 
// Funcion NF_InitSpriteSys();
void NF_InitSpriteSys(u8 screen);
// Inicializa las variables de control de Sprites y paletas
// Asigna 128kb de RAM para Sprites
// Activa el Soporte para Sprites
// Se debe especificar la pantalla (0 o 1)
 
// Funcion NF_LoadSpriteGfx();
void NF_LoadSpriteGfx(const char* file, u16 id, u16 width, u16 height);
// Carga un grafico para usarlo despues en la creacion de Sprites
// Especifica el archivo, ID exclusivo (0 – 255) y medidas del grafico
 
// Funcion NF_LoadSpritePal();
void NF_LoadSpritePal(const char* file, u16 id);
// Carga una paleta para usarla despues en la creacion de Sprites
// Especifica el archivo y ID exclusivo (0 – 63)
 
// Funcion NF_VramSpriteGfx();
void NF_VramSpriteGfx(u8 screen, u16 id);
// Transfiere un Grafico cargado para Sprites a la VRAM
// Debes especificar la pantalla y la Id del Grafico

// Funcion NF_VramSpritePal();
void NF_VramSpritePal(u8 screen, u8 slot, u8 id);
// Transfiere una Paleta cargada para Sprites a la VRAM
// Debes especificar la pantalla, el slot de paleta (0 – 15)
// y la Id de la Paleta a trasnferir.
 
// Funcion NF_CreateSprite();
void NF_CreateSprite(u8 screen, u8 id, u16 gfx, u8 pal, u16 x, u16 y);
// Crea un sprite en la pantalla.
// Debes especificar la pantalla, la ID del Sprite (0 – 127),
// la ID del Grafico que usaras (0 – 255), el slot de paleta (0 – 15),
// y las coordenadas donde lo crearas.

// Funcion NF_SpriteOamSet();
void NF_SpriteOamSet(u8 screen);
// Copia los datos del array propio de OAM al OAM real
// Debes especificar la pantalla
 
// Funcion NF_MoveSprite();
void NF_MoveSprite(u8 screen, u8 id, s16 x, s16 y);
// Mueve el Sprite a las coordenadas especificadas
// Debes de indicar la pantalla, id de sprite y coordenadas
 
// Funcion NF_SpriteLayer();
void NF_SpriteLayer(u8 screen, u8 id, u8 layer);
// Define la capa sobre la que el sprite sera dibujado
// Debes de indicar la pantalla, id del sprite y capa
 
 

Que queda por hacer.
Pues las funciones relativas al borrado de sprites, paletas y graficos, tanto de la VRAM como RAM, desfragmentacion de la VRAM caso de multiples borrados y soporte para sprites animados (sprites con multiples frames)
 
Aqui teneis el proyecto entero: Descarga version 20090413
 
Como siempre, dudas, sugerencias o criticas, a los comentarios
 
Un cordial saludos
 
NightFox

Programacion en DS. Proyecto de la Leccion 2.

Hola!
Bueno, porfin ya he conseguido que todo lo basico referente a los fondos, funcione. En el proyecto que os dejo hoy aprenderemos a:
– Cargar un fondo desde la FAT, guardarlo en la RAM y asignarle un nombre para, mas tarde, poderlo pasar a la pantalla.
– Inicializar el motor 2D en ambas pantallas y configurar los bancos de VRAM para poder cargar estos fondos y sus paletas.
– Mover estos fondos en la pantalla (scroll)
– Eliminacion de los mismos, tanto de la pantalla como de la RAM, para ahorrar memoria una vez no sean necesarios.
– Uso de GRIT para convertir estos fondos.
– Creacion de una ROM compatible con no$gba para poder probarla en el emulador.
 
Dado que a medida que hago estos tutoriales, estoy creando una libreria, he empezado a dividir las funciones en varios archivos, para tenerlo todo mas claro. He documentado lo suficiente el codigo para que con solo daros cuatro notas aqui, podais reseguirlo y aprenderlo ha hacer vosotros (o si sois uno vagos, usar directamente mis funciones).
 
Para empezar, os dejo un video con lo que aprenderemos ha hacer hoy.
 

 
Y a continuacion, las descargas para esta leccion.
Proyecto de la leccion 2 en VC Express 2005: http://www.mediafire.com/?e0ioo5lmmnm
Utilidad GRIT e imagenes para los fondos: http://www.mediafire.com/?2dzdydywiyj
Script y archivos para crear roms para NO$GBA: http://www.mediafire.com/?nmeiymdktoi

Intentare comentar una funcion cada dia en el blog, para que a mi me de tiempo de escribir el tutorial y a vosotros no se os haga pesado.
De momento los interesados, irle dando un vistazo (repito, el codigo esta MUY comentado) y dejarme aqui las dudas. Como ya he dicho, comentare en profundidad como funcionan cada una de las funciones que he escrito para que aprendais como funcionan internamente.
 
Asi que, disfrutarlo y hasta mañana!
 
Saludos

NightFox

Las tontunadas de tener poca documentacion, o como perder 3 dias por culpa de un numero.

Bueno, como son casi las 3 y media de la madrugada, sere breve, ya funciona. Si le dais un vistazo a las anteriores entradas, sabreis que hace unos dias que me estoy peleando con las paletas extendidas. Pues bien, para variar, no era culpa mia, si no de un "define" con mala leche, que segun alguna pagina existe, pero no.
El problema ha venido de esta linea de codigo:
 
vramSetBankG(VRAM_G_BG_EXT_PALETTE);
 
Con esto le comunicavamos a la DS (en teoria) que los datos que habiamos grabado en el banco de VRAM G, los queriamos usar como paleta extendida para fondo.
Pues no, se ve que no (ole por la documentacion de los co*ones) y gracias a un alma caritativa que hizo un ejemplo (lo siento, pero ya ni recuerdo de donde lo saque, pero le estoy agradecido), me encuentro con esto:
 
The ndslib does not have appropriate defines for this. The first line sets VRAM_F to store slots 0 and 1, and the hex on the second line sets VRAM_G to store slots 2 and 3. */
VRAM_F_CR = VRAM_ENABLE | VRAM_F_BG_EXT_PALETTE; //slots 0 and 1
VRAM_G_CR = VRAM_ENABLE | 0xC; //slots 2 and 3
 
Manda webos, o sea, que la linea que yo dava por buena (y que en el emulador Ideas funcionava), resulta que no, que no sirve. Pues yo voy y la cambio por esto:
 
vramSetBankG(0xC);
 

Y, oh, milagro milagroso, funciona.
En fin, 3 dias a tomar viento, por un puñetero numerito, pero al fin, funciona. Mañana mas.
 
Saludos a todos

Fox 

El fabuloso mundo de los emuladores y el desarrollo en Nintendo DS

Lo que son las cosas. Tanto darme de ostias y ahora resulta que encima depende en que emulador se comporta muy diferente. La cosa es que en el NO$GBA sigue sin funcionar, en la DS va algo mejor, pero vamos, no es para tirar cohetes, pero lo que son las cosas, con el Ideas va de muerte. Aqui teneis la prueba:
 

 
n00bey, habitual del mundillo del homebrew le esta dando un vistazo al codigo, a ver si pilla algo que este mal y se me haya pasado a mi, pero sospechamos que es que algun banco de VRAM queda bloqueado contra escritura (no deberia) y por eso la cosa no va.
A ver como lo terminamos solucionando.
 
Un cordial saludo
 
NightFox