Registrarse

[Gráficos] Arreglar el 'parpadeo' del DNS en los warp

Samu

Miembro insignia
Miembro insignia
Bueno, no sé si solo es a mi, pero es una cosa que siempre me ha molestado muchísimo del DNS. Cada vez que haces un warp, cuando lanzas una pokeball, cuando usas ciertos ataques (absorber, destello...)... la pantalla 'parpadea', y durante un frame muestra la pantalla o parte de esta con los colores sin filtrar (no aplica el filtro de colores DNS).
Ayer me dio por mirarlo en un minuto que tuve libre, y bueno, encontré el problema y lo he solucionado. Solo diré que me cago en Game Freak.

- Esmeralda: Ir a '080A1BC6'.
- Fire Red: Ir a '0807067A'.
- Ruby: Ir a '08073CE6'.

En esa dirección pegamos lo siguiente:
Código:
00 00 00 00 00 00 00 00 FF F7 F7 FE
Bienvenidos a un nuevo mundo, uno en el que el DNS funciona bien.
Este apartado es más que nada para aquel al que le interese qué es lo que pasaba y qué es lo que he hecho.

Antes de nada explicar brevemente como funciona el DNS. En los juegos de pokemon de gba, hay una función (llamada TransferPlttBuffer en pret) que se encarga de transferir la información del Buffer de paletas a la RAM de paletas, encargándose del DMA transfer. Es decir, la RAM de paletas es escrita desde esta función.
Código:
void TransferPlttBuffer(void)
{
    if (!gPaletteFade.bufferTransferDisabled)
    {
        void *src = gPlttBufferFaded;
        void *dest = (void *)PLTT;
        DmaCopy16(3, src, dest, PLTT_SIZE);
        sPlttBufferTransferPending = 0;
        if (gPaletteFade.mode == HARDWARE_FADE && gPaletteFade.active)
            UpdateBlendRegisters();
    }
}
La rutina DNS lo que hace es incrustarse en esta función 'TransferPlttBuffer', para ejecutarse cada vez que una función del ROM llame a la función. De esta manera, cada vez que las paletas se vayan a 'refrescar', la rutina DNS se encargará de refrescarlas modificando los colores según los filtros que correspondan a la hora.

Sin embargo, por algún motivo y solo durante un frame, la RAM de paletas se estaba actualizando sin pasar por los filtros de DNS (dando lugar al efecto del flashazo/parpadeo). Es decir, algún puto gañan estaba haciendo la transferencia del buffer de paletas a la RAM sin llamar a 'TransferPlttBuffer'. Ahora solo quedaba lo divertido, buscar que estaba haciendo el CpuSet.

Mirando un poco en el debugger lo encontré, y también estaba en pret. Ahí estaba, en la función 'BeginNormalPaletteFade' había un precioso CpuSet pasando los bytes del Buffer a la RAM de paletas sin llamar al TransferPlttBuffer e ignorando mi DNS.
Código:
bool8 BeginNormalPaletteFade(u32 selectedPalettes, s8 delay, u8 startY, u8 targetY, u16 blendColor)
{
    u8 temp;
    register u32 _blendColor asm("r8") = blendColor;

    if (gPaletteFade.active)
    {
        return FALSE;
    }
    else
    {
        gPaletteFade.deltaY = 2;

        if (delay < 0)
        {
            gPaletteFade.deltaY += (delay * -1);
            delay = 0;
        }

        gPaletteFade_selectedPalettes = selectedPalettes;
        gPaletteFade.delayCounter = delay;
        gPaletteFade_delay = delay;
        gPaletteFade.y = startY;
        gPaletteFade.targetY = targetY;
        gPaletteFade.blendColor = _blendColor;
        gPaletteFade.active = 1;
        gPaletteFade.mode = NORMAL_FADE;

        if (startY < targetY)
            gPaletteFade.yDec = 0;
        else
            gPaletteFade.yDec = 1;

        UpdatePaletteFade();

        temp = gPaletteFade.bufferTransferDisabled;
        gPaletteFade.bufferTransferDisabled = 0;
        [B]CpuCopy32(gPlttBufferFaded, (void *)PLTT, PLTT_SIZE);[/B] // En Corea del Norte ejecutan por menos
        sPlttBufferTransferPending = 0;
        if (gPaletteFade.mode == HARDWARE_FADE && gPaletteFade.active)
            UpdateBlendRegisters();
        gPaletteFade.bufferTransferDisabled = temp;
        return TRUE;
    }
}
La solución es bastante simple, me cargo el CpuSet chustero que hicieron y lo sustituyo por una llamada (bl) a la función 'TransferPlttBuffer'. Como la posición relativa es igual en todos los ROM, el bl es el mismo (mismo HEX para los 3 ROM).
Es bastante fácil, solo tienes que modificar la función 'BeginNormalPaletteFade' en src/palettes.c:
Código:
bool8 BeginNormalPaletteFade(u32 selectedPalettes, s8 delay, u8 startY, u8 targetY, u16 blendColor)
{
    u8 temp;
    register u32 _blendColor asm("r8") = blendColor;

    if (gPaletteFade.active)
    {
        return FALSE;
    }
    else
    {
        gPaletteFade.deltaY = 2;

        if (delay < 0)
        {
            gPaletteFade.deltaY += (delay * -1);
            delay = 0;
        }

        gPaletteFade_selectedPalettes = selectedPalettes;
        gPaletteFade.delayCounter = delay;
        gPaletteFade_delay = delay;
        gPaletteFade.y = startY;
        gPaletteFade.targetY = targetY;
        gPaletteFade.blendColor = _blendColor;
        gPaletteFade.active = 1;
        gPaletteFade.mode = NORMAL_FADE;

        if (startY < targetY)
            gPaletteFade.yDec = 0;
        else
            gPaletteFade.yDec = 1;

        UpdatePaletteFade();

        temp = gPaletteFade.bufferTransferDisabled;
        gPaletteFade.bufferTransferDisabled = 0;
       
        [S][B]CpuCopy32(gPlttBufferFaded, (void *)PLTT, PLTT_SIZE);[/B] [/S]//Esta línea fuera
       [B][I] TransferPlttBuffer();[/I][/B]  //Esta línea dentro
        
        sPlttBufferTransferPending = 0;
        if (gPaletteFade.mode == HARDWARE_FADE && gPaletteFade.active)
            UpdateBlendRegisters();
        gPaletteFade.bufferTransferDisabled = temp;
        return TRUE;
    }
}

En fin, espero no ser el único ido de la cabeza al que le molestaba esto y que le sirva a alguien más.

PD: No arregla el parpadeo solo en los warp, lo arregla en general, pero pensé que el título era mejor así(?).
 
Última edición:

CompuMax

Discord: CompuMax#0425
Miembro insignia
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

Excelente aporte y explicación como siempre bro!

Lástima que aportes como este pasen desapercibidos debido al grado de complejidad que algunos usuarios suponen que tienen.

De nuevo gracias por el aporte!
 

KleinStudio

Un plato es un plato
Miembro del equipo
Webmaster
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

Aparte de que es algo útil y dar una solución, explicas donde está el fallo, lo cual sinceramente agradezco porque muchas veces se dan soluciones sin explicar qué es lo que está arreglando realmente.
 

Naren Jr.

Puto amo
Usuario de Platino
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

Me lo comentaste antes de publicarlo.

Recuerdo mucho que comenzamos hablando del DNS que contiene una infinidad de fallos y tu has acomodado y adaptado mucho.

he algunos hacks inclusive antes de hacer un warp quedaba cargado este bug y te podías saltar el filtro del dns por un largo tiempo.

Gracias por eso, ya mismo lo he utilizado en los hacks, ya tu sabe'
 

Fran Agustín

Si el sol besa tus ojos, ni cuenta te das.
Miembro insignia
Re: [GBA] Arreglar el 'parpadeo' del DNS en los warp

¡Qué gran tutorial! No he usado mucho el DNS pero sí que he notado los parpadeos. Era un error pequeño pero que, solucionado, es un gran detalle. ¡Gracias!
Además, has explicado muy bien dónde estaba el fallo y qué cambio has hecho para solucionarlo.

Ahora, me surge una duda: ¿por qué estaba esa llamada al CpuSet directo en lugar de a la función de las paletas? El cambio no repercutirá en alguna otra cosa que pueda llegar a fallar, ¿cierto?

En fin. Como siempre, ¡grande, Samu! ¡Gigante!
 
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

PUTOOO SAMUU, TE AMOOO.
No me creerás, pero hace unas semanas estaba buscando esta solución, te hago 29 hijos.
sos un grande bro, ahora te ayudo con todos los tiles que quieras.
Ahora en serio, un excelente aporte, y muchas gracias por también explicarlo, ya que con eso se puede aprender un poquito más, ¿Estás seguro que no trae absolutamente ningún bug?, bueno, será cosa de probar, saludos.
 

Samu

Miembro insignia
Miembro insignia
Re: Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

Aparte de que es algo útil y dar una solución, explicas donde está el fallo, lo cual sinceramente agradezco porque muchas veces se dan soluciones sin explicar qué es lo que está arreglando realmente.
Se que hay mucha gente a la que solo le interesa 'como se arregla' y ya está. Pero a mí siempre me enfada mucho cuando me ponen un chorro de bytes y no me dicen nada más (sobretodo porque hace más difícil la modificación/solución de errores).
Yo prefiero que me den una explicación más o menos breve de lo que hay, así que lo menos que puedo hacer es predicar con el ejemplo. Aunque lo leamos/entendamos 1/5 de las personas que lo usen. Cada uno que se quede con lo que quiera o necesite.

PD: odio profundo a los post/tutoriales con las rutinas compiladas sin el código fuente.



Ahora, me surge una duda: ¿por qué estaba esa llamada al CpuSet directo en lugar de a la función de las paletas? El cambio no repercutirá en alguna otra cosa que pueda llegar a fallar, ¿cierto?
Lo más probable es que el cambio se deba a una mala decisión del programador que hizo esa parte. Al fin y a cabo el rom está lleno de cosas nonsense. Por ejemplo, el hecho de que las paletas de 16 colores estén o no comprimidas sin un criterio uniforme (puede que uno de los programadores las comprimiese siempre y otros no, o yo que sé), y eso sin tener en cuenta que una paleta de 16 colores ocupa más al comprimirla en lz77 prácticamente siempre, pero bueno XD.

Ah, y he llegado a ver el mismo bloque de código escrito 10 veces, uno por cada uno de los case de un switch. Aunque me imagino que esto último seguramente haya sido cosa del compilador que uso GF. Quiero pensarlo.


PUTOOO SAMUU, TE AMOOO.
¿Estás seguro que no trae absolutamente ningún bug?, bueno, será cosa de probar, saludos.
Al 100% no te lo puedo decir, pero en principio debería ser mejor así que como estaba antes. En cualquier caso, lo peor que puede pasar es que al llamar el 'BeginNormalPaletteFade' (Que se ejecuta solo una vez al comienzo de cada fade) no se haga el transfer del buffer a la RAM de paletas.
O sea, lo peor que puede pasar es que un cambio en el buffer de paletas llegue 1/60 segundos tarde a la RAM, en el peor de los casos.
Vaya, yo diría que el cambio es bastante seguro.

Ahora es cuando por bocas revienta, así que igual tendría que callarme (?).
 

Omega

For endless fight
Miembro del equipo
Moderador/a
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

Y así es como DNS se volvió perfecto :'D
Es una verdadera maravilla poder arreglar el parpadeo en general, muchas veces me molestaba ese mini fallo y me hacia querer quitar el sistema (casi voy a la casa del creador a pedirle que lo arreglé, yo y mi pequeño palo de golf (?)), gracias por traerlo, he cambiado los bytes y funciona perfectamente :boogie:

Saludos!!!
 

Red_Viper

Usuario de platino
Re: [GBA] Arreglar el 'parpadeo' del DNS en los warp

Gracias por el aporte. ¡Samu, eres un mago!
 

~Zane~

Let's Roll Arceus
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

Tengo un problema y es que cuando le doy ir a el offset dice que no se encuentra esa direccion por que pasa esto ¿?
 

Rubire4

Usuario mítico
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

אלוהים;432702 dijo:
Tengo un problema y es que cuando le doy ir a el offset dice que no se encuentra esa direccion por que pasa esto ¿?
El offset que indica es el 080A1BC6. Por si no lo sabes, 08 es una parte del offset que indica que dicha dirección se encuentra en la memoria ROM. Por esa razón cuando permutamos añadimos el 08 al final. Así que cuando vayas a buscar un offset de este tipo simplemente quita el 08 de delante y ya está.
Un saludo.
 

Kammm

Profesional de WaH
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

¡Se me paso esto!

Ahora ya tengo un problema solucionado, gracias por el aporte
 

KERBEROS

Usuario de Platino
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

v¡OOOOOOOOOOOOHHHHHHHH!
bueno, con esto mejora mucho, aunque aun falta resolver el bug del multijugador..me refiero a que no se pueden hacer intercambios!
cuando se solucione eso si sera perfecta!
 

MACHINE

Space Cowboy
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

v¡OOOOOOOOOOOOHHHHHHHH!
bueno, con esto mejora mucho, aunque aun falta resolver el bug del multijugador..me refiero a que no se pueden hacer intercambios!
cuando se solucione eso si sera perfecta!
Disculpa, ¿Con el DNS aplicado no se pueden hacer intercambios? o ¿A que te refieres?
 

jirachiwish

Usuario de oro
Respuesta: [GBA] Arreglar el 'parpadeo' del DNS en los warp

Do you mind to fix the following bugs of DNS for me? Thanks a million.

1.When Wally catches his Ralts at the beginning of the game, the battle background defaults to daytime when he exits the Pokéballs Menu.

2.The background also always defaults to daytime although it's in the evening or at night while riding the cable car.



3.Navel Rock, Faraway Island and Birth Island do not have any Day and Night effects.
 

Nachoius

Caminante del cielo
Gracias samu, veré como queda esto, me ando informando sobre el DNS a ver que tal, si me conviene usarlo en el ancient o no.
 
Arriba