WHAT THE HELL IS THIS?
No sé si recordarás que (a long, long time ago) empecé un proyecto en Emerald en el que iba a introducir distintas rutinas para hacer una rom base. ¿No lo recuerdas, dices? Ya me lo imaginaba... De cualquier modo, ese proyecto fue cancelado por razones de tiempo. ¿Cómo dices? ¿Que ya te lo esperabas? Uhm... Bueno, pues, aunque el proyecto fue cancelado, hice varias rutinas que están acumulando polvo en una carpeta de mi disco duro. Si a eso le sumas alguna que otra rutina que he hecho por encargo, más alguna que otra que hice para el Pokémon Inmortal, pues... ¿Cómo? ¿Que qué es el Pokémon Inmortal? Oh, Dios... ¡Eso sí que me duele!
Como iba diciendo antes de que me volvieras a cortar, he decidido ir publicando esas rutinas para que las puedas utilizar si las necesitas. Pero antes de lanzarte en plancha a ellas, échale un vistazo a la siguiente sección para enterarte bien de la compatibilidad de las mismas. Porque no, no son para Emerald.
COMPATIBILIDAD
Todas las rutinas que publique son para Pokémon Fire Red USA. Esa es la base con la que yo trabajo y es la base con la que recomiendo que trabajes tú. No obstante, si necesitas alguna de las rutinas para otra base distinta, deja un comentario e intentaré adaptarla.
¿CUÁNTO CUESTA?
El trato justo sería que me invitaras a una copa, pero como sé que no lo vas a hacer, al menos, da créditos si utilizas alguna de las rutinas. Poner mi nombre en la lista de créditos es infinitamente menos costoso que hacer las rutinas, no te costará nada. A mí, sin embargo, me alegrará que valores mi trabajo.
CRONÓMETRO
Esta rutina fue concebida como un cronómetro. Si has jugado, mi hack recordarás partes como la de robar a la señora que, sin las zapatillas, no te da tiempo a huir; o las pruebas de submarinista, que utilizan cronómetro. Por supuesto, las puedes utilizar para comprobar el tiempo total de juego o cualquier acrobacia lógica que se te ocurra (?).
En realidad son dos rutinas. Como sabrás, el juego cuenta con un reloj que está constantemente funcionando. Hablo del reloj que mide el tiempo jugado en una partida. Ese es precisamente el reloj que utilizaremos para poner en marcha nuestro cronómetro. Con respecto a dicho reloj, no te preocupes por él, seguirá funcionando sin problemas, ya que lo único que haremos será leer el tiempo.
La primera rutina se encarga simplemente de copiar el tiempo de juego y llevárselo a las variables 0x8000 (donde se guardan los segundos y los minutos) y 0x8001 (donde se guardan las horas). Hasta aquí, sería útil para hacer una comprobación del tiempo de juego (por ejemplo, si quisieras que un evento no sucediera hasta que llevaras x horas de juego).
Aquí está la rutina:
La segunda rutina es realmente la que tiene la dificultad, porque se encarga de restar el tiempo de juego. Pero es la que interesa. Lo que hace es que al tiempo que tengamos en las variables 0x8000 y 0x8001 le resta el tiempo que tengamos en las variables 0x8004 y 0x8005. Como sabrás, estas variables son volátiles, por lo que, si quieres guardar el tiempo, deberás hacer un copyvar para guardarlo en una variable segura.
La rutina es esta:
Y ahora que ya tenemos las dos rutinas y que más o menos sabes cómo funciona cada una, te voy a explicar un poco más detalladamente cómo hacer un cronómetro en un evento.
Imaginemos, por ejemplo, que quieres hablar con un NPC y que este te rete a encontrar en el mapa un objeto oculto en el menor tiempo posible. Para ello, debemos cronometrar el tiempo que tardamos en dar con el objeto y volver a hablar con el NPC para demostrarle que lo tenemos.
Por tanto, al hablar con el NPC ("Preparados... Listos... ¡Ya!"), lo que haremos será ejecutar la primera rutina (callasm 0x(offset + 1), de manera que se guardará el tiempo que llevamos jugado en ese momento en las variables 0x8000 y 0x8001. Luego haremos dos copyvar para guardar los valores en dos variables seguras. De esta forma, puedes guardar y cerrar la partida y, en cambio, el cronómetro seguirá funcionando cuando vuelvas a jugar.
A continuación, buscas el objeto, lo encuentras y vuelves a hablar con el NPC ("¡Ya lo tengo!"). Ahora quieres saber, por tanto, el tiempo que has tardado en encontrar el objeto. Pues es muy simple, habrás tardado el tiempo que lleves de partida en ese mismo momento menos el tiempo que llevaras de partida cuando empezaste a buscarlo.
Para ello, ejecutas de nuevo la primera rutina. Es decir, cargas el tiempo actual de juego en las variables 0x8000 y 0x8001. Después, haces dos copyvar para cargar el tiempo que llevabas de partida en el primer momento y lo copias en las variables 0x8004 y 0x8005. Por último, ejecutas la segunda rutina y se restará el tiempo.
El resultado se guardará en las variables 0x8004 (segundos y minutos) y 0x8005 (horas). Por tanto, lo último que te queda es, mediante script, comprobar los valores de dichas variables para ver si has tardado mucho, si has tardado poco o lo que quieras comprobar.
La estructura del tiempo en la ram es la siguiente: [XX][YY][ZZZZ]. Donde XX son los segundos, YY los minutos y ZZZZ las horas. Si no eres muy avanzado y te lías con eso, lo mejor es que hagas pruebas mirando directamente los resultados en la ram (en 0x020370B8).
La primera rutina se encarga simplemente de copiar el tiempo de juego y llevárselo a las variables 0x8000 (donde se guardan los segundos y los minutos) y 0x8001 (donde se guardan las horas). Hasta aquí, sería útil para hacer una comprobación del tiempo de juego (por ejemplo, si quisieras que un evento no sucediera hasta que llevaras x horas de juego).
Aquí está la rutina:
Código:
.align 2
.thumb
push {r0-r2,lr}
ldr r0, .asdf
ldr r0, [r0]
mov r2, #0x0
ldr r1, .var_8000
ldrb r2, [r0,#0x11]
strb r2, [r1]
ldrb r2, [r0,#0x10]
strb r2, [r1,#0x1]
ldrb r2, [r0,#0xE]
strb r2, [r1,#0x2]
ldrb r2, [r0,#0xF]
strb r2, [r1,#0x3]
pop {r0-r2,pc}
.asdf: .word 0x0300500C
.var_8000: .word 0x020370B8
Código:
07 B5 06 48 00 68 00 22 05 49 42 7C 0A 70 02 7C 4A 70 82 7B 8A 70 C2 7B CA 70 07 BD 0C 50 00 03 B8 70 03 02
La rutina es esta:
Código:
.align 2
.thumb
push {r0-r6,lr}
ldr r0, .var_8000
ldrb r1, [r0,#0x8]
ldrb r2, [r0]
ldr r3, =0x3C
sub r4, r3, r1
add r4, r4, r2
cmp r4, #0x3C
blo part2
sub r4, r4, r3
mov r5, #0x1
part2:
strb r4, [r0,#0x8]
ldrb r1, [r0,#0x9]
ldrb r2, [r0,#0x1]
sub r4, r3, r1
add r4, r4, r2
cmp r5, #0x1
beq part3
mov r6, #0x1
sub r4, r4, r6
part3:
mov r5, #0x0
cmp r4, #0x3C
blo part4
sub r4, r4, r3
mov r5, #0x1
part4:
strb r4, [r0,#0x9]
ldrh r1, [r0,#0xA]
ldrh r2, [r0,#0x2]
sub r4, r2, r1
cmp r5, #0x1
beq part5
sub r4, r4, r6
part5:
strh r4, [r0,#0xA]
pop {r0-r6,pc}
.var_8000: .word 0x020370B8
Código:
7F B5 10 48 01 7A 02 78 3C 23 5C 1A A4 18 3C 2C 01 D3 E4 1A 01 25 04 72 41 7A 42 78 5C 1A A4 18 01 2D 01 D0 01 26 A4 1B 00 25 3C 2C 01 D3 E4 1A 01 25 44 72 41 89 42 88 54 1A 01 2D 00 D0 A4 1B 44 81 7F BD B8 70 03 02
Imaginemos, por ejemplo, que quieres hablar con un NPC y que este te rete a encontrar en el mapa un objeto oculto en el menor tiempo posible. Para ello, debemos cronometrar el tiempo que tardamos en dar con el objeto y volver a hablar con el NPC para demostrarle que lo tenemos.
Por tanto, al hablar con el NPC ("Preparados... Listos... ¡Ya!"), lo que haremos será ejecutar la primera rutina (callasm 0x(offset + 1), de manera que se guardará el tiempo que llevamos jugado en ese momento en las variables 0x8000 y 0x8001. Luego haremos dos copyvar para guardar los valores en dos variables seguras. De esta forma, puedes guardar y cerrar la partida y, en cambio, el cronómetro seguirá funcionando cuando vuelvas a jugar.
A continuación, buscas el objeto, lo encuentras y vuelves a hablar con el NPC ("¡Ya lo tengo!"). Ahora quieres saber, por tanto, el tiempo que has tardado en encontrar el objeto. Pues es muy simple, habrás tardado el tiempo que lleves de partida en ese mismo momento menos el tiempo que llevaras de partida cuando empezaste a buscarlo.
Para ello, ejecutas de nuevo la primera rutina. Es decir, cargas el tiempo actual de juego en las variables 0x8000 y 0x8001. Después, haces dos copyvar para cargar el tiempo que llevabas de partida en el primer momento y lo copias en las variables 0x8004 y 0x8005. Por último, ejecutas la segunda rutina y se restará el tiempo.
El resultado se guardará en las variables 0x8004 (segundos y minutos) y 0x8005 (horas). Por tanto, lo último que te queda es, mediante script, comprobar los valores de dichas variables para ver si has tardado mucho, si has tardado poco o lo que quieras comprobar.
La estructura del tiempo en la ram es la siguiente: [XX][YY][ZZZZ]. Donde XX son los segundos, YY los minutos y ZZZZ las horas. Si no eres muy avanzado y te lías con eso, lo mejor es que hagas pruebas mirando directamente los resultados en la ram (en 0x020370B8).
RE-CALCULAR STATS
A veces, manipulando los datos de un pokémon del equipo, me he encontrado con errores. Esto es debido a que se produce un desajuste entre los datos actuales del pokémon en la ram y la configuración que tiene el pokémon en el juego. Dicho error se manifiesta de varias formas: reiniciándose el juego, quedándose pillado al subir de nivel al pokémon en cuestión, etc.
Esta rutina funciona simplemente para re-calcular los datos del pokémon y que no dé errores. Por tanto, si manipulas los datos de un pokémon y ves que te da errores, simplemente usa esta rutina en el script en el que manipulas dicho pokémon.
La rutina es la siguiente:
La rutina es muy sencilla de usar, simplemente haz un setvar para especificar en la variable 0x8004 la posición del pokémon en el equipo. Recuerda que el primer pokémon ocupa la posición 0x0. Por tanto, si quisieras re-calcular los datos del sexto pokémon del equipo, tendrías que poner "setvar 0x8004 0x5". Luego haz un callasm y se re-calcularán los datos del pokémon.
Código:
.align 2
.thumb
push {r0-r3,lr}
ldr r0, =0x02024284
ldr r1, =0x020370C0
ldrb r1, [r1]
mov r2, #0x64
mul r1, r2
add r0, r0, r1
ldr r3, =(0x803E47C +1)
bl linker
pop {r0-r3,pc}
linker:
bx r3
Código:
0F B5 05 48 05 49 09 78 64 22 51 43 40 18 04 4B 00 F0 01 F8 0F BD 18 47 84 42 02 02 C0 70 03 02 7D E4 03 08
CAMBIO DE SEXO
Esta rutina te permite cambiar del personaje masculino al personaje femenino. Si la elección de un personaje es forzada, luego tienes la opción de tener un segundo personaje con su propio mini, sprite y backsprite. Eso o lo que se te ocurra.
La rutina es la siguiente:
El funcionamiento es muy sencillo. Simplemente tienes que guardar en la variable 0x8000 el valor 0x0 (para convertirte en chico) o 0x1 (para convertirte en chica). Luego, simplemente, ejecuta la rutina.
Código:
.align 2
.thumb
push {r0-r1,lr}
ldr r0, .data
ldr r1, [r0]
mov r0, #0x0
ldr r0, .var_8000
ldrb r0, [r0]
strb r0, [r1,#0x8]
pop {r0-r1,pc}
.data: .word 0x0300500C
.var_8000: .word 0x020370B8
Código:
03 B5 03 48 01 68 00 20 02 48 00 78 08 72 03 BD 0C 50 00 03 B8 70 03 02
GIVEPOKEMON CON NOMBRE PREDEFINIDO
En realidad vale para un givepokemon o para cualquier forma de obtención del pokémon. O para cambiar el nombre de cualquier pokémon del equipo cuando te venga en gana. Pero lo más útil o, al menos, lógico, es utilizarlo junto con un givepokémon. Esta rutina, por tanto, te permite obtener un pokémon que ya venga con un nombre concreto que tú especifiques en el script.
La rutina es esta:
Esta rutina, por supuesto, sólo funciona con un pokémon que esté en el equipo. Si hacemos un givepokemon y se va al PC, no podremos darle un nombre predeterminado. Por tanto, antes de dar el pokémon, simplemente comprueba que hay espacio en el equipo con el comando countpokemon.
Para utilizar la rutina, pon lo siguiente en tu script:
IMPORTANTE: Recuerda que los pokémon tienen una limitación de 10 caracteres en sus nombres. Por lo tanto, recuerda no pasarte. Si te pasas, no te dará error, pero sólo se leerán los 10 primeros caracteres y, por tanto, el nombre estará incompleto.
Código:
.align 2
.thumb
push {r0-r4,lr}
ldr r0, .load_pointer
ldr r0, [r0]
ldr r2, .var_8000
ldrb r2, [r2]
mov r3, #0x64
mul r2, r3
add r2, #0x8
ldr r3, .pkmn_party
add r3, r2
ldr r1, .var_8000
ldrb r1, [r1]
add r1, #0x1
mov r4, #0x0
bucle1:
ldrb r2, [r0,r4]
cmp r2, #0xFF
beq completar
cmp r4, #0xA
beq fin
strb r2, [r3,r4]
add r4, #0x1
b bucle1
completar:
cmp r4, #0xA
beq fin
ldr r2, =0xFF
strb r2, [r3,r4]
mov r2, #0x0
add r4, #0x1
b completar
fin:
pop {r0-r4,pc}
.load_pointer: .word 0x03000f14
.var_8000: .word 0x020370B8
.pkmn_party: .word 0x02024284
Código:
1F B5 0E 48 00 68 0E 4A 12 78 64 23 5A 43 08 32 0C 4B 9B 18 0A 49 09 78 01 31 00 24 02 5D FF 2A 04 D0 0A 2C 09 D0 1A 55 01 34 F7 E7 0A 2C 04 D0 FF 22 1A 55 00 22 01 34 F8 E7 1F BD 14 0F 00 03 B8 70 03 02 84 42 02 02
Para utilizar la rutina, pon lo siguiente en tu script:
Este script, básicamente, después del givepokemon, determina cuál es el último pokémon en el equipo (es decir, el que acabas de recibir) y le cambia el nombre. Se puede hacer con cualquier pokémon del equipo en cualquier momento, simplemente haz un setvar para darle el valor a la variable 0x8000 que indique el slot del pokémon que quieres renombrar (recuerda que el primer pokémon ocupa la posición 0x0, no 0x1). Pero si lo quieres utilizar en un givepokemon, simplemente usa ese fragmento en tu script.(...)
loadpointer 0x0 @nombre 'Compila el nombre
countpokemon 'Comprueba la cantidad de pokémon en el equipo
copyvar 0x8000 LASTRESULT 'Guarda la cantidad en 0x8000
compare 0x8000 0x6 'Comprueba si tienes 6 (completo)
if 0x1 goto @noespacio 'Si los tienes va a @noespacio
givepokemon 0x(pokemon) 0x(nivel) 0x(objeto) 0x0 0x0 0x0
callasm 0x(offset de la rutina + 1) 'Ejecuta la rutina
(...)
#org @noespacio
(lo que pasa si no tienes espacio en el equipo)
(...)
#org @nombre
= PIPIOLO
IMPORTANTE: Recuerda que los pokémon tienen una limitación de 10 caracteres en sus nombres. Por lo tanto, recuerda no pasarte. Si te pasas, no te dará error, pero sólo se leerán los 10 primeros caracteres y, por tanto, el nombre estará incompleto.
POKéDEX HACK
Se trata de una rutina para comprobar o activar los avistamientos o capturas de los pokémon en la pokédex. Es decir, puedes comprobar si has visto o tienes capturado un determinado pokémon. A su vez, puedes poner a un pokémon como visto o como capturado (sin haberlo hecho realmente).
Esta es la rutina:
La rutina funciona poniendo el pokémon en la variable 0x8000 y la acción a realizar en la 0x8001. A continuación, se ejecuta la rutina. Las acciones son las siguientes:
Un ejemplo, si quisieramos comprobar si hemos capturado un pikachu (que es el número 25 en decimal y 0x19 en hex), lo haríamos de la siguiente forma:
Código:
.align 2
.thumb
push {r0-r2,lr}
ldr r2, .decrypt
ldr r0, .var_8000
ldrb r1, [r0,#0x2]
ldrh r0, [r0]
cmp r1, #0x4
bge end
cmp r1, #0x1
bls check
cmp r1, #0x2
beq seen
bl call_decrypt
mov r2, #0x0
ldr r2, .decrypt
ldr r0, .var_8000
ldrh r0, [r0]
mov r1, #0x2
b seen
check:
bl call_decrypt
ldr r1, .var_8000
strb r0, [r1]
b end
seen:
bl call_decrypt
end:
pop {r0-r2,pc}
call_decrypt:
bx r2
.decrypt: .word 0x08104AB1
.var_8000: .word 0x020370B8
Código:
07 B5 0D 4A 0D 48 81 78 00 88 04 29 12 DA 01 29 09 D9 02 29 0C D0 00 F0 0E F8 00 22 06 4A 07 48 00 88 02 21 04 E0 00 F0 06 F8 04 49 08 70 01 E0 00 F0 01 F8 07 BD 10 47 B1 4A 10 08 B8 70 03 02
En el caso del 0x0 y el 0x1, que sirven para comprobar, lo que hacen es devolver a la variable 0x8000 el valor 0x0 si no ha sido visto/capturado, y el valor 0x1 si efectivamente ha sido visto/capturado.0x0 - Comprueba si el pokémon ha sido visto.
0x1 - Comprueba si el pokémon ha sido capturado.
0x2 - Establece el pokémon como visto.
0x3 - Establece el pokémon como capturado.
Un ejemplo, si quisieramos comprobar si hemos capturado un pikachu (que es el número 25 en decimal y 0x19 en hex), lo haríamos de la siguiente forma:
setvar 0x8000 0x19
setvar 0x8001 0x1
callasm 0x(offset + 1)
compare 0x8000 0x1
if 0x1 goto @(pointer cuando tienes capturado a pikachu)
SHOWPOKEPIC PRO
Como seguramente sabrás, en Ruby hay un comando llamado hidebox que se suele utilizar para ocultar las cajas de los showpokepic. Como seguramente también sabrás, dicho comando no funciona en Fire Red. Lo que hacen estas rutinas es modificar el funcionamiento del showpokepic para introducir una comprobación que determina si mostrar el pokepic CON o SIN caja.
Esta no es una rutina como las demás, ya que las otras introducen funciones que se ejecutan al utilizar un callasm. Esta, en cambio, no requiere de ningún callasm, ya que modifica directamente el comando. Lo primero que vamos a hacer es introducir esta rutina en un espacio vacío del rom (¡Apunta el offset!):
Esta rutina se encarga de dibujar la caja. Es decir, si elegimos que el showpokepic se mostrará de manera normal (con la caja), pasará por este código.
Ahora tenemos que insertar una segunda rutina en otro espacio vacío del rom (¡Apunta este offset también!):
Esta segunda rutina comprueba el valor de la variable 0x8000. Si el valor es 0x1, entonces no dibuja la caja. En caso de que el valor sea cualquier otro distinto de 0x1, entonces sí la dibuja.
Pero esta rutina debe apuntar a la primera rutina que insertamos. Si la primera rutina la insertamos, por ejemplo, en el offset 0x904500, le añadiremos 1. Por lo tanto, en nuestro ejemplo no quedaría 0x904501. Ahora tenemos que permutarlo:
90 45 01 => 01 45 90
Y eso lo reemplazaremos en la XX XX XX de nuestra segunda rutina.
Ahora ya tenemos nuestras dos rutinas insertadas y las hemos conectado. Pero ahora mismo son independientes del comando showpokepic, no las hemos conectado a él. Este es el último paso. Y para ello vamos a introducir una última rutina:
Pero esta rutina NO la vamos a introducir en un espacio libre del rom, sino que la vamos a introducir en el offset 0xF7750.
Antes, por supuesto, vamos a reemplazar las XX XX XX con el offset + 1 de la segunda rutina. Recuerda permutarlo como hicimos en el paso anterior. Pero presta atención, es el offset de la segunda rutina, el que hicimos en el paso anterior fue el de la primera. No te equivoques y pongas el mismo offset.
Por tanto, la tercera rutina debe apuntar a la segunda. Del mismo modo, la segunda debe apuntar a la primera. Si ya has seguido todos los pasos, felicidades, puedes elegir si tus showpokepic mostraran o no la caja. Para ello, añade un setvar antes de cada showpokepic:
Código:
.align 2
.thumb
push {lr}
lsl r0, r0, #0x18
lsr r0, r0, #0x18
lsl r1, r1, #0x18
lsr r1, r1, #0x18
mov r2, #0x85
lsl r2, r2, #0x2
mov r3, #0xE
ldr r6, =0x810f2e9
bl call
pop {r0}
bx r0
call:
bx r6
Código:
00 B5 00 06 00 0E 09 06 09 0E 85 22 92 00 0E 23 02 4E 00 F0 02 F8 01 BC 00 47 30 47 E9 F2 10 08
Ahora tenemos que insertar una segunda rutina en otro espacio vacío del rom (¡Apunta este offset también!):
Código:
.align 2
.thumb
ldr r6, =0x020370B8
ldrb r6, [r6]
cmp r6, #0x1
beq end
ldr r6, =0x(rutina1 + 1)
bx r6
end:
push {lr}
pop {r0}
bx r0
Código:
04 4E 36 78 01 2E 01 D0 03 4E 30 47 00 B5 01 BC 00 47 00 00 B8 70 03 02 XX XX XX 08
Pero esta rutina debe apuntar a la primera rutina que insertamos. Si la primera rutina la insertamos, por ejemplo, en el offset 0x904500, le añadiremos 1. Por lo tanto, en nuestro ejemplo no quedaría 0x904501. Ahora tenemos que permutarlo:
90 45 01 => 01 45 90
Y eso lo reemplazaremos en la XX XX XX de nuestra segunda rutina.
Ahora ya tenemos nuestras dos rutinas insertadas y las hemos conectado. Pero ahora mismo son independientes del comando showpokepic, no las hemos conectado a él. Este es el último paso. Y para ello vamos a introducir una última rutina:
Código:
.align 2
.thumb
ldr r6, =0x(rutina2 + 1)
bx r6
Código:
00 4E 30 47 XX XX XX 08
Antes, por supuesto, vamos a reemplazar las XX XX XX con el offset + 1 de la segunda rutina. Recuerda permutarlo como hicimos en el paso anterior. Pero presta atención, es el offset de la segunda rutina, el que hicimos en el paso anterior fue el de la primera. No te equivoques y pongas el mismo offset.
Por tanto, la tercera rutina debe apuntar a la segunda. Del mismo modo, la segunda debe apuntar a la primera. Si ya has seguido todos los pasos, felicidades, puedes elegir si tus showpokepic mostraran o no la caja. Para ello, añade un setvar antes de cada showpokepic:
setvar 0x8000 0x(0 para mostrar la caja, 1 para no mostrarla)
showpokepic (parámetros normales)
PODER OCULTO
El ataque Poder Oculto depende en tipo y potencia de las estadísticas del pokémon. Si quieres averiguar el tipo y la potencia del ataque en un determinado pokémon del equipo, esta es tu rutina.
La rutina es la siguiente. Es un poco larga, pero determinar el tipo y la potencia son dos datos que se calculan a partir de los mismos valores pero que, aritméticamente, siguen dos procedimientos bastante distintos.
Simplemente tienes que especificar en la variable 0x8000 el slot del pokémon (recuerdo que el primer pokémon del equipo está en el slot 0x0, no en el 0x1). A continuación, ejecuta la rutina con un callasm. Se devolverá el número del tipo al que corresponde en la variable 0x8004 y la potencia en la variable 0x8005.
Para simplificar más el proceso, he escrito un script que os permitirá guardar en un buffer el tipo devuelto por la variable. El script es el siguiente:
Este script se encargará de guardar el tipo del pokémon en [buffer1]. De esta forma, podremos mostrarlo en nuestros mensajes. Para ello, simplemente lo compilamos y, cuando queramos utilizarlo, hacemos un "call 0x(offset del script)".
Algo interesante sería crear un objeto que te permitiera comprobarlo en cualquier momento. Pero hagais eso o una persona que te lo diga o lo que queráis hacer, yo he escrito un script para poder hacerlo de una forma adecuada. Sería este:
Código:
.align 2
.thumb
push {r0-r6,lr}
ldr r0, .var_8000
ldrb r0, [r0]
ldr r1, .pkmn_party
mov r2, #0x64
mul r2, r0
add r1, r1, r2
mov r2, #0x56
add r1, r1, r2
mov r0, #0x0
mov r3, #0x2
mov r4, #0x0
mov r5, #0x2
loop1:
cmp r4, #0x6
beq cont
add r1, r1, r3
ldrh r2, [r1]
loop2:
cmp r2, #0x1
beq impar
cmp r2, #0x0
beq par
sub r2, r2, r5
b loop2
par:
add r4, #0x1
b loop1
impar:
cmp r4, #0x1
beq corr2
cmp r4, #0x2
beq corr3
cmp r4, #0x3
beq corr4
cmp r4, #0x4
beq corr5
cmp r4, #0x5
beq corr6
mov r6, #0x1
b add
corr2:
mov r6, #0x2
b add
corr3:
mov r6, #0x4
b add
corr4:
mov r6, #0x8
b add
corr5:
mov r6, #0x10
b add
corr6:
mov r6, #0x20
add:
add r0, r0, r6
add r4, #0x1
b loop1
cont:
mov r1, #0x3F
mov r2, #0xF
mul r0, r2
swi 0x6
ldr r1, .var_8000
strh r0, [r1,#0x8]
mov r0, #0x0
ldr r0, .var_8000
ldrb r0, [r0]
ldr r4, .pkmn_party
mov r2, #0x64
mul r2, r0
add r4, r4, r2
mov r2, #0x58
add r4, r4, r2
mov r5, #0x0
ldrh r0, [r4]
mov r1, #0x4
swi 0x6
cmp r3, #0x1
bls jump1
mov r0, #0x1
add r5, r5, r0
jump1:
ldrh r0, [r4,#0x2]
mov r1, #0x4
swi 0x6
cmp r1, #0x1
bls jump2
mov r0, #0x2
add r5, r5, r0
jump2:
ldrh r0, [r4,#0x4]
mov r1, #0x4
swi 0x6
cmp r1, #0x1
bls jump3
mov r0, #0x4
add r5, r5, r0
jump3:
ldrh r0, [r4,#0x6]
mov r1, #0x4
swi 0x6
cmp r1, #0x1
bls jump4
mov r0, #0x8
add r5, r5, r0
jump4:
ldrh r0, [r4,#0x8]
mov r1, #0x4
swi 0x6
cmp r1, #0x1
bls jump5
mov r0, #0x10
add r5, r5, r0
jump5:
ldrh r0, [r4,#0xA]
mov r1, #0x4
swi 0x6
cmp r1, #0x1
bls jump6
mov r0, #0x20
add r5, r5, r0
jump6:
mov r6, #0x28
mov r1, #0x3F
mov r0, #0x0
add r0, r0, r5
mul r0,r6
swi 0x6
mov r6, #0x1E
add r0, r0, r6
ldr r1, .var_8000
strh r0, [r1,#0xA]
pop {r0-r6,pc}
.var_8000: .word 0x020370B8
.pkmn_party: .word 0x02024284
Código:
7F B5 3A 48 00 78 3A 49 64 22 42 43 89 18 56 22 89 18 00 20 02 23 00 24 02 25 06 2C 21 D0 C9 18 0A 88 01 2A 05 D0 00 2A 01 D0 52 1B F9 E7 01 34 F3 E7 01 2C 09 D0 02 2C 09 D0 03 2C 09 D0 04 2C 09 D0 05 2C 09 D0 01 26 08 E0 02 26 06 E0 04 26 04 E0 08 26 02 E0 10 26 00 E0 20 26 80 19 01 34 DB E7 3F 21 0F 22 50 43 06 DF 20 49 08 81 00 20 1E 48 00 78 1E 4C 64 22 42 43 A4 18 58 22 A4 18 00 25 20 88 04 21 06 DF 01 2B 01 D9 01 20 2D 18 60 88 04 21 06 DF 01 29 01 D9 02 20 2D 18 A0 88 04 21 06 DF 01 29 01 D9 04 20 2D 18 E0 88 04 21 06 DF 01 29 01 D9 08 20 2D 18 20 89 04 21 06 DF 01 29 01 D9 10 20 2D 18 60 89 04 21 06 DF 01 29 01 D9 20 20 2D 18 28 26 3F 21 00 20 40 19 70 43 06 DF 1E 26 80 19 01 49 48 81 7F BD B8 70 03 02 84 42 02 02
Para simplificar más el proceso, he escrito un script que os permitirá guardar en un buffer el tipo devuelto por la variable. El script es el siguiente:
Código:
#dynamic 0x800000
#org @start
compare 0x8004 0
if 0x1 goto @t0
compare 0x8004 1
if 0x1 goto @t1
compare 0x8004 2
if 0x1 goto @t2
compare 0x8004 3
if 0x1 goto @t3
compare 0x8004 4
if 0x1 goto @t4
compare 0x8004 5
if 0x1 goto @t5
compare 0x8004 6
if 0x1 goto @t6
compare 0x8004 7
if 0x1 goto @t7
compare 0x8004 8
if 0x1 goto @t8
compare 0x8004 9
if 0x1 goto @t9
compare 0x8004 10
if 0x1 goto @t10
compare 0x8004 11
if 0x1 goto @t11
compare 0x8004 12
if 0x1 goto @t12
compare 0x8004 13
if 0x1 goto @t13
compare 0x8004 14
if 0x1 goto @t14
compare 0x8004 15
if 0x1 goto @t15
return
#org @t0
bufferstring 0x0 @lucha
return
#org @t1
bufferstring 0x0 @volador
return
#org @t2
bufferstring 0x0 @veneno
return
#org @t3
bufferstring 0x0 @tierra
return
#org @t4
bufferstring 0x0 @roca
return
#org @t5
bufferstring 0x0 [MENTION=34347]Bicho[/MENTION]
return
#org @t6
bufferstring 0x0 @fantasma
return
#org @t7
bufferstring 0x0 [MENTION=39554]acero[/MENTION]
return
#org @t8
bufferstring 0x0 @fuego
return
#org @t9
bufferstring 0x0 @agua
return
#org @t10
bufferstring 0x0 @planta
return
#org @t11
bufferstring 0x0 [MENTION=30724]Elec[/MENTION]trico
return
#org @t12
bufferstring 0x0 @psiquico
return
#org @t13
bufferstring 0x0 @hielo
return
#org @t14
bufferstring 0x0 @dragon
return
#org @t15
bufferstring 0x0 [MENTION=25868]sin[/MENTION]iestro
return
#org @lucha
= LUCHA
#org @volador
= VOLADOR
#org @veneno
= VENENO
#org @tierra
= TIERRA
#org @roca
= ROCA
#org [MENTION=34347]Bicho[/MENTION]
= BICHO
#org @fantasma
= FANTASMA
#org [MENTION=39554]acero[/MENTION]
= ACERO
#org @fuego
= FUEGO
#org @agua
= AGUA
#org @planta
= PLANTA
#org [MENTION=30724]Elec[/MENTION]trico
= ELECTRICO
#org @psiquico
= PSÍQUICO
#org @hielo
= HIELO
#org @dragon
= DRAGÓN
#org [MENTION=25868]sin[/MENTION]iestro
= SINIESTRO
Algo interesante sería crear un objeto que te permitiera comprobarlo en cualquier momento. Pero hagais eso o una persona que te lo diga o lo que queráis hacer, yo he escrito un script para poder hacerlo de una forma adecuada. Sería este:
El msgbox simplemente poned el [buffer1] y el [buffer2] donde queráis que muestre el tipo y la potencia, respectivamente. Por ejemplo:(...)
fadescreen 0x1
special 0xBC 'abre el menú para elegir al poke que quieras
waitstate
compare 0x8004 0x6
if 0x4 goto @salir 'esto es lo que pasa cuando sales sin elegir a un poke
copyvar 0x8000 0x8004 'pasa el slot del poke a la variable 0x8000, que es la que usa la rutina
callasm 0x(offset de la rutina + 1)
pause 0x5 'esto es opcional, es para que no quede tan "drástico"
buffernumber 0x1 0x8005 'guarda la potencia del ataque en [buffer2]
call 0x(script para guardar el tipo) 'debe ser siempre call para que funcione el return, nunca goto
msgbox @texto MSG_NORMAL 'este sería el msgbox que muestra los datos
(...)
#org @texto
= TIPO: [buffer1].\nPOTENCIA: [buffer2].
POKéMON EDITOR
Esta rutina permite editar los datos encriptados de cualquier pokémon del equipo. Para ello, traslada los datos desencriptados del pokémon a un espacio libre de la RAM donde se pueden editar.
En realidad, el sistema utiliza dos rutinas, una para desencriptar y otra para encriptar. Aviso de que son largas.
Esta es la rutina para desencriptar los datos:
Y esta es la rutina para volverlos a encriptar:
El funcionamiento, al contrario que la rutina xD, es simple. Solo tienes que guardar el slot del poke en la variable 0x8000 y llamar a la rutina que desencripta los datos. Después, edita los datos que quieras y, por ultimo, llama a la rutina que los encripta de nuevo. Pero ten cuidado, si cambias el valor de la variable, se encriptarán los datos en otro slot, así que, cuando tengas que editar datos, hazlo y encripta de nuevo sin hacer otras cosas.
La rutina desencripta los datos, por tanto, no son editables los datos no encriptados, ya que estos se pueden hacer directamente sin necesidad de una rutina.
El pokémon se desencripta en la dirección 0x203F500 y se pueden editar los datos con simples WBTOs. Estos son los datos (en decimal):
Esta es la rutina para desencriptar los datos:
Código:
.align 2
.thumb
push {r0-r7,lr}
ldr r1, .var_8000
ldrh r1, [r1]
mov r0, #0x64
mul r1, r0
ldr r0, .party
add r0, r0, r1
ldr r1, [r0]
ldr r2, [r0,#0x4]
eor r1, r2
mov r6, r1
ldr r2, .memory
mov r7, #0x0
ldr r7, [r0,#0x50]
mov r5, r0
ldr r0, [r0]
seguir2:
ldr r1, =0x18000000
cmp r0, r1
blo seguir3
sub r0, r0, r1
b seguir2
seguir3:
ldr r1, =0x1800000
cmp r0, r1
blo seguir4
sub r0, r0, r1
b seguir3
seguir4:
ldr r1, =0x180000
cmp r0, r1
blo seguir5
sub r0, r0, r1
b seguir4
seguir5:
ldr r1, =0x18000
cmp r0, r1
blo seguir6
sub r0, r0, r1
b seguir5
seguir6:
ldr r1, =0x1800
cmp r0, r1
blo seguir7
sub r0, r0, r1
b seguir6
seguir7:
ldr r1, =0x180
cmp r0, r1
blo seguir8
sub r0, r0, r1
b seguir7
seguir8:
ldr r1, =0x18
cmp r0, r1
blo continuar
sub r0, r0, r1
b seguir8
continuar:
str r0, [r2,#0x50]
mov r0, r5
mov r5, #0x0
ldr r3, [r0]
str r3, [r2]
ldr r3, [r0,#0x4]
str r3, [r2,#0x4]
ldr r3, [r0,#0x8]
str r3, [r2,#0x8]
ldr r3, [r0,#0xC]
str r3, [r2,#0xC]
ldr r3, [r0,#0x10]
str r3, [r2,#0x10]
ldr r3, [r0,#0x14]
str r3, [r2,#0x14]
ldr r3, [r0,#0x18]
str r3, [r2,#0x18]
ldr r3, [r0,#0x1C]
str r3, [r2,#0x1C]
mov r5, #0x50
ldr r5, .memory
ldr r4, =0x50
ldrb r5, [r5,r4]
mov r1, r6
cmp r5, #0x6
blo g_pri
cmp r5, #0xC
blo a_pri
cmp r5, #0x12
blo e_pri
cmp r5, #0x18
blo m_pri
g_pri:
mov r3, #0x0
ldr r3, [r0,#0x20]
eor r3, r1
str r3, [r2,#0x20]
ldr r3, [r0,#0x24]
eor r3, r1
str r3, [r2,#0x24]
ldr r3, [r0,#0x28]
eor r3, r1
str r3, [r2,#0x28]
b segunda
a_pri:
mov r3, #0x0
ldr r3, [r0,#0x20]
eor r3, r1
str r3, [r2,#0x2C]
ldr r3, [r0,#0x24]
eor r3, r1
str r3, [r2,#0x30]
ldr r3, [r0,#0x28]
eor r3, r1
str r3, [r2,#0x34]
b segunda
e_pri:
mov r3, #0x0
ldr r3, [r0,#0x20]
eor r3, r1
str r3, [r2,#0x38]
ldr r3, [r0,#0x24]
eor r3, r1
str r3, [r2,#0x3C]
ldr r3, [r0,#0x28]
eor r3, r1
str r3, [r2,#0x40]
b segunda
m_pri:
mov r3, #0x0
ldr r3, [r0,#0x20]
eor r3, r1
str r3, [r2,#0x44]
ldr r3, [r0,#0x24]
eor r3, r1
str r3, [r2,#0x48]
ldr r3, [r0,#0x28]
eor r3, r1
str r3, [r2,#0x4C]
segunda:
mov r3, #0x0
cmp r5, #0x6
beq g_seg
cmp r5, #0x7
beq g_seg
cmp r5, #0xC
beq g_seg
cmp r5, #0xD
beq g_seg
cmp r5, #0x12
beq g_seg
cmp r5, #0x13
beq g_seg
cmp r5, #0x0
beq a_seg
cmp r5, #0x1
beq a_seg
cmp r5, #0xE
beq a_seg
cmp r5, #0xF
beq a_seg
cmp r5, #0x14
beq a_seg
cmp r5, #0x15
beq a_seg
cmp r5, #0x2
beq e_seg
cmp r5, #0x3
beq e_seg
cmp r5, #0x8
beq e_seg
cmp r5, #0x9
beq e_seg
cmp r5, #0x16
beq e_seg
cmp r5, #0x17
beq e_seg
cmp r5, #0x4
beq m_seg
cmp r5, #0x5
beq m_seg
cmp r5, #0xA
beq m_seg
cmp r5, #0xB
beq m_seg
cmp r5, #0x10
beq m_seg
cmp r5, #0x11
beq m_seg
g_seg:
mov r3, #0x0
ldr r3, [r0,#0x2C]
eor r3, r1
str r3, [r2,#0x20]
ldr r3, [r0,#0x30]
eor r3, r1
str r3, [r2,#0x24]
ldr r3, [r0,#0x34]
eor r3, r1
str r3, [r2,#0x28]
b tercera
a_seg:
mov r3, #0x0
ldr r3, [r0,#0x2C]
eor r3, r1
str r3, [r2,#0x2C]
ldr r3, [r0,#0x30]
eor r3, r1
str r3, [r2,#0x30]
ldr r3, [r0,#0x34]
eor r3, r1
str r3, [r2,#0x34]
b tercera
e_seg:
mov r3, #0x0
ldr r3, [r0,#0x2C]
eor r3, r1
str r3, [r2,#0x38]
ldr r3, [r0,#0x30]
eor r3, r1
str r3, [r2,#0x3C]
ldr r3, [r0,#0x34]
eor r3, r1
str r3, [r2,#0x40]
b tercera
m_seg:
mov r3, #0x0
ldr r3, [r0,#0x2C]
eor r3, r1
str r3, [r2,#0x44]
ldr r3, [r0,#0x30]
eor r3, r1
str r3, [r2,#0x48]
ldr r3, [r0,#0x34]
eor r3, r1
str r3, [r2,#0x4C]
tercera:
mov r3, #0x0
cmp r5, #0x8
beq g_ter
cmp r5, #0xA
beq g_ter
cmp r5, #0xE
beq g_ter
cmp r5, #0x10
beq g_ter
cmp r5, #0x14
beq g_ter
cmp r5, #0x16
beq g_ter
cmp r5, #0x2
beq a_ter
cmp r5, #0x4
beq a_ter
cmp r5, #0xC
beq a_ter
cmp r5, #0x11
beq a_ter
cmp r5, #0x12
beq a_ter
cmp r5, #0x17
beq a_ter
cmp r5, #0x0
beq e_ter
cmp r5, #0x5
beq e_ter
cmp r5, #0x6
beq e_ter
cmp r5, #0xB
beq e_ter
cmp r5, #0x13
beq e_ter
cmp r5, #0x15
beq e_ter
cmp r5, #0x1
beq m_ter
cmp r5, #0x3
beq m_ter
cmp r5, #0x7
beq m_ter
cmp r5, #0x9
beq m_ter
cmp r5, #0xD
beq m_ter
cmp r5, #0xF
beq m_ter
g_ter:
mov r3, #0x0
ldr r3, [r0,#0x38]
eor r3, r1
str r3, [r2,#0x20]
ldr r3, [r0,#0x3C]
eor r3, r1
str r3, [r2,#0x24]
ldr r3, [r0,#0x40]
eor r3, r1
str r3, [r2,#0x28]
b cuarta
a_ter:
mov r3, #0x0
ldr r3, [r0,#0x38]
eor r3, r1
str r3, [r2,#0x2C]
ldr r3, [r0,#0x3C]
eor r3, r1
str r3, [r2,#0x30]
ldr r3, [r0,#0x40]
eor r3, r1
str r3, [r2,#0x34]
b cuarta
e_ter:
mov r3, #0x0
ldr r3, [r0,#0x38]
eor r3, r1
str r3, [r2,#0x38]
ldr r3, [r0,#0x3C]
eor r3, r1
str r3, [r2,#0x3C]
ldr r3, [r0,#0x40]
eor r3, r1
str r3, [r2,#0x40]
b cuarta
m_ter:
mov r3, #0x0
ldr r3, [r0,#0x38]
eor r3, r1
str r3, [r2,#0x44]
ldr r3, [r0,#0x3C]
eor r3, r1
str r3, [r2,#0x48]
ldr r3, [r0,#0x40]
eor r3, r1
str r3, [r2,#0x4C]
cuarta:
mov r3, #0x0
cmp r5, #0x9
beq g_cua
cmp r5, #0xB
beq g_cua
cmp r5, #0xF
beq g_cua
cmp r5, #0x11
beq g_cua
cmp r5, #0x15
beq g_cua
cmp r5, #0x17
beq g_cua
cmp r5, #0x3
beq a_cua
cmp r5, #0x5
beq a_cua
cmp r5, #0xD
beq a_cua
cmp r5, #0x10
beq a_cua
cmp r5, #0x13
beq a_cua
cmp r5, #0x16
beq a_cua
cmp r5, #0x1
beq e_cua
cmp r5, #0x4
beq e_cua
cmp r5, #0x7
beq e_cua
cmp r5, #0xA
beq e_cua
cmp r5, #0x12
beq e_cua
cmp r5, #0x14
beq e_cua
cmp r5, #0x0
beq m_cua
cmp r5, #0x2
beq m_cua
cmp r5, #0x6
beq m_cua
cmp r5, #0x8
beq m_cua
cmp r5, #0xC
beq m_cua
cmp r5, #0xE
beq m_cua
g_cua:
mov r3, #0x0
ldr r3, [r0,#0x44]
eor r3, r1
str r3, [r2,#0x20]
ldr r3, [r0,#0x48]
eor r3, r1
str r3, [r2,#0x24]
ldr r3, [r0,#0x4C]
eor r3, r1
str r3, [r2,#0x28]
b salir
a_cua:
mov r3, #0x0
ldr r3, [r0,#0x44]
eor r3, r1
str r3, [r2,#0x2C]
ldr r3, [r0,#0x48]
eor r3, r1
str r3, [r2,#0x30]
ldr r3, [r0,#0x4C]
eor r3, r1
str r3, [r2,#0x34]
b salir
e_cua:
mov r3, #0x0
ldr r3, [r0,#0x44]
eor r3, r1
str r3, [r2,#0x38]
ldr r3, [r0,#0x48]
eor r3, r1
str r3, [r2,#0x3C]
ldr r3, [r0,#0x4C]
eor r3, r1
str r3, [r2,#0x40]
b salir
m_cua:
mov r3, #0x0
ldr r3, [r0,#0x44]
eor r3, r1
str r3, [r2,#0x44]
ldr r3, [r0,#0x48]
eor r3, r1
str r3, [r2,#0x48]
ldr r3, [r0,#0x4C]
eor r3, r1
str r3, [r2,#0x4C]
salir:
str r7, [r2,#0x50]
pop {r0-r7,pc}
.party: .word 0x02024284
.var_8000: .word 0x020370B8
.memory: .word 0x0203f500
Código:
FF B5 CA 49 09 88 64 20 41 43 C7 48 40 18 01 68 42 68 51 40 0E 1C C6 4A 00 27 07 6D 05 1C 00 68 C4 49 88 42 01 D3 40 1A FA E7 C3 49 88 42 01 D3 40 1A FA E7 C1 49 88 42 01 D3 40 1A FA E7 C0 49 88 42 01 D3 40 1A FA E7 BE 49 88 42 01 D3 40 1A FA E7 BD 49 88 42 01 D3 40 1A FA E7 18 21 88 42 01 D3 40 1A FA E7 10 65 28 1C 00 25 03 68 13 60 43 68 53 60 83 68 93 60 C3 68 D3 60 03 69 13 61 43 69 53 61 83 69 93 61 C3 69 D3 61 50 25 A8 4D 50 24 2D 5D 31 1C 06 2D 05 D3 0C 2D 0E D3 12 2D 17 D3 18 2D 20 D3 00 23 03 6A 4B 40 13 62 43 6A 4B 40 53 62 83 6A 4B 40 93 62 1F E0 00 23 03 6A 4B 40 D3 62 43 6A 4B 40 13 63 83 6A 4B 40 53 63 14 E0 00 23 03 6A 4B 40 93 63 43 6A 4B 40 D3 63 83 6A 4B 40 13 64 09 E0 00 23 03 6A 4B 40 53 64 43 6A 4B 40 93 64 83 6A 4B 40 D3 64 00 23 06 2D 2D D0 07 2D 2B D0 0C 2D 29 D0 0D 2D 27 D0 12 2D 25 D0 13 2D 23 D0 00 2D 2C D0 01 2D 2A D0 0E 2D 28 D0 0F 2D 26 D0 14 2D 24 D0 15 2D 22 D0 02 2D 2B D0 03 2D 29 D0 08 2D 27 D0 09 2D 25 D0 16 2D 23 D0 17 2D 21 D0 04 2D 2A D0 05 2D 28 D0 0A 2D 26 D0 0B 2D 24 D0 10 2D 22 D0 11 2D 20 D0 00 23 C3 6A 4B 40 13 62 03 6B 4B 40 53 62 43 6B 4B 40 93 62 1F E0 00 23 C3 6A 4B 40 D3 62 03 6B 4B 40 13 63 43 6B 4B 40 53 63 14 E0 00 23 C3 6A 4B 40 93 63 03 6B 4B 40 D3 63 43 6B 4B 40 13 64 09 E0 00 23 C3 6A 4B 40 53 64 03 6B 4B 40 93 64 43 6B 4B 40 D3 64 00 23 08 2D 2D D0 0A 2D 2B D0 0E 2D 29 D0 10 2D 27 D0 14 2D 25 D0 16 2D 23 D0 02 2D 2C D0 04 2D 2A D0 0C 2D 28 D0 11 2D 26 D0 12 2D 24 D0 17 2D 22 D0 00 2D 2B D0 05 2D 29 D0 06 2D 27 D0 0B 2D 25 D0 13 2D 23 D0 15 2D 21 D0 01 2D 2A D0 03 2D 28 D0 07 2D 26 D0 09 2D 24 D0 0D 2D 22 D0 0F 2D 20 D0 00 23 83 6B 4B 40 13 62 C3 6B 4B 40 53 62 03 6C 4B 40 93 62 1F E0 00 23 83 6B 4B 40 D3 62 C3 6B 4B 40 13 63 03 6C 4B 40 53 63 14 E0 00 23 83 6B 4B 40 93 63 C3 6B 4B 40 D3 63 03 6C 4B 40 13 64 09 E0 00 23 83 6B 4B 40 53 64 C3 6B 4B 40 93 64 03 6C 4B 40 D3 64 00 23 09 2D 2D D0 0B 2D 2B D0 0F 2D 29 D0 11 2D 27 D0 15 2D 25 D0 17 2D 23 D0 03 2D 2C D0 05 2D 2A D0 0D 2D 28 D0 10 2D 26 D0 13 2D 24 D0 16 2D 22 D0 01 2D 2B D0 04 2D 29 D0 07 2D 27 D0 0A 2D 25 D0 12 2D 23 D0 14 2D 21 D0 00 2D 2A D0 02 2D 28 D0 06 2D 26 D0 08 2D 24 D0 0C 2D 22 D0 0E 2D 20 D0 00 23 43 6C 4B 40 13 62 83 6C 4B 40 53 62 C3 6C 4B 40 93 62 1F E0 00 23 43 6C 4B 40 D3 62 83 6C 4B 40 13 63 C3 6C 4B 40 53 63 14 E0 00 23 43 6C 4B 40 93 63 83 6C 4B 40 D3 63 C3 6C 4B 40 13 64 09 E0 00 23 43 6C 4B 40 53 64 83 6C 4B 40 93 64 C3 6C 4B 40 D3 64 17 65 FF BD 84 42 02 02 B8 70 03 02 00 F5 03 02 00 00 00 18 00 00 80 01 00 00 18 00 00 80 01 00 00 18 00 00 80 01 00 00
Código:
.align 2
.thumb
push {r0-r7,lr}
ldrh r0, .memory
add r0, #0x20
mov r2, #0x0
mov r3, #0x2
mov r4, #0x0
checksum:
cmp r2, #0x30
beq encriptar2
ldrh r1, [r0,r2]
add r4, r4, r1
add r2, r2, r3
b checksum
encriptar2:
ldr r1, .var_8000
ldrh r1, [r1]
mov r0, #0x64
mul r1, r0
ldr r0, .party
add r2, r0, r1
ldr r0, .memory
ldr r7, [r0,#0x50]
strh r4, [r0,#0x1C]
ldr r1, [r0]
ldr r5, [r0,#0x4]
eor r1, r5
mov r6, r1
mov r5, r0
ldr r0, [r0]
seguir2:
ldr r1, =0x18000000
cmp r0, r1
blo seguir3
sub r0, r0, r1
b seguir2
seguir3:
ldr r1, =0x1800000
cmp r0, r1
blo seguir4
sub r0, r0, r1
b seguir3
seguir4:
ldr r1, =0x180000
cmp r0, r1
blo seguir5
sub r0, r0, r1
b seguir4
seguir5:
ldr r1, =0x18000
cmp r0, r1
blo seguir6
sub r0, r0, r1
b seguir5
seguir6:
ldr r1, =0x1800
cmp r0, r1
blo seguir7
sub r0, r0, r1
b seguir6
seguir7:
ldr r1, =0x180
cmp r0, r1
blo seguir8
sub r0, r0, r1
b seguir7
seguir8:
ldr r1, =0x18
cmp r0, r1
blo continuar
sub r0, r0, r1
b seguir8
continuar:
str r0, [r2,#0x50]
mov r0, r5
mov r5, #0x0
ldr r3, [r0]
str r3, [r2]
ldr r3, [r0,#0x4]
str r3, [r2,#0x4]
ldr r3, [r0,#0x8]
str r3, [r2,#0x8]
ldr r3, [r0,#0xC]
str r3, [r2,#0xC]
ldr r3, [r0,#0x10]
str r3, [r2,#0x10]
ldr r3, [r0,#0x14]
str r3, [r2,#0x14]
ldr r3, [r0,#0x18]
str r3, [r2,#0x18]
ldr r3, [r0,#0x1C]
str r3, [r2,#0x1C]
mov r5, #0x50
ldr r4, =0x50
ldrb r5, [r2,r4]
mov r1, r6
cmp r5, #0x6
blo g_pri
cmp r5, #0xC
blo a_pri
cmp r5, #0x12
blo e_pri
cmp r5, #0x18
blo m_pri
g_pri:
mov r3, #0x0
ldr r3, [r0,#0x20]
eor r3, r1
str r3, [r2,#0x20]
ldr r3, [r0,#0x24]
eor r3, r1
str r3, [r2,#0x24]
ldr r3, [r0,#0x28]
eor r3, r1
str r3, [r2,#0x28]
b segunda
a_pri:
mov r3, #0x0
ldr r3, [r0,#0x2C]
eor r3, r1
str r3, [r2,#0x20]
ldr r3, [r0,#0x30]
eor r3, r1
str r3, [r2,#0x24]
ldr r3, [r0,#0x34]
eor r3, r1
str r3, [r2,#0x28]
b segunda
e_pri:
mov r3, #0x0
ldr r3, [r0,#0x38]
eor r3, r1
str r3, [r2,#0x20]
ldr r3, [r0,#0x3C]
eor r3, r1
str r3, [r2,#0x24]
ldr r3, [r0,#0x40]
eor r3, r1
str r3, [r2,#0x28]
b segunda
m_pri:
mov r3, #0x0
ldr r3, [r0,#0x44]
eor r3, r1
str r3, [r2,#0x20]
ldr r3, [r0,#0x48]
eor r3, r1
str r3, [r2,#0x24]
ldr r3, [r0,#0x4C]
eor r3, r1
str r3, [r2,#0x28]
segunda:
mov r3, #0x0
cmp r5, #0x6
beq g_seg
cmp r5, #0x7
beq g_seg
cmp r5, #0xC
beq g_seg
cmp r5, #0xD
beq g_seg
cmp r5, #0x12
beq g_seg
cmp r5, #0x13
beq g_seg
cmp r5, #0x0
beq a_seg
cmp r5, #0x1
beq a_seg
cmp r5, #0xE
beq a_seg
cmp r5, #0xF
beq a_seg
cmp r5, #0x14
beq a_seg
cmp r5, #0x15
beq a_seg
cmp r5, #0x2
beq e_seg
cmp r5, #0x3
beq e_seg
cmp r5, #0x8
beq e_seg
cmp r5, #0x9
beq e_seg
cmp r5, #0x16
beq e_seg
cmp r5, #0x17
beq e_seg
cmp r5, #0x4
beq m_seg
cmp r5, #0x5
beq m_seg
cmp r5, #0xA
beq m_seg
cmp r5, #0xB
beq m_seg
cmp r5, #0x10
beq m_seg
cmp r5, #0x11
beq m_seg
g_seg:
mov r3, #0x0
ldr r3, [r0,#0x20]
eor r3, r1
str r3, [r2,#0x2C]
ldr r3, [r0,#0x24]
eor r3, r1
str r3, [r2,#0x30]
ldr r3, [r0,#0x28]
eor r3, r1
str r3, [r2,#0x34]
b tercera
a_seg:
mov r3, #0x0
ldr r3, [r0,#0x2C]
eor r3, r1
str r3, [r2,#0x2C]
ldr r3, [r0,#0x30]
eor r3, r1
str r3, [r2,#0x30]
ldr r3, [r0,#0x34]
eor r3, r1
str r3, [r2,#0x34]
b tercera
e_seg:
mov r3, #0x0
ldr r3, [r0,#0x38]
eor r3, r1
str r3, [r2,#0x2C]
ldr r3, [r0,#0x3C]
eor r3, r1
str r3, [r2,#0x30]
ldr r3, [r0,#0x40]
eor r3, r1
str r3, [r2,#0x34]
b tercera
m_seg:
mov r3, #0x0
ldr r3, [r0,#0x44]
eor r3, r1
str r3, [r2,#0x2C]
ldr r3, [r0,#0x48]
eor r3, r1
str r3, [r2,#0x30]
ldr r3, [r0,#0x4C]
eor r3, r1
str r3, [r2,#0x34]
tercera:
mov r3, #0x0
cmp r5, #0x8
beq g_ter
cmp r5, #0xA
beq g_ter
cmp r5, #0xE
beq g_ter
cmp r5, #0x10
beq g_ter
cmp r5, #0x14
beq g_ter
cmp r5, #0x16
beq g_ter
cmp r5, #0x2
beq a_ter
cmp r5, #0x4
beq a_ter
cmp r5, #0xC
beq a_ter
cmp r5, #0x11
beq a_ter
cmp r5, #0x12
beq a_ter
cmp r5, #0x17
beq a_ter
cmp r5, #0x0
beq e_ter
cmp r5, #0x5
beq e_ter
cmp r5, #0x6
beq e_ter
cmp r5, #0xB
beq e_ter
cmp r5, #0x13
beq e_ter
cmp r5, #0x15
beq e_ter
cmp r5, #0x1
beq m_ter
cmp r5, #0x3
beq m_ter
cmp r5, #0x7
beq m_ter
cmp r5, #0x9
beq m_ter
cmp r5, #0xD
beq m_ter
cmp r5, #0xF
beq m_ter
g_ter:
mov r3, #0x0
ldr r3, [r0,#0x20]
eor r3, r1
str r3, [r2,#0x38]
ldr r3, [r0,#0x24]
eor r3, r1
str r3, [r2,#0x3C]
ldr r3, [r0,#0x28]
eor r3, r1
str r3, [r2,#0x40]
b cuarta
a_ter:
mov r3, #0x0
ldr r3, [r0,#0x2C]
eor r3, r1
str r3, [r2,#0x38]
ldr r3, [r0,#0x30]
eor r3, r1
str r3, [r2,#0x3C]
ldr r3, [r0,#0x34]
eor r3, r1
str r3, [r2,#0x40]
b cuarta
e_ter:
mov r3, #0x0
ldr r3, [r0,#0x38]
eor r3, r1
str r3, [r2,#0x38]
ldr r3, [r0,#0x3C]
eor r3, r1
str r3, [r2,#0x3C]
ldr r3, [r0,#0x40]
eor r3, r1
str r3, [r2,#0x40]
b cuarta
m_ter:
mov r3, #0x0
ldr r3, [r0,#0x44]
eor r3, r1
str r3, [r2,#0x38]
ldr r3, [r0,#0x48]
eor r3, r1
str r3, [r2,#0x3C]
ldr r3, [r0,#0x4C]
eor r3, r1
str r3, [r2,#0x40]
cuarta:
mov r3, #0x0
cmp r5, #0x9
beq g_cua
cmp r5, #0xB
beq g_cua
cmp r5, #0xF
beq g_cua
cmp r5, #0x11
beq g_cua
cmp r5, #0x15
beq g_cua
cmp r5, #0x17
beq g_cua
cmp r5, #0x3
beq a_cua
cmp r5, #0x5
beq a_cua
cmp r5, #0xD
beq a_cua
cmp r5, #0x10
beq a_cua
cmp r5, #0x13
beq a_cua
cmp r5, #0x16
beq a_cua
cmp r5, #0x1
beq e_cua
cmp r5, #0x4
beq e_cua
cmp r5, #0x7
beq e_cua
cmp r5, #0xA
beq e_cua
cmp r5, #0x12
beq e_cua
cmp r5, #0x14
beq e_cua
cmp r5, #0x0
beq m_cua
cmp r5, #0x2
beq m_cua
cmp r5, #0x6
beq m_cua
cmp r5, #0x8
beq m_cua
cmp r5, #0xC
beq m_cua
cmp r5, #0xE
beq m_cua
g_cua:
mov r3, #0x0
ldr r3, [r0,#0x20]
eor r3, r1
str r3, [r2,#0x44]
ldr r3, [r0,#0x24]
eor r3, r1
str r3, [r2,#0x48]
ldr r3, [r0,#0x28]
eor r3, r1
str r3, [r2,#0x4C]
b salir
a_cua:
mov r3, #0x0
ldr r3, [r0,#0x2C]
eor r3, r1
str r3, [r2,#0x44]
ldr r3, [r0,#0x30]
eor r3, r1
str r3, [r2,#0x48]
ldr r3, [r0,#0x34]
eor r3, r1
str r3, [r2,#0x4C]
b salir
e_cua:
mov r3, #0x0
ldr r3, [r0,#0x38]
eor r3, r1
str r3, [r2,#0x44]
ldr r3, [r0,#0x3C]
eor r3, r1
str r3, [r2,#0x48]
ldr r3, [r0,#0x40]
eor r3, r1
str r3, [r2,#0x4C]
b salir
m_cua:
mov r3, #0x0
ldr r3, [r0,#0x44]
eor r3, r1
str r3, [r2,#0x44]
ldr r3, [r0,#0x48]
eor r3, r1
str r3, [r2,#0x48]
ldr r3, [r0,#0x4C]
eor r3, r1
str r3, [r2,#0x4C]
salir:
str r7, [r2,#0x50]
pop {r0-r7,pc}
.party: .word 0x02024284
.var_8000: .word 0x020370B8
.memory: .word 0x0203f500
Código:
FF B5 D0 48 20 30 00 22 02 23 00 24 30 2A 03 D0 81 5A 64 18 D2 18 F9 E7 C9 49 09 88 64 20 41 43 C6 48 42 18 C7 48 07 6D 84 83 01 68 45 68 69 40 0E 1C 05 1C 00 68 C4 49 88 42 01 D3 40 1A FA E7 C2 49 88 42 01 D3 40 1A FA E7 C1 49 88 42 01 D3 40 1A FA E7 BF 49 88 42 01 D3 40 1A FA E7 BE 49 88 42 01 D3 40 1A FA E7 BC 49 88 42 01 D3 40 1A FA E7 18 21 88 42 01 D3 40 1A FA E7 10 65 28 1C 00 25 03 68 13 60 43 68 53 60 83 68 93 60 C3 68 D3 60 03 69 13 61 43 69 53 61 83 69 93 61 C3 69 D3 61 50 25 50 24 15 5D 31 1C 06 2D 05 D3 0C 2D 0E D3 12 2D 17 D3 18 2D 20 D3 00 23 03 6A 4B 40 13 62 43 6A 4B 40 53 62 83 6A 4B 40 93 62 1F E0 00 23 C3 6A 4B 40 13 62 03 6B 4B 40 53 62 43 6B 4B 40 93 62 14 E0 00 23 83 6B 4B 40 13 62 C3 6B 4B 40 53 62 03 6C 4B 40 93 62 09 E0 00 23 43 6C 4B 40 13 62 83 6C 4B 40 53 62 C3 6C 4B 40 93 62 00 23 06 2D 2D D0 07 2D 2B D0 0C 2D 29 D0 0D 2D 27 D0 12 2D 25 D0 13 2D 23 D0 00 2D 2C D0 01 2D 2A D0 0E 2D 28 D0 0F 2D 26 D0 14 2D 24 D0 15 2D 22 D0 02 2D 2B D0 03 2D 29 D0 08 2D 27 D0 09 2D 25 D0 16 2D 23 D0 17 2D 21 D0 04 2D 2A D0 05 2D 28 D0 0A 2D 26 D0 0B 2D 24 D0 10 2D 22 D0 11 2D 20 D0 00 23 03 6A 4B 40 D3 62 43 6A 4B 40 13 63 83 6A 4B 40 53 63 1F E0 00 23 C3 6A 4B 40 D3 62 03 6B 4B 40 13 63 43 6B 4B 40 53 63 14 E0 00 23 83 6B 4B 40 D3 62 C3 6B 4B 40 13 63 03 6C 4B 40 53 63 09 E0 00 23 43 6C 4B 40 D3 62 83 6C 4B 40 13 63 C3 6C 4B 40 53 63 00 23 08 2D 2D D0 0A 2D 2B D0 0E 2D 29 D0 10 2D 27 D0 14 2D 25 D0 16 2D 23 D0 02 2D 2C D0 04 2D 2A D0 0C 2D 28 D0 11 2D 26 D0 12 2D 24 D0 17 2D 22 D0 00 2D 2B D0 05 2D 29 D0 06 2D 27 D0 0B 2D 25 D0 13 2D 23 D0 15 2D 21 D0 01 2D 2A D0 03 2D 28 D0 07 2D 26 D0 09 2D 24 D0 0D 2D 22 D0 0F 2D 20 D0 00 23 03 6A 4B 40 93 63 43 6A 4B 40 D3 63 83 6A 4B 40 13 64 1F E0 00 23 C3 6A 4B 40 93 63 03 6B 4B 40 D3 63 43 6B 4B 40 13 64 14 E0 00 23 83 6B 4B 40 93 63 C3 6B 4B 40 D3 63 03 6C 4B 40 13 64 09 E0 00 23 43 6C 4B 40 93 63 83 6C 4B 40 D3 63 C3 6C 4B 40 13 64 00 23 09 2D 2D D0 0B 2D 2B D0 0F 2D 29 D0 11 2D 27 D0 15 2D 25 D0 17 2D 23 D0 03 2D 2C D0 05 2D 2A D0 0D 2D 28 D0 10 2D 26 D0 13 2D 24 D0 16 2D 22 D0 01 2D 2B D0 04 2D 29 D0 07 2D 27 D0 0A 2D 25 D0 12 2D 23 D0 14 2D 21 D0 00 2D 2A D0 02 2D 28 D0 06 2D 26 D0 08 2D 24 D0 0C 2D 22 D0 0E 2D 20 D0 00 23 03 6A 4B 40 53 64 43 6A 4B 40 93 64 83 6A 4B 40 D3 64 1F E0 00 23 C3 6A 4B 40 53 64 03 6B 4B 40 93 64 43 6B 4B 40 D3 64 14 E0 00 23 83 6B 4B 40 53 64 C3 6B 4B 40 93 64 03 6C 4B 40 D3 64 09 E0 00 23 43 6C 4B 40 53 64 83 6C 4B 40 93 64 C3 6C 4B 40 D3 64 17 65 FF BD 84 42 02 02 B8 70 03 02 00 F5 03 02 00 00 00 18 00 00 80 01 00 00 18 00 00 80 01 00 00 18 00 00 80 01 00 00
La rutina desencripta los datos, por tanto, no son editables los datos no encriptados, ya que estos se pueden hacer directamente sin necesidad de una rutina.
El pokémon se desencripta en la dirección 0x203F500 y se pueden editar los datos con simples WBTOs. Estos son los datos (en decimal):
NOTA: Pronto haré un tutorial en el que explicaré cómo funcionan todos los datos de los pokémon para que sepáis editarlos correctamente. Además, es probable que también haga rutinas suplementarias para que podáis editar fácilmente algunos aspectos más complicados, como la pokéball en la que fue capturado o para poder hacer shiny al pokémon.00 - Personalidad (4 bytes)
04 - ID del entrenador original (4 bytes)
08 - Nombre del pokémon (10 bytes)
18 - Idioma (2 bytes)
20 - Nombre del entrenador original (7 bytes)
27 - Marcas (1 byte)
28 - Checksum (2 bytes)
30 - ??? (posiblemente relleno)
32 - Especie (2 bytes)
34 - Objeto (2 bytes)
36 - Experiencia (4 bytes)
40 - Más PP (1 byte)
41 - Amistad (1 byte)
42 - Desconocido (2 bytes)
44 - Ataque 1 (2 bytes)
46 - Ataque 2 (2 bytes)
48 - Ataque 3 (2 bytes)
50 - Ataque 4 (2 bytes)
52 - PP Ataque 1 (1 byte)
53 - PP Ataque 2 (1 byte)
54 - PP Ataque 3 (1 byte)
55 - PP Ataque 4 (1 byte)
56 - EV Salud (1 byte)
57 - EV Ataque (1 byte)
58 - EV Defensa (1 byte)
59 - EV Velocidad (1 byte)
60 - EV Ataque especial (1 byte)
61 - EV Defensa especial (1 byte)
62 - Carisma (1 byte)
63 - Belleza (1 byte)
64 - Dulzura (1 byte)
65 - Ingenio (1 byte)
66 - Dureza (1 byte)
67 - Feel (1 byte)
68 - Estado del pokérus (1 byte)
69 - Localización (1 byte)
70 - Origen (2 bytes)
72 - IVs, huevo y habilidad (4 bytes)
76 - Cintas y Obediencia (4 bytes)
ACTUALIZACIONES
Tengo más rutinas que iré poniendo poco a poco. Recuerda que algunas las hice en su momento para Emerald. Así que hay algunas que las tengo que pasar a FR. Independientemente, las tenga que pasar o no, también las tengo que probar para ver si todo funciona correctamente. Luego las tengo que subir aquí y explicar cómo funcionan. Y eso sin contar que, después de tanto tiempo, la mitad de rutinas ni siquiera recuerdo cómo funcionaban y tengo que descifrarlo. Así que, entre que requiere bastante tiempo y que yo no dispongo de demasiado... En definitiva, que con tranquilidad, pero iré actualizando.
A parte, si dejáis cualquier sugerencia y la puedo llevar a cabo, también lo subiré.
Última edición por un moderador: