Registrarse

[pokeemerald] Como cargar y configurar BGs personalizados

Samu

Miembro insignia
Miembro insignia
Es la segunda parte de la guía para el manejo de los gráficos en los proyectos de decomp.

El vídeo contiene una explicación sobre como se deben de cargar y configurar los gráficos de BGs o 'fondos' custom dentro de decompilación.




Próximamente:
- Parte III: Controlar la transparencia/blending de las capas de vídeo/BGs.
- Parte IV: Funcionamiento de las 'ventanas'/windows textos.
 
Última edición por un moderador:

Zvleon

Usuario de oro
¿No tienes pensado seguir con el tutorial?
En estos momentos, es lo que más necesito para finalizar mi proyecto y no encuentro información de algo similar en ninguna otra parte.

De momento, gracias a tu tuto he podido crear la base de un menú custom de selección de inicial, pero lo único que me falta es ver como puedo printear mensajes en pantalla. He estado intentando replicar lo que hay en otros archivos del juego pero no me funciona :p

Espero que puedas seguir con esta serie de tutos porque realmente no he visto nada como esto y siento que sería muy beneficioso para toda la comunidad.

 

Samu

Miembro insignia
Miembro insignia
Re: Respuesta: Como cargar y configurar BGs personalizados

¿No tienes pensado seguir con el tutorial?
En estos momentos, es lo que más necesito para finalizar mi proyecto y no encuentro información de algo similar en ninguna otra parte.
Tenía pensado continuarlo, pero no en el futuro inmediato. Ahora mismo no hay tanta gente interesada en decomp en la comunidad hispana, en mi opinión debido a la falta de documentación y una mayor barrera de entrada en comparación con RH o RPG.

Está claro que la forma de minimizar este problema es crear documentación, recursos y tutoriales sobre decomp. No obstante, creo que lo más importante ahora mismo son varios tutoriales básicos que permitan comenzar a una persona desde cero, sin experiencia previa en otras plataformas o en programación. Es por esto que llevo unas semanas trabajando en completar el tutorial de scripting de Decomp que Ludiloco dejó a medias; así como un tutorial para aprender a usar Porymap que pueda ser útil para una persona ajena a todo esto.

Por otro lado, esta serie de tutoriales son más 'avanzados', y no representan una disminución en la barrera de entrada, por lo que ahora mismo no son mi prioridad.

No obstante, ya que lo necesitas, intentaré hacer el tutorial de las ventanas de texto tan pronto como pueda, aunque no tengo mucho tiempo este mes. Si te urge mucho, explícame un poco más específicamente dónde quieres poner los textos (su distribución en la pantalla) y más o menos la longitud de los mismos y te doy unas pequeñas indicaciones sobre el código que necesitas.


Y ahora, continúo quejándome. Por que hay otras personas tan capaces como yo para hacer los tutoriales básicos.
Ya lo he dicho varias veces, pero creo que Decomp es el futuro del RH o al menos el único futuro viable a medio-largo plazo. Por eso no podemos pretender que los usuarios nuevos que puedan llegar, tengan que pasarse un par de meses en RH tradicional, simplemente para poder entender lo que dice el más básico de los tutoriales de Decomp. Estamos dando por sentado que cualquier persona que empiece en Decomp tiene los conocimientos básicos/medios de RH y esto solo reduce la usabilidad de la "plataforma", que es el motivo por el que fue creada.

Deben hacerse tutoriales básicos de Decomp, al igual que se hicieron con RH, sin dar nada por sabido, y teniendo en cuenta que un usuario nuevo debería ser capaz de aprender a usar decomp únicamente con los tutoriales de esta plataforma, cosa que ahora mismo veo complicado.

¿Qué a dónde voy con todo esto?

Ayudad a crear los tutoriales básicos de decomp, cabrones(?).

PD: He visto tu menú, pero tienes no estás usando el link adecuado dentro del bbcode, prueba con este link https://i.imgur.com/pvwPMU1.gif .
 

Zvleon

Usuario de oro


Gracias por la rápida respuesta :D

La verdad es que soy bastante nuevo en todo esto. Me había propuesto comenzar a hacer tutoriales (de hecho, por ahí debo tener un PDF hecho en LaTex que nunca terminé sobre como hacer scripts en mapas) pero me puse como objetivo primero tratar de crear un menú custom de iniciales y unas healthbar para demostrar que estoy "capacitado" para realmente entender que ocurre en el código y efectivamente poder ser un aporte (además de que recien ahora tengo tiempo libre porque he salido de vacaciones) Después de eso con gusto puedo ayudar a subir tutoriales :B

En cuanto a la distribución de "strings" en pantalla, me gustaría tener una distribución como esta:




Tengo más o menos una idea de como extraer dichos strings, pero no se como mostrarlos en pantalla.

Saludos :D
 

Samu

Miembro insignia
Miembro insignia
Re: Respuesta: Como cargar y configurar BGs personalizados


En cuanto a la distribución de "strings" en pantalla, me gustaría tener una distribución como esta:




Tengo más o menos una idea de como extraer dichos strings, pero no se como mostrarlos en pantalla.
Perfecto, te comento como funciona.

Dentro del código de los proyectos de decomp existe un sistema de ventanas o "Windows" que se encarga de crear los cuadros que ves a lo largo del juego en los menús, los cuadros de texto, multichoice, etc. Estos cuadros pueden mostrar varios gráficos distintos, o ninguno (cuadro de fondo transparente).
*Importante: el funcionamiento del sistema de ventanas cambia bastante entre las 3 ediciones de 3ª generación, todo lo que te voy a decir ahora es sobre pokeemerald.

Como ya he mencionado, una de las utilidades de un "window" es albergar un cuadro con texto, por lo tanto, para escribir un texto en pantalla será necesario que crees un Window en la posición y con el tamaño necesario para albergar el texto deseado.

  • 1. Importa 'window.h'
  • 2. Crea un struct 'WindowTemplate' para asignar las "plantillas" de tus ventanas.
  • 3. Crea una nueva función para inicializar tus window.
Código:
#include "window.h"

static void InitMyTextWindows();

enum { TITLE_WINDOW, POKEMON_WINDOW, HABILITY_WINDOW, ATTACKS_WINDOW}

static const struct WindowTemplate sWindowTemplate_MiPlantilla[] = 
{
	[TITLE_WINDOW] = { 		// NAME_WINDOW
        .bg = 0,            // bg layer
        .tilemapLeft = 2,   // x position, in no. of tiles (8x8 pixels)
        .tilemapTop = 1,    // y position. (8x8 tiles)
        .width = 6,			// width x 8 pixels
        .height = 2,		// height x 2 pixels
        .paletteNum = 15,	// Palette to be used by window tiles
        .baseBlock = 1,     // initial tile number in vram? relative to .charBaseIndex of bgTemplate?
    },
	
	[POKEMON_WINDOW] = { 
        .bg = 0,                   
        .tilemapLeft = 2,                 
        .tilemapTop = 1,                  
        .width = 6,
        .height = 2,
        .paletteNum = 15,
        .baseBlock = 1,                  
    },
	
	[HABILITY_WINDOW] = { 
        .bg = 0,                    
        .tilemapLeft = 2,                
        .tilemapTop = 1,                 
        .width = 6,
        .height = 2,
        .paletteNum = 15,
        .baseBlock = 1,                   
    },
	
	[ATTACKS_WINDOW] = { 
        .bg = 0,                    
        .tilemapLeft = 2,                 
        .tilemapTop = 1,                  
        .width = 6,
        .height = 2,
        .paletteNum = 15,
        .baseBlock = 1,                   
    },
};

static void InitMyTextWindows()
{
	InitWindows(sWindowTemplate_MiPlantilla);	//Inicializa los window
	DeactivateAllTextPrinters(); 	//Desactiva cualquier posible Text printer que haya quedado abierto
	LoadPalette(GetOverworldTextboxPalettePtr(), 0xf0, 0x20);	//Carga la paleta del texto por defecto del juego en el slot 15 de las paletas para backgrounds
	//LoadUserWindowBorderGfx(YES_NO_WINDOW, 211, 0xe0); //Opcional, necesario si se van a usar ventanas Yes/no
}
Con esto ya debería estar todo lo referente a las ventanas (has de ajustar las posiciones, el ancho y el alto de cada una de ellas). Ahora falta el texto.

Para añadir texto siempre va a haber dos pasos: añadir el texto y crear el textbox. En el caso de un texto estático, como el del título sería algo así:
Código:
const u8 gText_MenuTitle[] = _("Pick your starter: "); //Este texto debería ser declarado en un fichero .h separado y dedicado a almacenar constantes

AddText(gText_MenuTitle);
CreateTextBox(TITLE_WINDOW);
En el caso de querer obtener el texto del nombre de un Pokémon, sus movimientos o su habilidad, tendrás que hacer un par de cosillas más si no quieres hardcodear un montón de mierda.

Código:
static void InitMyTexts()
{
	
	AddText(gSpeciesNames[/*id_especie*/]);	
	CreateTextBox(POKEMON_WINDOW);
	AddText(gAbilityNames[/*id_habilidad*/]);	
	CreateTextBox(HABILITY_WINDOW);
	AddText(gMoveNames[/*id_ataque*/]);	
	CreateTextBox(ATTACKS_WINDOW);
}
Para terminar, en la función en la que estés inicializando los background "InitBgsFromTemplates", deberás de inicializar también tus window y tus textos, llamando a las funciones "InitMyTextWindows" e "InitMyTexts" en este paso.

No es exactamente todo el código que necesitas, pero con esto deberías tener suficiente para empezar.
 

Zvleon

Usuario de oro
Respuesta: Re: Respuesta: Como cargar y configurar BGs personalizados



De antemano muchisimas gracias, me ayudaste a entender muchas cosas que me faltaban de los template, pero tengo una duda. En esta parte haces uso de unas funciones llamadas <<AddText>> y <<CreateTextBox>>.


AddText(gText_MenuTitle);
CreateTextBox(TITLE_WINDOW);[/code]

En el caso de querer obtener el texto del nombre de un Pokémon, sus movimientos o su habilidad, tendrás que hacer un par de cosillas más si no quieres hardcodear un montón de mierda.

Código:
static void InitMyTexts()
{
	
	AddText(gSpeciesNames[/*id_especie*/]);	
	CreateTextBox(POKEMON_WINDOW);
	AddText(gAbilityNames[/*id_habilidad*/]);	
	CreateTextBox(HABILITY_WINDOW);
	AddText(gMoveNames[/*id_ataque*/]);	
	CreateTextBox(ATTACKS_WINDOW);
}
Según tengo entendido, dichas funciones no existen. ¿Las creaciones de dichas funciones van por mi cuenta o estaré revisando mal?

Saludos :D
 

Samu

Miembro insignia
Miembro insignia
Perdona JAJAJJA, pensaba que eran funciones de pokeemerald, pero fueron unas funciones que creé yo para dejar mi código más limpio hace tiempo. Aquí te dejo el código que usé para esas funciones, puedes usar dicho código o pasar de hacer las funciones como tal.

Código:
static void AddText(const u8* text)
{
    StringExpandPlaceholders(gStringVar4, text); //Coloca el texto en el buffer de strings
}

static void CreateTextBox(u8 windowId)
{
    FillWindowPixelBuffer(windowId, 0);	//Llena todos los pixeles del Buffer con el color indicado (0-> transparencia)
    PutWindowTilemap(windowId);	//Coloca el tilemap de los gráficos
    AddTextPrinterParameterized3(windowId, 1, 0, 0, sFontColourTable, -1, gStringVar4); //Asigna un textPrinter
    CopyWindowToVram(windowId, 3);	//Copia la ventana del buffer a la VRam
}
En CreateTextBox deberías tener los parámetros correctos para que el muestro se muestre al completo desde el principio, sin que tengas que esperar a que se escriba.

PD: Es importante remarcar que has de tener en cuenta la configuración que hayas establecido para el BG0 y que los lugares correspondientes al tileset y el tilemap para este BG estén vacíos, de esta manera evitarás que los Window generados tengan fondo alguno.
 
Última edición:

Zvleon

Usuario de oro
Respuesta: Re: Respuesta: Como cargar y configurar BGs personalizados

Finalmente pude printear mensajes en pantallas (YAAAY!)
Aunque ahora el textbox entra en conflicto con la ventana, resultando en algo como esto:


Me imagino que puede ser por parametros que no se como operan realmente de los templates del Background o de Window. Por ejemplo, en este fragmento de código no entiendo realmente que hace el baseBlock, o como está vinculado al .charBase Index del bgTemplate.

Código:
static const struct WindowTemplate sWindowTemplate_MiPlantilla[] = 
{
	[TITLE_WINDOW] = { 		// NAME_WINDOW
        .bg = 0,            // bg layer
        .tilemapLeft = 2,   // x position, in no. of tiles (8x8 pixels)
        .tilemapTop = 1,    // y position. (8x8 tiles)
        .width = 6,			// width x 8 pixels
        .height = 2,		// height x 2 pixels
        .paletteNum = 15,	// Palette to be used by window tiles
        .baseBlock = 1,     // initial tile number in vram? relative to .charBaseIndex of bgTemplate?
    },

};
}
También podría ser por la parte del .mapBaseIndex del BG. Esa parte no la entendí bien en tu video.

Saludos :D
 

Samu

Miembro insignia
Miembro insignia
Re: Respuesta: Re: Respuesta: Como cargar y configurar BGs personalizados

Vale, por lo que puedo ver en la imagen lo que está pasando es que estás usando la misma capa de vídeo para los gráficos de la interfaz y el texto en sí mismo.

Revisa otra vez el vídeo en la parte en la que hablo sobre los BgTemplates, tienes que usar otros bg distintos al 0 para los gráficos de la interfaz.

Si sigues teniendo problemas, necesitaría que abrieses los tools de tu emulador y me pongas imágenes de lo que aparece en cada capa de vídeo.
 

Zvleon

Usuario de oro
Respuesta: Re: Respuesta: Re: Respuesta: Como cargar y configurar BGs personalizados

Vale, por lo que puedo ver en la imagen lo que está pasando es que estás usando la misma capa de vídeo para los gráficos de la interfaz y el texto en sí mismo.

Revisa otra vez el vídeo en la parte en la que hablo sobre los BgTemplates, tienes que usar otros bg distintos al 0 para los gráficos de la interfaz.

Si sigues teniendo problemas, necesitaría que abrieses los tools de tu emulador y me pongas imágenes de lo que aparece en cada capa de vídeo.
Si con usar el mismo BG para ambos te refieres al .bg en esta struct

Código:
[TITLE_WINDOW] = { 		// NAME_WINDOW
        .bg = 1,            // bg layer
        .tilemapLeft = 2,   // x position, in no. of tiles (8x8 pixels)
        .tilemapTop = 1,    // y position. (8x8 tiles)
        .width = 12,			// width x 8 pixels
        .height = 2,		// height x 2 pixels
        .paletteNum = 15,	// Palette to be used by window tiles
        .baseBlock = 1,     // initial tile number in vram? relative to .charBaseIndex of bgTemplate?
    },
Pues lo cambie a 1 (pues la imagen usa el bg0) y el resultado es el siguiente


El texto desaparece. Trate de adjuntar lo que creo que me pedías, aunque no se si sea eso.



Por cierto ¿No estas en el discord del foro? Creo que sería mejor hablar por el chat de decom de ahí en vez de estar spammeando dudas personales por acá. Aunque tal vez hay gente con el mismo problema que yo así que es mejor que sigamos acá xD

Saludos :D
 

Samu

Miembro insignia
Miembro insignia
Lo normal y lo recomendable es que uses siempre el BG0 para cargar el texto (es lo que hace el juego). En este caso tu BG0 tiene prioridad 0, es decir, que será el que se muestre por encima del resto de BG.



Si pinchas en el BG1 dentro del tool, verás que el texto sí está siendo dibujado, pero está "detrás". Si quieres que el texto se vea lo más fácil es usar el BG1 para la interfaz y el BG0 para el texto.

O eso, o cambiar la priority dentro del BgTemplate como se ve en el vídeo. Tal y como lo tienes tú necesitas que el BG0 tenga una prioridad más alta que el BG1.



Y sí, prefiero contestarte por aquí, porque así no se pierde.
 

Zvleon

Usuario de oro
Supongo que ahora puedo considerar que tuve "exito" en todo esto:



Lo que pasaba era que, inicialmente estaba abriendo este menú desde la cinematica inicial de Birch. Presumo que previamente ya había declarado un BG que no se cerró como corresponde, entrando en conflicto con el resto de cosas. Ahora hay unos bugs menores, aunque quiero agregar más cosas, como un icon animado del pokémon en pantalla (esos que se usan en el PC o en la party_screen) y ver si puedo animar el fondo o la poké ball.

Muchas gracias Samu por darte el tiempo de explicarme las cosas paso a paso :D

