Sí llevas poco tiempo con el RH es muy probable que este tutorial no sea para tí, se sobrentiende que tienes conocimientos básicos en edición hexadecimal e inserción de tiles y paletas.
desde hace un tiempo tenía pendiende subir esta subrutina ASM que permite iluminar las ventanas de noche cuando se está utilizando el sistema D&N, el resultado podría ser el siguiente:
Antes de nada decir que la rutina ASM que ofrezco yo aquí está basada en una rutina que subió eing hace 2-3 años, cosa que le agradezco enormemente. Sin embargo, su rutina presenta varios problemas que han hecho que se pierda en el tiempo y no se use:
La rutina se encuentra integrada con otras 2 rutinas que pueden no interesarnos.
Una de estas rutinas es un sistema de reloj estilo "gta", en el que 4 horas reales son un día en el juego. Lamentablemente la hora se almacena en una variable cuyo valor no se guarda en el .sav, por lo que al apagar el emulador y limpiarse la ram, se pierde el valor de dicha variable. ¿Qué problema tiene esto? Cada vez que enciendes la "consola" son las 00:00.
La rutina solo funciona para pokemon ruby y no hay una versión descompilada de la misma que permita una fácil edición, lo que puede hacer que sea menos accesible.
Mi objetivos con este tutorial son los siguientes:
Hacer este sistema más accesible para todo el mundo.
Que la rutina esté disponible para los 3 rom base.
Explicar su funcionamiento junto con el funcionamiento de la rutina D&N para establecer las bases que permitan editar la rutina para iluminar las ventanas según la conveniencia/gustos de cada uno.
He decidido dividirlo en dos partes:
- Una primera parte para todos aquellos que no quieran romperse demasiado la cabeza (los cuales no podrán relizar ningún cambio sobre la rutina, ni siquiera cambiar los offsets del D&N).
- Una segunda parte para entender como funciona el sistema D&N y la subrutina de iluminación, así como editar la misma al gusto. No será estrictamente necesario tener conocimientos en ASM aunque tener una pequeña base ayudará a comprender la segunda parte del tutorial.
**IMPORTANTE**
Sea donde sea que insertes la rutina DAN asegúrate de dejar 0x120 bytes de espacio libre extra antes del comienzo de la misma.
Primeramente los programas que vamos a utilizar son los siguientes:
Podéis encontrarlos en google, wah, pokeco o en este enlace.
- Nuestra rom favorita.
- Un emulador que soporte RTC (VBA).
- Day, Night & Seasons de Prime-Dialga/Prime. Esta versión (Si usais otra puede no funcionar con las direcciones que doy)
versión.
- Un editor de texto plano (yo recomiendo Notepad++).
- Un compilador de instrucciones thumb (descargar aquí)
- Un debuger de gba (recomendado NO$GBA/NOSGBA).
Podéis encontrarlos en google, wah, pokeco o en este enlace.
Elige tu rom base:
Funcionamiento de la rutina:
Esta subrutina para iluminar las ventanas lo que hace es cambiar los colores de ciertas paletas por la noche, en concreto los siguientes:
Cualquier y digo CUALQUIER tile que utilice esos colores se verá iluminado de noche, por lo que tendréis que utilizar esos colores únicamente para las ventanas o las cosas que tengan que iluminarse.
En primer lugar vamos a instalar la rutina D&N. Abrimos el Day, Night and Seasons y cargamos la rom a editar.
Insertamos el RTC en la dirección 00B01000.
Insertamos el DAN en la dirección 00B00000.
Ahora que la rutina D&N está instalada tenemos que insertar la subrutina para iluminar las ventanas.
Abrimos el rom con el editor hexadecimal y vamos a la dirección 00B000D2 (control + g -> B000D2)
Cambiamos el byte "A8" por "05".
Vamos a la dirección 00AFFEE0 (cntrl + g -> AFFEE0).
Copiamos el siguiente código hexadecimal y lo pegamos en esa dirección (contrl + c -> copiar || control + b -> pegar):
Guardamos los cambios y ya hemos terminado de insertar el sistema.
Insertamos el RTC en la dirección 00B01000.
Insertamos el DAN en la dirección 00B00000.
Ahora que la rutina D&N está instalada tenemos que insertar la subrutina para iluminar las ventanas.
Abrimos el rom con el editor hexadecimal y vamos a la dirección 00B000D2 (control + g -> B000D2)
Cambiamos el byte "A8" por "05".
Vamos a la dirección 00AFFEE0 (cntrl + g -> AFFEE0).
Copiamos el siguiente código hexadecimal y lo pegamos en esa dirección (contrl + c -> copiar || control + b -> pegar):
Código:
0D 48 00 78 1E 28 14 D0 0C 48 00 78 00 28 01 D0 03 28 0E DD 0B 49 0E 4A 11 60 0B 49 0D 4A 11 80 0A 49 0D 4A 11 60 08 49 0C 4A 11 80 07 49 0C 4A 11 60 03 49 08 47 C0 46 5A 10 02 02 00 C0 03 02 27 00 B0 08 FF 5F BD 4B FF 5F 00 00 BD 4B 7B 3B 04 00 00 05 22 00 00 05 24 00 00 05 C2 00 00 05 C4 00 00 05
Guardamos los cambios y ya hemos terminado de insertar el sistema.
En primer lugar vamos a instalar la rutina D&N. Abrimos el Day, Night and Seasons y cargamos la rom a editar.
Insertamos el RTC en la dirección 00B01000.
Insertamos el DAN en la dirección 00B00000.
Ahora que la rutina D&N está instalada tenemos que insertar la subrutina para iluminar las ventanas.
Abrimos el rom con el editor hexadecimal y vamos a la dirección 00B000D2 (control + g -> B000D2)
Cambiamos el byte "A8" por "05".
Vamos a la dirección 00AFFEE0 (cntrl + g -> AFFEE0).
Copiamos el siguiente código hexadecimal y lo pegamos en esa dirección (contrl + c -> copiar || control + b -> pegar):
Guardamos los cambios y ya hemos terminado de insertar el sistema.
Insertamos el RTC en la dirección 00B01000.
Insertamos el DAN en la dirección 00B00000.
Ahora que la rutina D&N está instalada tenemos que insertar la subrutina para iluminar las ventanas.
Abrimos el rom con el editor hexadecimal y vamos a la dirección 00B000D2 (control + g -> B000D2)
Cambiamos el byte "A8" por "05".
Vamos a la dirección 00AFFEE0 (cntrl + g -> AFFEE0).
Copiamos el siguiente código hexadecimal y lo pegamos en esa dirección (contrl + c -> copiar || control + b -> pegar):
Código:
0D 48 40 78 1E 28 14 D0 0C 48 00 78 00 28 01 D0 03 28 0E DD 0B 49 0E 4A 11 60 0B 49 0D 4A 11 80 0A 49 0D 4A 11 60 08 49 0C 4A 11 80 07 49 0C 4A 11 60 03 49 08 47 C0 46 91 16 02 02 00 C0 03 02 27 00 B0 08 FF 5F BD 4B FF 5F 00 00 BD 4B 7B 3B 04 00 00 05 22 00 00 05 24 00 00 05 C2 00 00 05 C4 00 00 05
Guardamos los cambios y ya hemos terminado de insertar el sistema.
Es importante recalcar para Pokemon Esmeralda que el Day&Night tiene un pequeño fallo. En la dirección en la que se inserta la rutina la rutina del RTC se insertará la rutina DAN y la dirección en la que se inserta al rutina DAN se insertará la rutina RTC. (simplemente los offsets se intercambian, si seguís el tutorial al pié de la letra no tendréis ningún problema).
En primer lugar vamos a instalar la rutina D&N. Abrimos el Day, Night and Seasons y cargamos la rom a editar.
Insertamos el RTC en la dirección 00F00000 (en realidad insertamos DAN).
Insertamos el DAN en la dirección 00F01000 (en realidad insertamos el RTC).
Ahora que la rutina D&N está instalada tenemos que insertar la subrutina para iluminar las ventanas.
Abrimos el rom con el editor hexadecimal y vamos a la dirección 00F000D2 (control + g -> F000D2)
Cambiamos el byte "D2" por "05".
Vamos a la dirección 00EFFEE0 (cntrl + g -> EFFEE0).
Copiamos el siguiente código hexadecimal y lo pegamos en esa dirección (contrl + c -> copiar || control + b -> pegar):
Guardamos los cambios y ya hemos terminado de insertar el sistema.
En primer lugar vamos a instalar la rutina D&N. Abrimos el Day, Night and Seasons y cargamos la rom a editar.
Insertamos el RTC en la dirección 00F00000 (en realidad insertamos DAN).
Insertamos el DAN en la dirección 00F01000 (en realidad insertamos el RTC).
Ahora que la rutina D&N está instalada tenemos que insertar la subrutina para iluminar las ventanas.
Abrimos el rom con el editor hexadecimal y vamos a la dirección 00F000D2 (control + g -> F000D2)
Cambiamos el byte "D2" por "05".
Vamos a la dirección 00EFFEE0 (cntrl + g -> EFFEE0).
Copiamos el siguiente código hexadecimal y lo pegamos en esa dirección (contrl + c -> copiar || control + b -> pegar):
Código:
0D 48 40 78 1E 28 14 D0 0C 48 00 78 00 28 01 D0 03 28 0E DD 0B 49 0E 4A 11 60 0B 49 0D 4A 11 80 0A 49 0D 4A 11 60 08 49 0C 4A 11 80 07 49 0C 4A 11 60 03 49 08 47 C0 46 85 16 02 02 00 C0 03 02 27 00 F0 08 FF 5F BD 4B FF 5F 00 00 BD 4B 7B 3B 04 00 00 05 22 00 00 05 24 00 00 05 C2 00 00 05 C4 00 00 05
Guardamos los cambios y ya hemos terminado de insertar el sistema.
Funcionamiento de la rutina:
Esta subrutina para iluminar las ventanas lo que hace es cambiar los colores de ciertas paletas por la noche, en concreto los siguientes:
- Tileset principal: Paleta 0[colores 2, 3], Paleta 1[colores 1, 2, 3]
- Tileset secundario: Paleta 6[colores 1, 2, 3]
Cualquier y digo CUALQUIER tile que utilice esos colores se verá iluminado de noche, por lo que tendréis que utilizar esos colores únicamente para las ventanas o las cosas que tengan que iluminarse.
Si has llegado hasta aquí, entiendo que no te asusta demasiado pensar, aunque sea un poco. Bienvenido.
Doy por supuesto que saber usar el "Day, Night and Seasons" pero aquí tienes un pequeño recordatorio (por si hay algún despistado).
Primeramente creo que es importante explicar el funcionamiento de la rutina DAN sin entrar en muchos detalles para que pueda entenderse más allá de lo frío que puedan dejar a mucha gente las instrucciones thumb.
-En colores azules se encuentran los fragmentos de código encargados de realizar las comprobaciones que decidirán si ha de aplicarse el filtro de iluminación o no, esto se hará en función de lo que hayamos seleccionado en el programa (excepciones[cuevas,interiores], si estamos en un menú, si es un combate...)
-En colores verdes tenemos las partes del código que escogen el filtro de color que toca y lo aplican a cada uno de los colores de las paletas afectadas.
-En color rojo/naranja están las instrucciones que se encargan de finalizar la rutina.
Aquí las instrucciones de la rutina DAN:
Nosotros lo que vamos a hacer, explicándolo de forma que lo pueda entender todo el mundo, es "cortar la conexión" entre los números "6-7", conectar "6" con la subrutina que ilumina las ventanas y mandar el final de esta subrutina a "7".
Bien, ahora que todos sabemos como funciona la rutina DAN (aunque sea por encima) creo que nos será más fácil entender la subrutina para iluminar las ventanas y editarla. La rutina sin compilar es la siguiente:
(Recomendable leer los comentarios de la rutina).
Como algunos ya os habréis dado cuenta está rutina lo que hace no es "iluminar" los colores de ciertas paletas, si no que sobrescribe ciertos colores por otros. Por decirlo de otra manera, yo lo he utilizado para iluminar las ventanas, pero podéis utilizarlo para cambiar de color cualquier cosa en función de la hora. Podéis oscurecer algo, iluminarlo de otro color totalmente distinto al que he usado yo (los que traía la rutina de eing) o lo que se os ocurra.
Los colores modificados (iluminados) son los siguientes:
main:
Aquí se encuentran las condiciones que decidirán si se ejecuta el cambio de colores o no, podéis añadir nuevas condiciones (como por ejemplo el tileset del mapa actual), para editar esto es necesario que tengáis conocimientos en ASM.
execute:
Aquí se ejecuta el cambio de colores, para cada color o pareja de colores tendremos que utilizar la siguiente estructura:
gotoDN:
Aquí debemos escribir la dirección a la que debe ir la subrutina iluminar al terminar.
Como hemos mencionado antes lo que nos interesa es mandarlo al apartado "7" de la rutina DAN principal, a la instrucción pop{r0-r7}. Está instrucción debería encontrarse en la dirección -> Dirección donde insertamos DAN + 26, a esta dirección debemos de sumarle 1.
Otras modificaciones que podéis hacer con algunos conocimientos de ASM son por ejemplo:
Cambiar las franjas horarias en las que se activa la iluminación (podéis hacer que algo cambie de color durante el día, que ciertas paletas se "apaguen" a las 12 de la noche). También podéis hacer distintos tipos de iluminación o cambios de color en función del tileset del mapa en el que os encontráis... En fin, hay muchísimas opciones, os dejo las direcciones necesarias para realizar algunas de estas modificaciones en cada uno de los rom.
Doy por supuesto que saber usar el "Day, Night and Seasons" pero aquí tienes un pequeño recordatorio (por si hay algún despistado).
-En colores azules se encuentran los fragmentos de código encargados de realizar las comprobaciones que decidirán si ha de aplicarse el filtro de iluminación o no, esto se hará en función de lo que hayamos seleccionado en el programa (excepciones[cuevas,interiores], si estamos en un menú, si es un combate...)
-En colores verdes tenemos las partes del código que escogen el filtro de color que toca y lo aplican a cada uno de los colores de las paletas afectadas.
-En color rojo/naranja están las instrucciones que se encargan de finalizar la rutina.
Aquí las instrucciones de la rutina DAN:
Los números indican el orden de ejecución (exceptuando a 2.5).
Bien, ahora que todos sabemos como funciona la rutina DAN (aunque sea por encima) creo que nos será más fácil entender la subrutina para iluminar las ventanas y editarla. La rutina sin compilar es la siguiente:
(Recomendable leer los comentarios de la rutina).
Código:
.thumb
.align 2
@;Rutina ruby || todo lo que hay después de @ es un comentario
main: @;checkea si estamos en un combate || stanceByte = 1E.
ldr r0, stanceByte @;si estamos en combate finaliza la rutina.
ldrb r0, [r0]
cmp r0, #0x1E
beq end
ldr r0, timeStatusbyte @;checkea si la franja horaria corresponde e la noche
ldrb r0, [r0] @; (satus byte = 0, 4 o 5)
cmp r0, #0x0
beq execute
cmp r0, #0x3
ble end
execute: @;Cambia los colores de las paletas a los colores "iluminados".
ldr r1, COLOR_1 @;Carga los dos colores en r1
ldr r2, PAL_0_C2_3 @;Carda la dirección del color 2 de la paleta 0
str r1, [r2] @;Guarda los colores de r1 en r2 (al no caber ambos colores en el "espacio" del color 2 el segundo pasa al color 3
ldr r1, COLOR_2 @;Carga UN color en r1 (SOLO UN COLOR)
ldr r2, PAL_1_C1 @;Carga la dirección del color 1 de la paleta 1
strh r1, [r2] @;Guarda el color de r1 en r2
ldr r1, COLOR_3 @;El resto es lo mismo cambiando los colores y las paletas.
ldr r2, PAL_1_C2_3
str r1, [r2]
ldr r1, COLOR_2
ldr r2, PAL_6_C1
strh r1, [r2]
ldr r1, COLOR_3
ldr r2, PAL_6_C2_C3
str r1, [r2]
end: @;fin de la subrutina y vuelta a D&N
ldr r1, gotoDN
bx r1
.align 2
stanceByte:
.word 0x0202105A @;(+1) Si el valor de byte es 1E estamos en combate
timeStatusbyte:
.word 0x0203C000 @;Statusbyte del DAN [0-5](indica la franja del día)
gotoDN:
.word 0x08B00027 @;Dirección del D&N + 27 [26+1]
@;Colores en formato de 15b RGB (7FFF)
COLOR_1:
.word 0x4BBD5FFF @;2 Colores en formato 15b (7FFF-7FFF)
COLOR_2:
.word 0x00005FFF @;1 Color en formato 15b (0000-7FFF)
COLOR_3:
.word 0x3B7B4BBD @;2 Colores en formato 15b (7FFF-7FFF)
@;Direcciones de las paletas
PAL_0_C2_3:
.word 0x05000004 @;dirección del color 2 de la paleta 0
PAL_1_C1:
.word 0x05000022 @;direccion del color 1 de la paleta 1
PAL_1_C2_3:
.word 0x05000024 @;dirección del color 2 de la paleta 1
PAL_6_C1:
.word 0x050000C2 @;dirección del color 1 de la paleta 6
PAL_6_C2_C3:
.word 0x050000C4 @;dirección del color 2 de la paleta 6
Código:
.thumb
.align 2
@;Rutina fire red || todo lo que hay después de @ es un comentario
main: @;checkea si estamos en un combate || stanceByte = 1E.
ldr r0, stanceByte @;si estamos en combate finaliza la rutina.
ldrb r0, [r0, #0x1]
cmp r0, #0x1E
beq end
ldr r0, timeStatusbyte @;checkea si la franja horaria corresponde e la noche
ldrb r0, [r0] @;(satus byte = 0, 4 o 5)
cmp r0, #0x0
beq execute
cmp r0, #0x3
ble end
execute: @;Cambia los colores de las paletas a los colores "iluminados".
ldr r1, COLOR_1 @;Carga los dos colores en r1
ldr r2, PAL_0_C2_3 @;Carda la dirección del color 2 de la paleta 0
str r1, [r2] @;Guarda los colores de r1 en r2 (al no caber ambos colores en el "espacio" del color 2 el segundo pasa al color 3
ldr r1, COLOR_2 @;Carga UN color en r1 (SOLO UN COLOR)
ldr r2, PAL_1_C1 @;Carga la dirección del color 1 de la paleta 1
strh r1, [r2] @;Guarda el color de r1 en r2
ldr r1, COLOR_3 @;El resto es lo mismo cambiando los colores y las paletas.
ldr r2, PAL_1_C2_3
str r1, [r2]
ldr r1, COLOR_2
ldr r2, PAL_6_C1
strh r1, [r2]
ldr r1, COLOR_3
ldr r2, PAL_6_C2_C3
str r1, [r2]
end: @;fin de la subrutina y vuelta a D&N
ldr r1, gotoDN
bx r1
.align 2
stanceByte:
.word 0x02021691 @;(+1) Si el valor de byte es 1E estamos en combate
timeStatusbyte:
.word 0x0203C000 @;Statusbyte del DAN [0-5](indica la franja del día)
gotoDN:
.word 0x08B00027 @;Dirección del D&N + 27 [26+1]
@;Colores en formato de 15b RGB (7FFF)
COLOR_1:
.word 0x4BBD5FFF @;2 Colores en formato 15b (7FFF-7FFF)
COLOR_2:
.word 0x00005FFF @;1 Color en formato 15b (0000-7FFF)
COLOR_3:
.word 0x3B7B4BBD @;2 Colores en formato 15b (7FFF-7FFF)
@;Direcciones de las paletas
PAL_0_C2_3:
.word 0x05000004 @;dirección del color 2 de la paleta 0
PAL_1_C1:
.word 0x05000022 @;direccion del color 1 de la paleta 1
PAL_1_C2_3:
.word 0x05000024 @;dirección del color 2 de la paleta 1
PAL_6_C1:
.word 0x050000C2 @;dirección del color 1 de la paleta 6
PAL_6_C2_C3:
.word 0x050000C4 @;dirección del color 2 de la paleta 6
Código:
.thumb
.align 2
@;Rutina emerald || todo lo que hay después de @ es un comentario
main: @;checkea si estamos en un combate || stanceByte = 1E.
ldr r0, stanceByte @;si estamos en combate finaliza la rutina.
ldrb r0, [r0, #0x1]
cmp r0, #0x1E
beq end
ldr r0, timeStatusbyte @;checkea si la franja horaria corresponde e la noche
ldrb r0, [r0] @; (satus byte = 0, 4 o 5)
cmp r0, #0x0
beq execute
cmp r0, #0x3
ble end
execute: @;Cambia los colores de las paletas a los colores "iluminados".
ldr r1, COLOR_1 @;Carga los dos colores en r1
ldr r2, PAL_0_C2_3 @;Carda la dirección del color 2 de la paleta 0
str r1, [r2] @;Guarda los colores de r1 en r2 (al no caber ambos colores en el "espacio" del color 2 el segundo pasa al color 3
ldr r1, COLOR_2 @;Carga UN color en r1 (SOLO UN COLOR)
ldr r2, PAL_1_C1 @;Carga la dirección del color 1 de la paleta 1
strh r1, [r2] @;Guarda el color de r1 en r2
ldr r1, COLOR_3 @;El resto es lo mismo cambiando los colores y las paletas.
ldr r2, PAL_1_C2_3
str r1, [r2]
ldr r1, COLOR_2
ldr r2, PAL_6_C1
strh r1, [r2]
ldr r1, COLOR_3
ldr r2, PAL_6_C2_C3
str r1, [r2]
end: @;fin de la subrutina y vuelta a D&N
ldr r1, gotoDN
bx r1
.align 2
stanceByte:
.word 0x02021685 @;(+1) Si el valor de byte es 1E estamos en combate
timeStatusbyte:
.word 0x0203C000 @;Statusbyte del DAN [0-5](indica la franja del día)
gotoDN:
.word 0x08F00027 @;Dirección del D&N + 27 [26+1]
@;Colores en formato de 15b RGB (7FFF)
COLOR_1:
.word 0x4BBD5FFF @;2 Colores en formato 15b (7FFF-7FFF)
COLOR_2:
.word 0x00005FFF @;1 Color en formato 15b (0000-7FFF)
COLOR_3:
.word 0x3B7B4BBD @;2 Colores en formato 15b (7FFF-7FFF)
@;Direcciones de las paletas
PAL_0_C2_3:
.word 0x05000004 @;dirección del color 2 de la paleta 0
PAL_1_C1:
.word 0x05000022 @;direccion del color 1 de la paleta 1
PAL_1_C2_3:
.word 0x05000024 @;dirección del color 2 de la paleta 1
PAL_6_C1:
.word 0x050000C2 @;dirección del color 1 de la paleta 6
PAL_6_C2_C3:
.word 0x050000C4 @;dirección del color 2 de la paleta 6
Como algunos ya os habréis dado cuenta está rutina lo que hace no es "iluminar" los colores de ciertas paletas, si no que sobrescribe ciertos colores por otros. Por decirlo de otra manera, yo lo he utilizado para iluminar las ventanas, pero podéis utilizarlo para cambiar de color cualquier cosa en función de la hora. Podéis oscurecer algo, iluminarlo de otro color totalmente distinto al que he usado yo (los que traía la rutina de eing) o lo que se os ocurra.
Los colores modificados (iluminados) son los siguientes:
- Tileset principal: Paleta 0[colores 2, 3], Paleta 1[colores 1, 2, 3]
- Tileset secundario: Paleta 6[colores 1, 2, 3]
Código:
.thumb
.align 2
@;Rutina ruby || todo lo que hay después de @ es un comentario
main: @;checkea si estamos en un combate || stanceByte = 1E.
ldr r0, stanceByte @;si estamos en combate finaliza la rutina.
ldrb r0, [r0]
cmp r0, #0x1E
beq end
ldr r0, timeStatusbyte @;checkea si la franja horaria corresponde e la noche
ldrb r0, [r0] @; (satus byte = 0, 4 o 5)
cmp r0, #0x0
beq execute
cmp r0, #0x3
ble end
execute:
ldr r1, COLOR
ldr r2, PALETA
str r1, [r2] // strh r1, [r2]
end: @;fin de la subrutina y vuelta a D&N
ldr r1, gotoDN
bx r1
.align 2
stanceByte:
.word 0x0202105A
timeStatusbyte:
.word 0x0203C000
gotoDN:
.word 0x(offset de la rutina DAN + 27)
@;Colores en formato de 15b RGB (7FFF)
COLOR:
.word 0x(valor de 2 colores en rgb 15b)
COLOR:
.word 0x0000(valor de 1 color en rgb 15b)
@;Direcciones de las paletas
PALETA:
.word 0x5(dirección en la ram del color de la paleta que se desea sobrescribir)
Código:
.thumb
.align 2
@;Rutina fire red || todo lo que hay después de @ es un comentario
main: @;checkea si estamos en un combate || stanceByte = 1E.
ldr r0, stanceByte @;si estamos en combate finaliza la rutina.
ldrb r0, [r0, #0x1]
cmp r0, #0x1E
beq end
ldr r0, timeStatusbyte @;checkea si la franja horaria corresponde e la noche
ldrb r0, [r0] @; (satus byte = 0, 4 o 5)
cmp r0, #0x0
beq execute
cmp r0, #0x3
ble end
execute:
ldr r1, COLOR
ldr r2, PALETA
str r1, [r2] // strh r1, [r2]
end: @;fin de la subrutina y vuelta a D&N
ldr r1, gotoDN
bx r1
.align 2
stanceByte:
.word 0x02021691
timeStatusbyte:
.word 0x0203C000
gotoDN:
.word 0x(offset de la rutina DAN + 27)
@;Colores en formato de 15b RGB (7FFF)
COLOR:
.word 0x(valor de 2 colores en rgb 15b)
COLOR:
.word 0x0000(valor de 1 color en rgb 15b)
@;Direcciones de las paletas
PALETA:
.word 0x5(dirección en la ram del color de la paleta que se desea sobrescribir)
Código:
.thumb
.align 2
@;Rutina emerald || todo lo que hay después de @ es un comentario
main: @;checkea si estamos en un combate || stanceByte = 1E.
ldr r0, stanceByte @;si estamos en combate finaliza la rutina.
ldrb r0, [r0, #0x1]
cmp r0, #0x1E
beq end
ldr r0, timeStatusbyte @;checkea si la franja horaria corresponde e la noche
ldrb r0, [r0] @; (satus byte = 0, 4 o 5)
cmp r0, #0x0
beq execute
cmp r0, #0x3
ble end
execute:
ldr r1, COLOR
ldr r2, PALETA
str r1, [r2] // strh r1, [r2]
end: @;fin de la subrutina y vuelta a D&N
ldr r1, gotoDN
bx r1
.align 2
stanceByte:
.word 0x02021685
timeStatusbyte:
.word 0x0203C000
gotoDN:
.word 0x(offset de la rutina DAN + 27)
@;Colores en formato de 15b RGB (7FFF)
COLOR:
.word 0x(valor de 2 colores en rgb 15b)
COLOR:
.word 0x0000(valor de 1 color en rgb 15b)
@;Direcciones de las paletas
PALETA:
.word 0x5(dirección en la ram del color de la paleta que se desea sobrescribir)
Aquí se encuentran las condiciones que decidirán si se ejecuta el cambio de colores o no, podéis añadir nuevas condiciones (como por ejemplo el tileset del mapa actual), para editar esto es necesario que tengáis conocimientos en ASM.
execute:
Aquí se ejecuta el cambio de colores, para cada color o pareja de colores tendremos que utilizar la siguiente estructura:
Código:
@Se insertan dos colores (4 bytes, palabra completa) -- str
ldr r1, COLOR
ldr r2, PALETA
str r1, [r2]
//
@Se inserta un color (2 bytes, hword) -- srth
ldr r1, COLORES
ldr r2, PALETA
strh r1, [r2]
Aquí debemos escribir la dirección a la que debe ir la subrutina iluminar al terminar.
Como hemos mencionado antes lo que nos interesa es mandarlo al apartado "7" de la rutina DAN principal, a la instrucción pop{r0-r7}. Está instrucción debería encontrarse en la dirección -> Dirección donde insertamos DAN + 26, a esta dirección debemos de sumarle 1.
Código:
gotoDN:
.word 0x08XXYYZZ+27 @siendo por defecto 08B00027
Direcciones de los colores de las paletas en la ram:
Para encontrar las direcciones de cada uno de los colores de las distintas paletas de los tilesets primario y secundario es bastante sencillo:
Abrimos el rom con el emulador VBA y vamos a opciones-> pallete viewer
Las paletas de los tilesets son las del apartado "background", cada fila es una paleta y cada casilla un color. Si pinchamos en el color nos saldrá su dirección en la ram.
Para encontrar las direcciones de cada uno de los colores de las distintas paletas de los tilesets primario y secundario es bastante sencillo:
Abrimos el rom con el emulador VBA y vamos a opciones-> pallete viewer
Las paletas de los tilesets son las del apartado "background", cada fila es una paleta y cada casilla un color. Si pinchamos en el color nos saldrá su dirección en la ram.
Status Byte (hora): 0x0203C000 [viene dado por el sistema DAN-RTC]
- Tipo de mapa: 0x0202E83F [0-9]
- Check combat/menu: 0x0202105A [0- mundo, 1E- combate, A0- menu]
- Datos del mapa actual: 0x [+4 banco del mapa, +5 numero del mapa]
- Tipo de mapa: 0x02036E13 [0-9]
- Check menu: 0x02021691 [0- fuera de menu, 1- en un menu]
- Check combat: 0x02021691+1 [0- mundo, 1E- combate, A0- menu]
- Tipo de mapa: 0x0203732F [0-9]
- Check menu: 0x02021685 [0- fuera de menu, 1- en un menu]
- Check combat: 0x02021685+1 [0- mundo, 1E- combate, A0- menu]
- Datos del mapa actual(pointer al offset dynamico): 0x3005D8C [+4 banco del mapa, +5 numero del mapa]
Otras modificaciones que podéis hacer con algunos conocimientos de ASM son por ejemplo:
Cambiar las franjas horarias en las que se activa la iluminación (podéis hacer que algo cambie de color durante el día, que ciertas paletas se "apaguen" a las 12 de la noche). También podéis hacer distintos tipos de iluminación o cambios de color en función del tileset del mapa en el que os encontráis... En fin, hay muchísimas opciones, os dejo las direcciones necesarias para realizar algunas de estas modificaciones en cada uno de los rom.
Este apartado es para aquellas personas que no sepan como compilar una rutina asm.
En este caso sustituyo los colores 1, 2 y 3 de la paleta 2.
Creamos un documento de texto nuevo y cambiamos la extensión a .asm
El documento podemos abrirlo con el bloc de notas (recomiendo Notepad++). Pegamos la plantilla correspondiente a nuestra rom base.
Editamos la rutina para que sustituya los colores que queremos
En este caso sustituyo los colores 1, 2 y 3 de la paleta 2.
Guardamos el archivo y lo dejamos en el mismo directorio que el compilador.
Abrimos cmd y nos dirigimos al directorio en el que se encuentran la rutina y el compilador (Creo que es bastante obvio pero... escribid el directorio donde esta VUESTRA rutina, no escribáis mí directorio).
Introducimos el siguiente comando: "thumb nombre_rutina.asm nombre_rutina.bin"
Enhorabuena has compilado la rutina y obtenido un archivo .bin
- Abre el .bin con un editor hexadecimal y obtendrás la rutina en hexadecimal.
Para insertar la rutina lo que vamos a tener que hacer es lo que comenté anteriormente:
Nos dirigimos a la dirección en la que insertamos el DAN - 120 bytes (por defecto AFFEE0) e insertamos la subrutina que modificamos y compilamos anteriormente en esta dirección.
Vamos a abrir el rom con el editor hexadecimal (HxD) y nos dirigiremos a la dirección en la que hayamos instalado la rutina DAN+D2 Bytes (por defecto B000D2), en esta dirección nos encontraremos el byte "A8" seguido del byte "E7". Sustituimos "A8" por "05".Nosotros lo que vamos a hacer, explicándolo de forma que lo pueda entender todo el mundo, es "cortar la conexión" entre los números "6-7", conectar "6" con la subrutina que ilumina las ventanas y mandar el final de esta subrutina a "7".
Si no se entiende algo ver el esquema del DAN más arriba.
Los bytes de DAN+D2//DAN+D3 hacen referencia a la instrucción thumb E7A8, siendo E7 el byte correspondiente a "b" o "branch", una instrucción que hace que el programa "salte" dirigiéndose a la dirección relativa a la que apunta el byte "A8".
Esta dirección relativa apunta a DAN+27 (apartado "7" de la rutina) por lo que al cambiar "A8" por "05" el b o branch pasa a apuntar a la dirección -> dirección del DAN-120 Bytes (por defecto AFFEE0).
De esta manera habremos cortado la conexión entre "6" y "7", haciendo que "6" apunte a la nueva dirección en la que insertaremos nuestra subrutina de iluminar.
Esta dirección relativa apunta a DAN+27 (apartado "7" de la rutina) por lo que al cambiar "A8" por "05" el b o branch pasa a apuntar a la dirección -> dirección del DAN-120 Bytes (por defecto AFFEE0).
De esta manera habremos cortado la conexión entre "6" y "7", haciendo que "6" apunte a la nueva dirección en la que insertaremos nuestra subrutina de iluminar.
Nos dirigimos a la dirección en la que insertamos el DAN - 120 bytes (por defecto AFFEE0) e insertamos la subrutina que modificamos y compilamos anteriormente en esta dirección.
Recordar que anteriormente, mientras editabamos la rutina ASM, la configuramos para que volviese al apartado "7" de la rutina DAN al terminar de ejecutarse
- Eing por la idea y la rutina originales.
- Prime-Dialga/Prime por crear el Day, Night and Seasons.
- HackMew/ShinyQuagsire (No se de cual de los dos es el compilador que he compartido aquí pero vamos, ambos se merecen que les coma todos los... pies de Castform).
PD: Cualquier duda puedo resolverla tanto por aquí como por Discord (@Xhyz7194). En caso de ser por discord dejaré constancia luego en el foro por si alguien más tuviera la misma duda
Última edición: