Registrarse

[Decomp-GBA] [Avanzado] Cómo funcionan las interfaces

Kaktus

Miembro insignia
Miembro insignia
¡¡Buenaass!!

Hoy @Jack Johnson me ha pedido consejos para hacer interfaces, y le he dicho que lo mejor que podía hacer para aprender sobre interfaces era entender los conceptos, y luego analizar código para asentar los conocimientos, pero me he venido muy arriba y le he explicado gran parte de los conceptos necesarios. Y como he escrito suficiente contenido como para publicarlo a modo de tutorial/aporte, os dejo a continuación una especie de glosario con los términos que necesitáis conocer de decompilación para empezar a investigar, modificar y desarrollar interfaces.

En total tenemos 4, y son como capas. Tenemos el BG 0, el 1, el 2 y el 3. El 0 es el de más arriba, y el 3 el de más abajo. Es decir, que si cargamos un fondo (que viene a ser una imagen de cualquier tamaño (siempre y cuando no exceda 512x512 que es el tope, y que las dimensiones sean múltiplos de 8) a tamaño completo en el BG1, y otro en el BG0, el fondo que hemos cargado en el BG0, tapará al del BG1.
Son imágenes que podemos cargar cuyo máximo por defecto es 64x64. Con esto es con lo que se cargan las imágenes de los Pokémon, de los entrenadores, y alguna que otra imagen pequeña, que podamos introducir dentro de ese límite de tamaño, además, de estos podemos usar muchísimos más que fondos (que solo tenemos 4)
Contamos con dos formas distintas de almacenar las paletas (que son los colores que usan nuestros fondos o sprites). Una de ellas es en el espacio de los colores de los background, y otra de ellas, los colores de los sprites (Contamos con 256 colores para backgrounds, y con 256 colores para sprites, que es el límite de la GBA)
Para cargar gran parte, por no decir todos los gráficos, contamos con estructuras de datos, de las que tendremos que hacer uso. Es decir, no basta con importar el gráfico y ya está, tenemos que definir una serie de parámetros según el gráfico que estemos cargando. Por ejemplo la posición en la que aparecerá, su tamaño, que paleta usará, etc, y cuando carguemos los gráficos por pantalla, todos los datos serán tomados de estas estructuras. Un ejemplo de estos, es la estructura de tipo OamData, que lo usamos para cargar sprites.
Cuando cargamos un fondo, lo más normal será que lo carguemos con un tilemap, es decir, que nosotros en lugar de pasar el fondo como tal, eliminaremos del fondo todos los tiles que se repitan, para ahorrar espacio, y el tilemap, será el que nos sirva para indicarle al juego, en qué posición o posiciones, pondrá cada tile en la pantalla (esto se ve mejor una vez estéis insertando fondos y lo veáis)
Estos son los gráficos cargados en la VRAM, de los que la GBA imprime directamente en pantalla todo lo que vemos. Ya sean backgrounds, textos, minisprites, sprites... Cualquier cosa que veamos por pantalla, se carga en los tileblocks. Por eso, cuando por ejemplo cargamos un Tilemap, o la imagen de un background, tenemos que saber bien en qué parte del tileblock lo estamos cargando, y estar seguros de que ese espacio no está ya ocupado, porque si lo está, nos cargaremos los gráficos, o los tilemaps de otra cosa (el 90% de gráficos cargados con errores, será por temas relacionados con reemplazo de espacios ocupados en los gráficos de la VRAM)
Supongo que muchos entenderéis ya este concepto, pero aún así lo explicaré. Un frame es una imagen. Para que entendáis como funcionan las pantallas, y como conseguimos tener la sensación de movimiento cuando las vemos, pues simplemente, mostramos por pantalla muchísimas imágenes una detrás de otra en muy poco tiempo. Y así, es como hacemos que algo en una pantalla "se mueva". Si os dais cuenta, cuando jugamos un juego, hablamos de FPS, o sin abreviarlo, Frames Per Second, que viene a significar Imágenes por Segundo. Vaya, que cuando jugamos a un juego que va a 60 FPS, estamos jugando a un juego que cada segundo, está mostrando un total de 60 imágenes.
Los tasks, como dice la palabra, son tareas, el propósito general es separar en varios frames las funciones que queremos ejecutar, o hasta que se mantenga ejecutando X secuencia de código cada frame hasta que se cumpla una condición(sé que suena ambiguo, pero cuando las veáis entenderéis mejor a que me refiero)
Los callbacks son funciones que asignaremos al task general (normalmente se llama gTask) para que sean llamadas antes de calcular el siguiente frame a mostrar por pantalla. Si no se cambia el callback, se ejecutará la función asignada al callback hasta que esta cambie. Por ejemplo, en el overworld, la función asignada al callback es una que comprueba si antes de calcular el siguiente frame el botón de start está pulsado, y si es así, abre el menú, si no, simplemente no hace nada. O también sirve en el propio overworld para detectar las teclas para moverse, o para hablar con NPC's, etc.
Los registros nos sirven para manipular cómo se imprimen los gráficos en pantalla de forma genérica. Por ejemplo, podemos decidir que se carguen ciertos backgrounds y otros no. O podemos hacer que dos backgrounds fundan sus colores. O podemos seleccionar los backgrounds que queramos para hacer un fundido a negro o a blanco, o podemos crear zonas semitransparentes, etc.

Y esos han sido todos los conceptos que he recordado que serían útiles para empezar a aprender sobre interfaces. Ahora, tengo dos recomendaciones cruciales para vosotros, para que podáis hacer un buen uso de la información que os he dado. La primera de ellas, es que uséis el emulador mGBA. Es un emulador de lo más fiel a una GameBoy real, además, con él podemos ver en qué estado se encuentran gran parte de los conceptos hoy explicados. Con mGBA, podemos ver (incluso ver como cambian en tiempo real) las paletas cargadas, los backgrounds cargados, los sprites cargados, los gráficos de la VRAM, los tilemaps cargados en la misma para ver si estamos superponiendo alguna carga de gráficos con otro gráfico ya cargado, e incluso podemos ver el estado de los registros (y modificar algunos de ellos, pero no todos).

Mi segunda recomendación, es que para asentar estos conceptos, analicéis la interfaz de selección del Pokémon inicial de pokeemerald (ojo, estos conceptos sirven para cualquier juego de 3ª Gen, pero este es un buen ejemplo. En el, vemos carga de backgrounds con sus respectivas paletas y tilemaps, carga de sprites, modificación de los registros, impresión de textos... Muy recomendable para ver un poco de todo.

Espero que os sea de utilidad. Este post está enfocado sobretodo para que os apoyéis en él siempre queráis hacer un tutorial en relación a la carga/descarga de interfaces, o incluso carga/descarga de cualquier tipo de gráfico. Podéis sentiros libres de citar cualquier parte del glosario/aporte en vuestros tutoriales.

¡Un saludo!
 

Acimut

Profesional de WaH
¡Excelente aporte! Sin duda algo que la comunidad de WaH necesita es más documentación en español, y si es fácil de entender, mejor.

uséis el emulador mGBA. Es un emulador de lo más fiel a una GameBoy real
Personalmente odio el mGBA >:v y a pesar de lo que dicen, tiene uno que otro bug que no pasa en el hardware real (esto es real hijo) y ya me ha causado un par de problemas por ello, pero como son problemas muy puntuales, no debería haber problemas en la mayoría de los casos ; sin embargo, el emulador sigue en desarrollo y sigue mejorando, por lo que creo que en algún punto será perfecto. De todos modos y en teoría, si funciona en mGBA funciona en una calculadora cualquier emulador. Eso sí, lo que sí me gusta es el grabador de gif, es de lo mejor.

Mi segunda recomendación, es que para asentar estos conceptos, analicéis la interfaz de selección del Pokémon inicial de pokeemerald (ojo, estos conceptos sirven para cualquier juego de 3ª Gen, pero este es un buen ejemplo. En el, vemos carga de backgrounds con sus respectivas paletas y tilemaps, carga de sprites, modificación de los registros, impresión de textos... Muy recomendable para ver un poco de todo.
No podría estar más de acuerdo, también recomiendo para los que estén aprendiendo, si ya entienden los conceptos, leer el código que ya está en el juego, y entre más corto más fácil será de entender, que no es lo mismo ver el código de la summay screen que la trainer card, por poner un ejemplo. Para muchas de las cosas que queremos hacer ya tenemos ejemplos en el código, y seguramente es una gran referencia ver cómo se hace o funciona determinada cosa.

Espero que os sea de utilidad. Este post está enfocado sobretodo para que os apoyéis en él siempre queráis hacer un tutorial en relación a la carga/descarga de interfaces, o incluso carga/descarga de cualquier tipo de gráfico. Podéis sentiros libres de citar cualquier parte del glosario/aporte en vuestros tutoriales.
No dudes que te referenciaré en un futuro.
 

Eaas

Profesional de WaH
¡¡Buenaass!!

Hoy @Jack Johnson me ha pedido consejos para hacer interfaces, y le he dicho que lo mejor que podía hacer para aprender sobre interfaces era entender los conceptos, y luego analizar código para asentar los conocimientos, pero me he venido muy arriba y le he explicado gran parte de los conceptos necesarios. Y como he escrito suficiente contenido como para publicarlo a modo de tutorial/aporte, os dejo a continuación una especie de glosario con los términos que necesitáis conocer de decompilación para empezar a investigar, modificar y desarrollar interfaces.

En total tenemos 4, y son como capas. Tenemos el BG 0, el 1, el 2 y el 3. El 0 es el de más arriba, y el 3 el de más abajo. Es decir, que si cargamos un fondo (que viene a ser una imagen de cualquier tamaño (siempre y cuando no exceda 512x512 que es el tope, y que las dimensiones sean múltiplos de 8) a tamaño completo en el BG1, y otro en el BG0, el fondo que hemos cargado en el BG0, tapará al del BG1.
Son imágenes que podemos cargar cuyo máximo por defecto es 64x64. Con esto es con lo que se cargan las imágenes de los Pokémon, de los entrenadores, y alguna que otra imagen pequeña, que podamos introducir dentro de ese límite de tamaño, además, de estos podemos usar muchísimos más que fondos (que solo tenemos 4)
Contamos con dos formas distintas de almacenar las paletas (que son los colores que usan nuestros fondos o sprites). Una de ellas es en el espacio de los colores de los background, y otra de ellas, los colores de los sprites (Contamos con 256 colores para backgrounds, y con 256 colores para sprites, que es el límite de la GBA)
Para cargar gran parte, por no decir todos los gráficos, contamos con estructuras de datos, de las que tendremos que hacer uso. Es decir, no basta con importar el gráfico y ya está, tenemos que definir una serie de parámetros según el gráfico que estemos cargando. Por ejemplo la posición en la que aparecerá, su tamaño, que paleta usará, etc, y cuando carguemos los gráficos por pantalla, todos los datos serán tomados de estas estructuras. Un ejemplo de estos, es la estructura de tipo OamData, que lo usamos para cargar sprites.
Cuando cargamos un fondo, lo más normal será que lo carguemos con un tilemap, es decir, que nosotros en lugar de pasar el fondo como tal, eliminaremos del fondo todos los tiles que se repitan, para ahorrar espacio, y el tilemap, será el que nos sirva para indicarle al juego, en qué posición o posiciones, pondrá cada tile en la pantalla (esto se ve mejor una vez estéis insertando fondos y lo veáis)
Estos son los gráficos cargados en la VRAM, de los que la GBA imprime directamente en pantalla todo lo que vemos. Ya sean backgrounds, textos, minisprites, sprites... Cualquier cosa que veamos por pantalla, se carga en los tileblocks. Por eso, cuando por ejemplo cargamos un Tilemap, o la imagen de un background, tenemos que saber bien en qué parte del tileblock lo estamos cargando, y estar seguros de que ese espacio no está ya ocupado, porque si lo está, nos cargaremos los gráficos, o los tilemaps de otra cosa (el 90% de gráficos cargados con errores, será por temas relacionados con reemplazo de espacios ocupados en los gráficos de la VRAM)
Supongo que muchos entenderéis ya este concepto, pero aún así lo explicaré. Un frame es una imagen. Para que entendáis como funcionan las pantallas, y como conseguimos tener la sensación de movimiento cuando las vemos, pues simplemente, mostramos por pantalla muchísimas imágenes una detrás de otra en muy poco tiempo. Y así, es como hacemos que algo en una pantalla "se mueva". Si os dais cuenta, cuando jugamos un juego, hablamos de FPS, o sin abreviarlo, Frames Per Second, que viene a significar Imágenes por Segundo. Vaya, que cuando jugamos a un juego que va a 60 FPS, estamos jugando a un juego que cada segundo, está mostrando un total de 60 imágenes.
Los tasks, como dice la palabra, son tareas, el propósito general es separar en varios frames las funciones que queremos ejecutar, o hasta que se mantenga ejecutando X secuencia de código cada frame hasta que se cumpla una condición(sé que suena ambiguo, pero cuando las veáis entenderéis mejor a que me refiero)
Los callbacks son funciones que asignaremos al task general (normalmente se llama gTask) para que sean llamadas antes de calcular el siguiente frame a mostrar por pantalla. Si no se cambia el callback, se ejecutará la función asignada al callback hasta que esta cambie. Por ejemplo, en el overworld, la función asignada al callback es una que comprueba si antes de calcular el siguiente frame el botón de start está pulsado, y si es así, abre el menú, si no, simplemente no hace nada. O también sirve en el propio overworld para detectar las teclas para moverse, o para hablar con NPC's, etc.
Los registros nos sirven para manipular cómo se imprimen los gráficos en pantalla de forma genérica. Por ejemplo, podemos decidir que se carguen ciertos backgrounds y otros no. O podemos hacer que dos backgrounds fundan sus colores. O podemos seleccionar los backgrounds que queramos para hacer un fundido a negro o a blanco, o podemos crear zonas semitransparentes, etc.

Y esos han sido todos los conceptos que he recordado que serían útiles para empezar a aprender sobre interfaces. Ahora, tengo dos recomendaciones cruciales para vosotros, para que podáis hacer un buen uso de la información que os he dado. La primera de ellas, es que uséis el emulador mGBA. Es un emulador de lo más fiel a una GameBoy real, además, con él podemos ver en qué estado se encuentran gran parte de los conceptos hoy explicados. Con mGBA, podemos ver (incluso ver como cambian en tiempo real) las paletas cargadas, los backgrounds cargados, los sprites cargados, los gráficos de la VRAM, los tilemaps cargados en la misma para ver si estamos superponiendo alguna carga de gráficos con otro gráfico ya cargado, e incluso podemos ver el estado de los registros (y modificar algunos de ellos, pero no todos).

Mi segunda recomendación, es que para asentar estos conceptos, analicéis la interfaz de selección del Pokémon inicial de pokeemerald (ojo, estos conceptos sirven para cualquier juego de 3ª Gen, pero este es un buen ejemplo. En el, vemos carga de backgrounds con sus respectivas paletas y tilemaps, carga de sprites, modificación de los registros, impresión de textos... Muy recomendable para ver un poco de todo.

Espero que os sea de utilidad. Este post está enfocado sobretodo para que os apoyéis en él siempre queráis hacer un tutorial en relación a la carga/descarga de interfaces, o incluso carga/descarga de cualquier tipo de gráfico. Podéis sentiros libres de citar cualquier parte del glosario/aporte en vuestros tutoriales.

¡Un saludo!
Vale, vale.
Es bueno que esto este documentado aqui.
Un grandismo aporte a lacomunidad, ya que muchos no saven ni la mitad de los explicas aqui.
Mis 10 Inmo.....
 

Hoennwalker

Usuario de platino
@Acimut Man precisamente en interfaces gráficas puedes estar líandola seriamente y con el VBA ni te enteras. Sin embargo, con mGBA ves los errores. Y créeme es decir, puedes tener bugeado un Bg hasta la mitad y en VBA sale perfecto. Se trata también de aprender como funciona el hardware de GBA y para ello usamos mGBA.
 

kakarotto

Leyenda de WaH
Un tutorial muy completo y que de seguro le servirá a la gente que esté iniciandose en el maravilloso mundo de decompilación y para otros refrescar la memoría como yo 😁.

¡Crack!
 
Arriba