Saludos
 

Cheve

MoonLover~
Miembro de honor
Me gusta como explicas para qué es cada cosa, dando lugar a que luego podamos usar lo que aprendimos acá para codear algo más. (Dentro de lo que cabe para el tutorial xD)

Lo estaré probando entre hoy y mañana, pasaré resultados acá (O en el subforo de dudas, dependiendo de cómo me valla xD) muchas gracias Samu!

PD: Ya avisé que el video no se ve, pero es por el bbcode del foro, si lo quieren ver acá lo dejo hasta que Samu lo arregle:

 

Versekr Dark

Usuario mítico
Disculpa si yo hiciera un menú parecido como podría inyectarlo en una rom, es que veo el método y sirve para hacer una dex pero no se podría hacer con la misma que ya existe ya que no veo que cargue los raws de manera normal.
 

Samu

Miembro insignia
Miembro insignia
Disculpa si yo hiciera un menú parecido como podría inyectarlo en una rom, es que veo el método y sirve para hacer una dex pero no se podría hacer con la misma que ya existe ya que no veo que cargue los raws de manera normal.
Para insertar sistemas en C dentro de un ROM binario te recomiendo mirar este tutorial de Kaiser https://whackahack.com/foro/threads/aprendiendo-a-romhackear-en-c.51510/

Ahí tienes una "plantilla" para programar en C para cada uno de los ROM, aunque puede que esté desactualizada (juraría que Compumax en su día posteo una más actual).
Esta plantilla tiene parte del código de pret (de una versión antigua) y en el fichero AXVE.id/BPEE.id/BPRE.id tienes los punteros a distintos atributos de la RAM y distintas funciones del ROM.

Digamos que tu por ejemplo quieres usar la función LoadPalette(const u16* src, u16 pos, u16 size) y dicha función no se encuentra en el "XXX.id", te tocaría buscar el offset de dicha función en un fichero .map de un proyecto de pret:



Una vez tengas el offset te vas al fichero XXX.id y escribes:
Código:
LoadPalette = 080adee0|1;
En este caso se pone |1 ya que es una función ejecutable (al igual que ocurría en ASM), si se tratase de un dato, no llevaría el |1;

Además de añadirlo en el fichero XXX.id también tendrías que declarar la función en algún lado con sus parámetros y su retorno.
 

Versekr Dark

Usuario mítico
Para insertar sistemas en C dentro de un ROM binario te recomiendo mirar este tutorial de Kaiser https://whackahack.com/foro/threads/aprendiendo-a-romhackear-en-c.51510/

Ahí tienes una "plantilla" para programar en C para cada uno de los ROM, aunque puede que esté desactualizada (juraría que Compumax en su día posteo una más actual).
Esta plantilla tiene parte del código de pret (de una versión antigua) y en el fichero AXVE.id/BPEE.id/BPRE.id tienes los punteros a distintos atributos de la RAM y distintas funciones del ROM.

Digamos que tu por ejemplo quieres usar la función LoadPalette(const u16* src, u16 pos, u16 size) y dicha función no se encuentra en el "XXX.id", te tocaría buscar el offset de dicha función en un fichero .map de un proyecto de pret:



Una vez tengas el offset te vas al fichero XXX.id y escribes:
Código:
LoadPalette = 080adee0|1;
En este caso se pone |1 ya que es una función ejecutable (al igual que ocurría en ASM), si se tratase de un dato, no llevaría el |1;

Además de añadirlo en el fichero XXX.id también tendrías que declarar la función en algún lado con sus parámetros y su retorno.
Muchas gracias samu la verdad todavia no entiendo del todo esto pero ya voy poco a poco.
 

Draizehn

I'm back, baby.
Miembro del equipo
Moderador/a
Es la segunda parte de la guía para el manejo de los gráficos en los proyectos de decomp.

El vídeo contiene una explicación sobre como se deben de cargar y configurar los gráficos de BGs o 'fondos' custom dentro de decompilación.




Próximamente:
- Parte III: Controlar la transparencia/blending de las capas de vídeo/BGs.
- Parte IV: Funcionamiento de las 'ventanas'/windows textos.
Estos tutoriales si que valen la pena, me pondré a practicar. Literalmente empecé hace dos días xddd
¿Seguirás con los demás?
 
Arriba