inv_gba
Thread Id: 24977
Thread Name: Crianza de Pokémon Shiny en la guardería [100%] [INVESTIGACIÓN FINALIZADA] [RUBY]
#0
Doctor Juanjo 12932
Notifiquese: Que el Grupo POSITRON, en persona de su representante [MENTION=12932]Juanjo[/MENTION] considere que esta investigación sea abierta al público debido a que el grupo POSITRON no se encuentra en su mejor momento ni sus miembros están completamente enfocados en su subforo y al mismo tiempo incitar a la generación de nuevos miembros.



PRESENTA:

¿CÓMO CRIAR POKéMON SHINY EN TERCERA GENERACIÓN?
PSEB System - Positron Shiny Egg Breeding System

INTRODUCCIÓN

Como muchos sabrán en los juegos de segunda generación era genial poder criar pokémon shinys, es decir si lograbas conseguir uno de estos raros especímenes al criar en la guardería obtenías un 1.5% de posibilidad (1/64) de tener un huevo del que nacería un pokémon shiny.



Para tercera generación esto se perdió. Y los pokémon shiny quedaron relegados a un simple azar y no a una mutación genética que me gustaba más.

MISIÓN

Lograr que la guardería de tercera generación logre generar ese 1.5% de probabilidad de generar un huevo shiny si el padre o la madre es shiny.

PROCEDIMIENTO



LOGROS CONSEGUIDOS

ESTUDIAR EL SCRIPT DE LA GUARDERÍA: Al investigarlo he descubierto que el special 0xB5 genera en el y en el los Pokémon de la guardería (Y hace algunas cosas más que no he descubierto).

El special2 LASTRESULT 0xB6 devuelve en la variable LASTRESULT un número que:

0x0 = No tienes Pokes y se presenta.

0x1 = Te va a dar un huevo.

0x2 = Tienes un solo Poke en la guardería y te dice que está bien.

0x3 = Tienes 2 Pokes en la guardería y te dice que están bien.

La parte del script que interesa es:

#org 0x1B22B2
preparemsg 0x81B27A2 '"[player] received the EGG from\nth..."
fanfare 0x16F
waitfanfare
waitmsg
waitkeypress
msgbox 0x81B27CD MSG_KEEPOPEN '"Take good care of it."
special 0xB8
clearflag 0x86
release
end

No se observa ningún giveegg.

LOGRAR QUE EL HUEVO SEA SHINY: Aún así introduciendo la rutina del shinyzer:

#org 0x71234A
checkflag 0x1234
if 0x1 call 0x871243C
preparemsg 0x81B27A2 '"[player] received the EGG from\nth..."
fanfare 0x16F
waitfanfare
waitmsg
waitkeypress
msgbox 0x81B27CD MSG_KEEPOPEN '"Take good care of it."
special 0xB8
clearflag 0x86
clearflag 0x1234
release
end

'---------------
#org 0x71243C
setvar 0x8003 0x1
return

De esta manera genero que el huevo que me entreguen sea Shiny. SOLAMENTE si la flag 1234 está activada.

La ventaja de hacer esto es que da independencia total de si el huevo es shiny o no, y el viejo solamente mirara si la flag externa está activa o no. (A este paso lo llamé la palanca de radioactividad de la guardería

CONTROLAR LA PROBABILIDAD DEL 15%:
A pesar de que realmente sera de 1.5%, se ha investigado para un 15% (es más fácil para probarlo pero el valor al final puede ser corregido perfectamente).
Bueno, no se mucho de como se manejan los eventos aleatorios del juego (Supongo que a muy bajo nivel hacen operaciones con bytes y comparan si el resultado están entre algún rango, o algo por el estilo).

Un 15% significa que de 100 posibilidades, 15 son aciertos. Es decir si una variable aleatoria toma 100 posibles valores, 15 de ellos serán aciertos. Por lo que me fui a la fácil: Generar una variable aleatoria random y evaluar los aciertos. ¡Por supuesto no iba a tomar 100 valores y tomar 15 como aciertos! simplemente 15/100 = 3/20. Una variable que toma 20 posiciones de los cuales 3 son aciertos:

'---------------
#org 0x712393
random 0x14
copyvar 0x50FE LASTRESULT
buffernumber 0x2 0x50FE
compare 0x50FE 0x0
if 0x1 goto 0x8712457
compare 0x50FE 0x1
if 0x1 goto 0x8712457
compare 0x50FE 0x2
if 0x1 goto 0x8712457
msgbox 0x87123EF MSG_FACE '" No hay huevos shiny."
end

'---------------
#org 0x712457
msgbox 0x8170CA7 MSG_FACE '" Hay huevos shiny."
setflag 0x1234
end


'---------
' Strings
'---------
#org 0x7123EF
= No hay huevos shiny.

#org 0x170CA7
= Hay huevos shiny.

De esta manera he logrado una especie de "gatillo" que al activarse genera una probabilidad de un 15% de que el huevo sea Shiny o no.

Aquí pueden ver esto funcionando:

YouTube Video

DETERMINAR SI EL POKéMON ES SHINY:

Gracias al método descrito por Mastermind_X, y planteado por [MENTION=13374]Javi4315♪[/MENTION] lo que define que un Pokémon sea Shiny o no es su personalidad que lo podemos obtener como los 4 primeros bytes de la información de un Pokémon (Para más información pueden ver esta investigación de [MENTION=12314]Gershel[/MENTION].

Esos cuatro bytes definen la personalidad del pokemon. Otro dato importante es la ID de entrenador (Que vemos en la TrainerCard) y la ID de entrenador secreta (Un número también aleatorio que no podemos ver).

La fórmula para saber si pokémon es Shiny es:

Trainer ID ⊕ Secret ID ⊕ P1 ⊕ P2

Donde:

Trainer ID, es la ID del TrainerCard que podemos ver en la dirección 0x02024EAE (2 Bytes).

Secret ID, es la ID secreta del Trainer que podemos ver en la dirección 0x02024EB0 (2 Bytes).

P1, son los 2 primeros bytes de la personalidad del pokémon.

P2, son los 2 últimos bytes de la personalidad del pokémon.

⊕, es el operador XOR.

El resultado de esta operación debe dar un valor en hexadecimal que si es menor a 08, entonces el Pokémon es Shiny.

Investigando un poco (Y jugando con los bytes) He descubierto que al almacenar un pokemón en la guardería podemos conseguir la personalidad del pokémon almacenado directamente (Sin tener que buscar cual pokémon del equipo insertamos):

0x20286D0 -> Primer Pokémon de la Guardería

0x2028720 -> Segundo Pokémon de la Guardería

Con esto para identificar un Pokémon Shiny habría que hacer esta operación. (Se requiere ASM para poder hacer XOR).

Gracias a [MENTION=15014]Cheve_X[/MENTION], tenemos una rutina específicamente diseñada para retornar el resultado de la operación para el primer pokemon de la guardería:

Iniciado por Cheve_X

.text
.align 2
.thumb
.thumb_func
.global lesson1

main:
push {r0-r4, lr}
ldr r4, .PKMN_DATA
ldrh r0, [r4]
ldrh r2, [r4, #0X2]
EOR r0, r2
ldr r4, .PKMN_DATA2
ldrh r3, [r4]
ldr r4, .PKMN_DATA3
ldrh r2, [r4]
EOR r3, r2
EOR r0,r3
ldr r1, .VAR
strh r0, [r1]
pop {r0-r1, pc}


.align 2
.PKMN_DATA:
.word 0x20286D0

.PKMN_DATA2:
.word 0x2024EB0

.PKMN_DATA3:
.word 0x2024EAE

.VAR:
.word 0x0201E8C2 + (0x800D * 2)



Para aquellos con problemas en pasarla a HEX...


1F B5 06 4C 20 88 62 88 50 40 05 4C 23 88 05 4C 22 88 53 40 58 40 04 49 08 80 03 BD D0 86 02 02 B0 4E 02 02 AE 4E 02 02 DC E8 02 02

Deben copiar ese código en un Offset vacío que termine en 0, 4, 8 o C, luego deberan usar un callasm a esa direccion+1

Si por ejemplo lo ponen en 0x700000 un script simple con ésto funcionando sería así:


#include std.rbh
#DYNAMIC 0x800000

#org @Inicio
callasm 0x700001
compare LASTRESULT 0x8
if B_> call @NoShiny
msgbox @sms1 MSG_NORMAL
end


#org @NoShiny
msgbox @sms2 MSG_NORMAL '"o hay un Shiny"
end



#org @sms1
= Hay un Shiny

#org @sms2
= No hay un Shiny


INSERTARLO EN EL SCRIPT DE LA GUARDERÍA

Como la rutina de Cheve solo identifica si un Pokemon es shiny (y no el segundo dos), he creado una segunda rutina (Que es igual pero carga el segundo Pokémon)

88 53 40 58 40 04 49 08 80 03 BD D0 86 02 02 B0 4E 02 02 AE 4E 02 02 DC E8 02 02 FF 1F B5 06 4C 20 88 62 88 50 40 05 4C 23 88 05 4C 22 88 53 40 58 40 04 49 08 80 03 BD 20 87 02 02 B0 4E 02 02 AE 4E 02 02 DC E8 02 02

De esta manera el script sería algo así:

'---------------
#include std.rbh
#dynamic 0x712345

#org @Inicio
callasm 0x700001
compare LASTRESULT 0x8
if B_< call @SiShiny
callasm 0x70000D
compare LASTRESULT 0x8
if B_< call @SiShiny
msgbox @sms2 MSG_NORMAL
end


#org @SiShiny
msgbox @sms1 MSG_NORMAL
goto @Proba
end



#org @sms1
= Hay un Shiny

#org @sms2
= No hay un Shiny

#org @Proba
random 0x14
copyvar 0x50FE LASTRESULT
buffernumber 0x2 0x50FE
compare 0x50FE 0x0
if 0x1 goto 0x8712457
compare 0x50FE 0x1
if 0x1 goto 0x8712457
compare 0x50FE 0x2
if 0x1 goto 0x8712457
msgbox 0x87123EF MSG_FACE '" No hay huevos shiny."
end

'---------------
#org 0x712457
msgbox 0x8170CA7 MSG_FACE '" Hay huevos shiny."
setflag 0x1234
end


'---------
' Strings
'---------
#org 0x7123EF
= No hay huevos shiny.

#org 0x170CA7
= Hay huevos shiny.

Este sería el script insertado en la chica (recuerden que es para probar que funcione).

YouTube Video

He insertado la rutina en 0x700000, recuerden que esta incluye una segunda rutina en 0x70000C.

Les dejo el script completo de la guardería con el 100% de esta investigación y listo para usarse: (Con el 1.5%)



EN RESUMEN

Este sistema hace que si alguno de los padres de un huevos es shiny genere un 1.5% de que el pokémon del huevo nazca Shiny.

Investigación iniciada a los 14 día del primer mes de 2014

Investigación principal finalizada a los 18 días del primer mes de 2014. Queda abierta a extensiones, mejores, adaptaciones [FR] y desarrollos posteriores de elementos descubiertos.

AGRADECIMIENTOS

-A [MENTION=12260]Serg!o[/MENTION], por su apoyo, ayuda y estar siempre dispuesto a resolverme dudas.
-A [MENTION=13374]Javi4315♪[/MENTION], por ayudarme y estar respaldando la investigación.
-A [MENTION=15014]Cheve_X[/MENTION], Por su granito de arena por el que pude completar la investigación.
-A [MENTION=26580]BLAx[/MENTION], por su interés y querer ayudar.
-Al grupo POSITRON.
-A la Comunidad Whack a Hack! en general

Firman:
Juanjo - Grupo POSITRON


Ha nacido el PSEB System - Positron Shiny Egg Breeding System
#1
BLAx/Atlas 26580
Se me ocurre una idea para solucionar la parte del 15%

La cosa sería que ese mismo script que has usado con la chica para que te diga un número aleatorio y sepas si el Pokémon es shiny o no, se introdujese en el script de la guardería, justo después de haber dicho SI a la pregunta de si quieres coger el huevo o no.

PROS del método:
- El porcentaje de "mutación genética" es real, ya que da la manera que lo tienes puesto ahora (aunque es provisional, imagino) puedes hablar con la mujer hasta que salga que si hay huevo shiny.
- Había pensado otro más, pero se me ha olvidado xD, si lo recuerdo edito y lo pongo.

CONTRAS del método:
- No estoy seguro de si se puede introducir el script de que el Pokémon sea shiny en el momento que yo digo. Creo que si, pero por si acaso lo pongo como CONTRA.
- Igual que antes, había sacado otro CONTRA, pero se me ha olvidado xD
#2
Doctor Juanjo 12932
Iniciado por BLAx
Se me ocurre una idea para solucionar la parte del 15%

La cosa sería que ese mismo script que has usado con la chica para que te diga un número aleatorio y sepas si el Pokémon es shiny o no, se introdujese en el script de la guardería, justo después de haber dicho SI a la pregunta de si quieres coger el huevo o no.

PROS del método:
- El porcentaje de "mutación genética" es real, ya que da la manera que lo tienes puesto ahora (aunque es provisional, imagino) puedes hablar con la mujer hasta que salga que si hay huevo shiny.
- Había pensado otro más, pero se me ha olvidado xD, si lo recuerdo edito y lo pongo.

CONTRAS del método:
- No estoy seguro de si se puede introducir el script de que el Pokémon sea shiny en el momento que yo digo. Creo que si, pero por si acaso lo pongo como CONTRA.
- Igual que antes, había sacado otro CONTRA, pero se me ha olvidado xD


Si lo de la chica es provisional. La idea es que este evento ocurra tan pronto metas el pokemon en la guardería e identifique que es shiny. Eso es fácil. Lo dejo aparte con la chica para expresar que ese 15% se activa o no. Y no siempre está presente.

De momento el "gatillo" de activar 15% es hablar con la chica. Pero en su momento será si el padre y/o la madre es shiny
#3
BLAx/Atlas 26580
Bueno, como te he dicho, no he hecho nunca algo similar a investigación de un ROM. No he conseguido sacar nada en claro, pero por lo menos sé que hay dos cosas que diferencian a los Shiny de los normales: el número es de otro color, el fondo del sprite es de un color más blanco que el de los otros. Al menos esto es así en Ruby.


Zigzagoon normal


Zigzagoon Shiny

Como se puede apreciar el numerito arriba a la izquierda es negro en el normal, y dorado en el Shiny. Alguna manera tiene que haber para diferenciarlos. Por otra parte el fondo del sprite Shiny es más brillante que el del sprite normal, con lo cual también hay algo ahí.

Obvia el nombre del Zigzagoon shiny, que ha salido así por usar un Gamshark para tener al Shiny.


He intentado usar el Cheat Engine para ver si hay algún cambio, pero no entiendo muy bien como funciona, así que no he sacado nada en claro más que lo que dicho :/
#4
Javi4315♪ 13374
[NOTA: Esto es para Ruby, como dice el título de la investigación]

Bueno, se puede determinar si un pokémon es o no shiny a partir de algunos datos de la ram. El problema es que de manera externa al rom se puede hacer, pero hacerlo en el rom es más complicado (aunque quizás existan rutinas). El problema viene porque hay que hacer operaciones XOR. Y digo que se puede porque hay una rutina para Fire Red, pero el caso es que se pudiera insertar una rutina con la misma función en Ruby.

Como sea, vamos a ver cómo determinar si el pokémon es shiny. Necesitamos los siguientes datos de la ram:



Es importante saber que estos datos están permutados, por lo que, a la hora de manipularlos, hay que tener esto en cuenta.

EJEMPLOS

Voy a hacer dos pruebas. Una con un pokémon normal y otra con uno shiny. Para las operaciones XOR utilizaré esta calculadora, ¿Por qué esta calculadora? Efectivamente, porque es la primera que he encontrado en Google.

EJEMPLO 1 - Pokémon no shiny

Obtenemos de la RAM los datos que necesitamos:



Pero recordemos que los datos está permutados. Así que vamos a ponerlos bien:



El Trainer ID y el Secret ID tienen 2 bytes, pero la personalidad tiene 4. Así que vamos a partirla en dos partes:

C93B5CCA: P1 = C93B; P2 = 5CCA.

Ahora tenemos vamos a nuestra calculadora XOR para hacer los cálculos. La fórmula es previsible:

Trainer ID ⊕ Secret ID ⊕ P1 ⊕ P2

O lo que es lo mismo (sustituyendo por los valores):

DFA1 ⊕ 9C5E ⊕ C93B ⊕ 5CCA

Y esta preciosa operación nos da como resultado: D60E

CONCLUSIÓN: El pokémon no es shiny.

EJEMPLO 2 - Pokémon shiny

(Copio el ejemplo 1 y le cambio los datos)

Obtenemos de la RAM los datos que necesitamos:



*Obviamente los valores de Trainer ID y Secret ID son los mismos porque es la misma partida. Si iniciáramos otra partida, estos datos cambiarían.

Pero recordemos que los datos está permutados. Así que vamos a ponerlos bien:



El Trainer ID y el Secret ID tienen 2 bytes, pero la personalidad tiene 4. Así que vamos a partirla en dos partes:

DC289FD2: P1 = DC28; P2 = 9FD2.

Ahora tenemos vamos a nuestra calculadora XOR para hacer los cálculos. La fórmula es previsible:

Trainer ID ⊕ Secret ID ⊕ P1 ⊕ P2

O lo que es lo mismo (sustituyendo por los valores):

DFA1 ⊕ 9C5E ⊕ DC28 ⊕ 9FD2

Y esta preciosa operación nos da como resultado: 5

CONCLUSIÓN: El pokémon sí es shiny.

Vale, ¿Y eso por qué?

Claro, os estaréis prguntando, ¿Por qué si el resultado es D60E no es shiny? ¿Y por qué si es 5 sí lo es?

Bueno, pues esto es lo más sencillo de todo. Siempre que el resultado sea menor que 8, el pokémon será shiny.

¿Entonces qué nos quedas?

Bueno. Sabemos dónde están los tres datos que necesitamos y podemos determinar si el resultado es menor que 8. Lo que necesitamos sería hacer las operaciones (XOR) de manera interna. A ver que se puede hacer.
#5
Doctor Juanjo 12932
Iniciado por Javi4315♪
[NOTA: Esto es para Ruby, como dice el título de la investigación]



La explicación que das es ¡Brillante! La había leído del tutorial de "Search for Cheats" de Mastermind_X, traducido a nuestra preciosa lengua castellana por nuestro admin querido [MENTION=12260]Serg!o[/MENTION]

Lo que has explicado aquí es ¡Brillante! ¡Absolutamente brillante!, al comparar los bytes de los pokemon allí arriba (Las imágenes del Paint) podemos comprobar esto. Fue mi primer idea pero no conocía que esos 4 primeros bytes (Que tan extraños me parecieron, y eran únicos sin importar el tipo del pokemon) ¡Era la codiciada personalidad!. Además nunca sabía que la ID secreta ese byte.

¡Amigo debo decirte que es brillante!. Pero comprobemos esto con las imágenes que subí arriba (Usando Excel o Calculadora de Windows se puede Javi xD)



Dratini Shiny: A7 21 6F A1
Dratini Normal: BC F2 19 15

ID Encontrada: A8 42 (Que coincide al repuntear con el 17064 observado)

ID Secreta: 64 C2

PERMUTANDO:

DS: A16F21A7
DN: 1519F2BC
ID: 42A8
sID: C264

Intentemos primero con el Shiny:

X_DS: A16F⊕21A7 = 80C8
X_ID: 42A8⊕C264 = 80CC

VAR = 80C8⊕80CC = 04

Aquí tenemos un resultado esperado :D

Ahora voy a desarrollar el proceso de manera algorítmica...

Seguiré buscando
#6
Cheve_X 15014
¿Que tal chicos? Bueno, pues no trabajo mucho con ruby, pero aquí vá mi granito de arena...




.align 2
.thumb

/*Special 0x44 is the Logical XOR operation.
returns 1st ^^ 2nd. Doesn't change the originals*/
special_44: push {r1-r4, lr}
ldr r3, pointer7
ldrh r0, [r3]
ldrh r4, [r3, #0x2]
bl call_var_decrypt
add r3, r0, #0x0
add r0, r4, #0x0
add r4, r3, #0x0
bl call_var_decrypt
ldrh r0, [r0]
ldrh r2, [r4]
EOR r0, r2
pop {r1-r4, pc}
.hword 0x0000
pointer7: .word 0x0203f4d8

call_var_decrypt: ldr r1, var_decrypt
bx r1
var_decrypt:.word 0x0806E455



Ésta rutina actualmente, carga dos variables que hayamos puesto en 0x0203f4d8 de la siguiente manera:

Writebytetooffset 0x50 0x0203f4d8
Writebytetooffset 0x60 0x0203f4d9
Writebytetooffset 0x06 0x0203f4da
Writebytetooffset 0x80 0x0203f4db

aqui cargamos la variable 6050 y 8008


Pero hay un problema, ésta rutina fue hecha para reemplazar un Special (El 0x44) en FireRed, y ser usada con un special2 de forma que pueda devolver el valor a una variable que nosotros le digamos... Mañana con tiempo veré si usando el IDA PRO, IPS y algun que otro truco me doy cuenta como funciona, o, miro otras rutinas para intentar lograr que carge el resultado en la primer variable que seteamos
#7
Doctor Juanjo 12932
Jugando un poco con las direcciones de memoria me he topado con algo bastante interesante :O

0x20286D0 -> Primer Pokémon de la Guardería

0x2028720 -> Segundo Pokémon de la Guardería

Allí está almacenado todos los datos del Pokémon que esté en la guardería, es decir se copian todos los valores directamente de los datos que teníamos por decirlo así en el equipo. Eso significa que la ID del Pokémon de la guardería sería 0x20286D0 [4 Bytes]. Eso nos simplifica bastante el problema ya que limitamos la búsqueda de shiny directamente en los pokémon que estén en la guardería.

Aquí tienen un ejemplo de como sería el algoritmo obteniendo 8 variables [He resaltado con colores los bytes que deben operarse con XOR, y puesto el resultado del mismo color en el centro]


Iniciado por Cheve_X
¿Que tal chicos? Bueno, pues no trabajo mucho con ruby, pero aquí vá mi granito de arena...



¡Chevesitoooo! Si logras hacer que esa rutina funcione, en teoría tendríamos listo toda la investigación :D

Guardamos temporalmente en las 2 variables los dos bytes que queremos XOR'rar (?) que la obtenemos de los offsets encontrados por Javi y por mi. Una tercera variable almacena el resultado. Repetimos el proceso 6 veces con las otras variables (Reutilizando lo que más se pueda) Y tendríamos nuestro script funcionando en un 100%.

¡CHEVE!, ¿Te mencioné que eres BRILLANTE?
#8
Cheve_X 15014
¡Hola Chicos! Al fin pude hacer algo útil en ASM :3 Me siento muy bien!

Bueno, miren, les diré como funciona la rutina (Lo unico malo que tiene, por ahora, es que solo chequea el Primer Pokémon que Guardamos si guardamos el shiny segundo, será como que no haya ninguno (Cuando pueda lo arreglo, que ahora estoy emocionado)

Funciona así:

Carga los valores de la OTID1 y la OTID2 y hace XOR, y guarda el resultado.
Carga los valores de la ID y SID y hace XOR, y guarda el resultado.
Hace XOR entre los resultados guardados y guarda ese resultado en la variable LASTRESULT :3

Bueno, aquí la rutina:


.text
.align 2
.thumb
.thumb_func
.global lesson1

main:
push {r0-r4, lr}
ldr r4, .PKMN_DATA
ldrh r0, [r4]
ldrh r2, [r4, #0X2]
EOR r0, r2
ldr r4, .PKMN_DATA2
ldrh r3, [r4]
ldr r4, .PKMN_DATA3
ldrh r2, [r4]
EOR r3, r2
EOR r0,r3
ldr r1, .VAR
strh r0, [r1]
pop {r0-r1, pc}


.align 2
.PKMN_DATA:
.word 0x20286D0

.PKMN_DATA2:
.word 0x2024EB0

.PKMN_DATA3:
.word 0x2024EAE

.VAR:
.word 0x0201E8C2 + (0x800D * 2)



Para aquellos con problemas en pasarla a HEX...


1F B5 06 4C 20 88 62 88 50 40 05 4C 23 88 05 4C 22 88 53 40 58 40 04 49 08 80 03 BD D0 86 02 02 B0 4E 02 02 AE 4E 02 02 DC E8 02 02

Deben copiar ese código en un Offset vacío que termine en 0, 4, 8 o C, luego deberan usar un callasm a esa direccion+1

Si por ejemplo lo ponen en 0x700000 un script simple con ésto funcionando sería así:


#include std.rbh
#DYNAMIC 0x800000

#org @Inicio
callasm 0x700001
compare LASTRESULT 0x8
if B_> call @NoShiny
msgbox @sms1 MSG_NORMAL
end


#org @NoShiny
msgbox @sms2 MSG_NORMAL '"o hay un Shiny"
end



#org @sms1
= Hay un Shiny

#org @sms2
= No hay un Shiny




RECUERDEN QUE ES SOLO PARA RUBY
#9
Doctor Juanjo 12932
Iniciado por Cheve_X
¡Hola Chicos! Al fin pude hacer algo útil en ASM :3 Me siento muy bien!

Bueno, miren, les diré como funciona la rutina (Lo unico malo que tiene, por ahora, es que solo chequea el Primer Pokémon que Guardamos si guardamos el shiny segundo, será como que no haya ninguno (Cuando pueda lo arreglo, que ahora estoy emocionado)

Funciona así:

Carga los valores de la OTID1 y la OTID2 y hace XOR, y guarda el resultado.
Carga los valores de la ID y SID y hace XOR, y guarda el resultado.
Hace XOR entre los resultados guardados y guarda ese resultado en la variable LASTRESULT :3

Bueno, aquí la rutina:


.text
.align 2
.thumb
.thumb_func
.global lesson1

main:
push {r0-r4, lr}
ldr r4, .PKMN_DATA
ldrh r0, [r4]
ldrh r2, [r4, #0X2]
EOR r0, r2
ldr r4, .PKMN_DATA2
ldrh r3, [r4]
ldr r4, .PKMN_DATA3
ldrh r2, [r4]
EOR r3, r2
EOR r0,r3
ldr r1, .VAR
strh r0, [r1]
pop {r0-r1, pc}


.align 2
.PKMN_DATA:
.word 0x20286D0

.PKMN_DATA2:
.word 0x2024EB0

.PKMN_DATA3:
.word 0x2024EAE

.VAR:
.word 0x0201E8C2 + (0x800D * 2)



Para aquellos con problemas en pasarla a HEX...


1F B5 06 4C 20 88 62 88 50 40 05 4C 23 88 05 4C 22 88 53 40 58 40 04 49 08 80 03 BD D0 86 02 02 B0 4E 02 02 AE 4E 02 02 DC E8 02 02

Deben copiar ese código en un Offset vacío que termine en 0, 4, 8 o C, luego deberan usar un callasm a esa direccion+1

Si por ejemplo lo ponen en 0x700000 un script simple con ésto funcionando sería así:


#include std.rbh
#DYNAMIC 0x800000

#org @Inicio
callasm 0x700001
compare LASTRESULT 0x8
if B_> call @NoShiny
msgbox @sms1 MSG_NORMAL
end


#org @NoShiny
msgbox @sms2 MSG_NORMAL '"o hay un Shiny"
end



#org @sms1
= Hay un Shiny

#org @sms2
= No hay un Shiny




RECUERDEN QUE ES SOLO PARA RUBY
.

Chevesito :D lo hiciste. ¡Eres fantástico! Cuando llegue a mi casa lo probaré y te digo. ¡Eres genial! Aunque la pregunta es que el resultado son 2 bytes. ¿Eso está incluído?
#10
Cheve_X 15014
Iniciado por Juanjo
.

Chevesito :D lo hiciste. ¡Eres fantástico! Cuando llegue a mi casa lo probaré y te digo. ¡Eres genial! Aunque la pregunta es que el resultado son 2 bytes. ¿Eso está incluído?


No entiendo muy bien a lo que te refieres... El resultado de toda la operación puede ser cualquiera de entre 0000 a 7FFF que son los valores que entran en la variable :D
#11
Doctor Juanjo 12932
Iniciado por Cheve_X
No entiendo muy bien a lo que te refieres... El resultado de toda la operación puede ser cualquiera de entre 0000 a 7FFF que son los valores que entran en la variable :D


¡Oh vaya! perdóname, no se porque tenía en mi mente que una variable almacenaba hasta FF, ahora si lo recuerdo. Definitivamente los años pesan.
#12
Javi4315♪ 13374
Bueno, ¿Pero ahora la cuestión no sería algo así como seleccionar un pokémon del equipo y que se determine si es shiny? Es decir, no que te diga si es shiny el primer pokémon, o el segundo, sino el que tú selecciones, me refiero.
#13
DriveTheGamer 28224
Pues esta bastante genial la investigación, suena bien tener pokémons shiny más fáciles con la guardería y ahora me entero de que la de pokémon Oro y Plata podían hacer eso. :D
#14
Doctor Juanjo 12932
Iniciado por Javi4315♪
Bueno, ¿Pero ahora la cuestión no sería algo así como seleccionar un pokémon del equipo y que se determine si es shiny? Es decir, no que te diga si es shiny el primer pokémon, o el segundo, sino el que tú selecciones, me refiero.


No exactamente, ya que toma la información directamente del que esté en la guardería. De esa manera evitamos tener que seleccionarlo. Aunque lo que dices puede ser válido si queremos hacer un comando que sirva en general de acuerdo al pokemon que seleccionemos. Pero para efectos de esta inve con solo el de la guardería está perfecto.

Ahora, remasterizando la rutina de Cheve, he logrado hacer que lea tanto el primero como el segundo de la guardería. He de decir que no se nada de ASM pero aún así soy lo bastante curioso para entender el HEX, por lo tanto he copiado la misma rutina en el offset 0x70000C (Por ejemplo) y cambiado los bytes de la dirección del primero de la guardería por el del segundo. Después de eso fue simplemente trabajo del script (Que si manejo bastante bien)

88 53 40 58 40 04 49 08 80 03 BD D0 86 02 02 B0 4E 02 02 AE 4E 02 02 DC E8 02 02 FF 1F B5 06 4C 20 88 62 88 50 40 05 4C 23 88 05 4C 22 88 53 40 58 40 04 49 08 80 03 BD 20 87 02 02 B0 4E 02 02 AE 4E 02 02 DC E8 02 02

De esta manera el script sería algo así:

'---------------
#include std.rbh
#dynamic 0x712345

#org @Inicio
callasm 0x700001
compare LASTRESULT 0x8
if B_< call @SiShiny
callasm 0x70000D
compare LASTRESULT 0x8
if B_< call @SiShiny
msgbox @sms2 MSG_NORMAL
end


#org @SiShiny
msgbox @sms1 MSG_NORMAL
goto @Proba
end



#org @sms1
= Hay un Shiny

#org @sms2
= No hay un Shiny

#org @Proba
random 0x14
copyvar 0x50FE LASTRESULT
buffernumber 0x2 0x50FE
compare 0x50FE 0x0
if 0x1 goto 0x8712457
compare 0x50FE 0x1
if 0x1 goto 0x8712457
compare 0x50FE 0x2
if 0x1 goto 0x8712457
msgbox 0x87123EF MSG_FACE '" No hay huevos shiny."
end

'---------------
#org 0x712457
msgbox 0x8170CA7 MSG_FACE '" Hay huevos shiny."
end


'---------
' Strings
'---------
#org 0x7123EF
= No hay huevos shiny.

#org 0x170CA7
= Hay huevos shiny.

Con este script mira si alguno de los padres son shinys y si es cierto hace el script de probabilidad del 15% y en caso de ser positivo entonces dice que hay huevos shinys.

Este script debe ser fácil insertar en el script de la guardería (Es más ya lo estoy insertando)

Al probar esto ha funcionado perfecto.

Puedo decir que esta investigación está al 100%. Falta organizar el post principar y comenzar a redactar el tutorial ¡Gracias Cheve y Javi!

EDITO: Script final :D

'---------------
#include std.rbh
#dynamic 0x712345

#org 0x1B222D
lock
faceplayer
special 0xB5
special2 LASTRESULT 0xB6
compare LASTRESULT 0x1
if 0x1 goto 0x81B2262
compare LASTRESULT 0x2
if 0x1 goto 0x81B22E7
compare LASTRESULT 0x3
if 0x1 goto 0x81B22FE
msgbox 0x81B25CB MSG_KEEPOPEN '"I'm the DAY-CARE MAN.\pI help take..."
release
end

'---------------
#org 0x1B2262
msgbox 0x81B2659 MSG_YESNO '"Ah, it's you!\pWe were raising you..."
compare LASTRESULT 0x1
if 0x1 goto 0x81B2298
msgbox 0x81B28C4 MSG_YESNO '"ine."
compare LASTRESULT 0x1
if 0x1 goto 0x81B2298
msgbox 0x81B2745 MSG_KEEPOPEN '" ell then, I'll keep it.\nThanks!"
clearflag 0x86
special 0xB7
release
end

'---------------
#org 0x1B22E7
special 0xB5
msgbox 0x81B2710 MSG_KEEPOPEN '"Ah, it's you! Good to see you.\nYo..."
setvar 0x8004 0x0
call 0x81B22CD
release
end

'---------------
#org 0x1B22FE
special 0xB5
msgbox 0x81B2897 MSG_KEEPOPEN '"Ah, it's you! Your and\n..."
special 0xB9
special 0x8D
waitmsg
waitkeypress
setvar 0x8004 0x0
call 0x81B22CD
setvar 0x8004 0x1
call 0x81B22CD
release
end

'---------------
#org 0x1B2298
special2 LASTRESULT 0x83
compare LASTRESULT 0x6
if 0x5 goto 0x871234A
msgbox 0x81B2766 MSG_KEEPOPEN '"You have no room for it...\nCome b..."
release
end

'---------------
#org 0x1B22CD
clearflag 0x86
release
end

'---------------
#org 0x71234A
call @BusqueShiny
preparemsg 0x81B27A2 '"[player] received the EGG from\nth..."
fanfare 0x16F
waitfanfare
waitmsg
waitkeypress
msgbox 0x81B27CD MSG_KEEPOPEN '"Take good care of it."
special 0xB8
clearflag 0x86
clearflag 0x1234
release
end

'---------------
#org @BusqueShiny
callasm 0x700001
compare LASTRESULT 0x8
if B_< call @SiShiny
callasm 0x70000D
compare LASTRESULT 0x8
if B_< call @SiShiny
return

#org @SiShiny
random 0x14
copyvar 0x50FE LASTRESULT
buffernumber 0x2 0x50FE
compare 0x50FE 0x0
if 0x1 goto @NaceShiny
compare 0x50FE 0x1
if 0x1 goto @NaceShiny
compare 0x50FE 0x2
if 0x1 goto @NaceShiny
return

#org @NaceShiny
setvar 0x8003 0x1
return



'---------
' Strings
'---------
#org 0x1B25CB
= I'm the DAY-CARE MAN.\pI help take care of the precious\nPOKéMON of TRAINERS.\pIf you'd like me to raise your POKéMON,\nhave a word with my wife.

#org 0x1B2659
= Ah, it's you!\pWe were raising your POKéMON, and my\ngoodness, were we surprised!\pYour POKéMON had an EGG!\pWe don't know how it got there,\nbut your POKéMON had it.\pYou do want it, yes?

#org 0x1B28C4
= ine.

#org 0x1B2745
= ell then, I'll keep it.\nThanks!

#org 0x1B2710
= Ah, it's you! Good to see you.\nYour 's doing fine.

#org 0x1B2897
= Ah, it's you! Your and\n are doing fine.

#org 0x1B2766
= You have no room for it...\nCome back when you've made room.

#org 0x1B27A2
= [player] received the EGG from\nthe DAY-CARE MAN.

#org 0x1B27CD
= Take good care of it.

¡ARRIBA GRUPO POSITRÓN!

Investigación principal finalizada a los 18 días del primer mes de 2014. Queda abierta a extensiones, mejores, adaptaciones [FR] y desarrollos posteriores de elementos descubiertos.

Firman:
Juanjo - Grupo POSITRÓN


Esperen pronto el PSEB System - Positron Shiny Egg Breeding System
#15
JV Works 12391
Pollo

(?)

Pues no tengo más que felicitarte por excelente trabajo que has hecho con esta investigación amigo. Una vez más, se ha demostrado que con esfuerzo se puede lograr lo que se desea.

Este sistema se puede utilizar de muchas maneras distintas, aunque lo primordial será agregar un plus al coleccionismo al aumentar las posibilidades de obtener pokemons (O en este caso, huevos), shinys. Ahora bien, ya te dije que ese ratio de 1.5% me parece demasiado poco, pero bueno, ya será cuestión de cada quien editarlo.

Y una vez más, y por el poder del Pollo, ¡Que viva Positron! :D
#16
Doctor Juanjo 12932
Bien. ¡Lo prometido en deuda! ¡Aquí tienen el vídeo del sistema funcionando en un 100%.

Tengan cuidado de leer las anotaciones que he dejado ya que explican todo el sistema funcionando. Cualquier duda pueden plantearla aquí. O también dentro de poco redactaré el tutorial.

YouTube Video

Att: Doctor Juanjo
#17
Brock 25910
GENIAAAL!!!!1 que panda de genios tenemos aqui
sois excelentes

Mi mas sincera enhorabuena GENIOS :)
#18
Chamber4315♪ 26330
Felicidades muchachos, una buena manera de incentivar el breeding en los RH!!

[MENTION=28012]Crystal_[/MENTION] Seria posible que hicieramos algo similar en GBC? y digo similar por que en Crystal ya existe la rutina del odd egg, solo haria falta que leyera si alguno de los padres es shiny y de ahi saltar a esa rutina u otra similar pero mas corta.

Seria relativamente sencillo no?? aunque ya vez que en GBC nada facil jaja
#19
Doctor Juanjo 12932
Iniciado por Chamber
Felicidades muchachos, una buena manera de incentivar el breeding en los RH!!

[MENTION=28012]Crystal_[/MENTION] Seria posible que hicieramos algo similar en GBC? y digo similar por que en Crystal ya existe la rutina del odd egg, solo haria falta que leyera si alguno de los padres es shiny y de ahi saltar a esa rutina u otra similar pero mas corta.

Seria relativamente sencillo no?? aunque ya vez que en GBC nada facil jaja


De por sí en GBC el proceso si que existe y te genera un huevo shiny en 1/64 = 1.56...%

Es más, ese sistema fue el que me motivó a investigar esto :D. (No se GBC pero opino que el proceso debe ser fácil de hallar ya que YA está implementado)
#20
Chamber4315♪ 26330
Iniciado por Juanjo
De por sí en GBC el proceso si que existe y te genera un huevo shiny en 1/64 = 1.56...%

Es más, ese sistema fue el que me motivó a investigar esto :D. (No se GBC pero opino que el proceso debe ser fácil de hallar ya que YA está implementado)


Bueno, existe y no. Te explico.

Esa mecanica es exclusiva de Pokemon Crystal y aplica únicamente al huevo (Odd Egg) que te regala el hombre de la guarderia.

En el caso de las versiones internacionales el Odd Egg tiene un 14% de probabilidades de ser shiny (segun bulbapedia) y 50% de probabilidad en la version japonesa.

Es importante mencionar que solo pueden "nacer" de ese huevo Pichu, Cleffa, Igglybuff, Tyrogue, Smoochum, Elekid, o Magby, los cuales tendran el movimiento Dizzy Punch.

En nuestro caso (GBC) habria que separar la parte de la rutina que crea los IV de la rutina que define el pokemon y el moveset, para asi permitir que cualquier pokemon pueda ser shiny.

Aunque al final creo que ni es necesario, por que nosotros modificamos la probabilidad de que aparesca un pokemon shiny de manera salvaje y si los IV se crean de la misma manera para todos los tipos de captura entonces no seria necesario implementar algo asi, bueno, eso creo, si no que Crystal_ o Javcdark me desmientan XD
#21
Doctor Juanjo 12932
Iniciado por Chamber
Bueno, existe y no. Te explico.

Esa mecanica es exclusiva de Pokemon Crystal y aplica únicamente al huevo (Odd Egg) que te regala el hombre de la guarderia.

En el caso de las versiones internacionales el Odd Egg tiene un 14% de probabilidades de ser shiny (segun bulbapedia) y 50% de probabilidad en la version japonesa.

Es importante mencionar que solo pueden "nacer" de ese huevo Pichu, Cleffa, Igglybuff, Tyrogue, Smoochum, Elekid, o Magby, los cuales tendran el movimiento Dizzy Punch.

En nuestro caso (GBC) habria que separar la parte de la rutina que crea los IV de la rutina que define el pokemon y el moveset, para asi permitir que cualquier pokemon pueda ser shiny.

Aunque al final creo que ni es necesario, por que nosotros modificamos la probabilidad de que aparesca un pokemon shiny de manera salvaje y si los IV se crean de la misma manera para todos los tipos de captura entonces no seria necesario implementar algo asi, bueno, eso creo, si no que Crystal_ o Javcdark me desmientan XD


No hablo precisamente del Odd Egg, aunque podría estar equivocado.

Citaré a Bulbapedia:
In Generation II, a player can breed for "Shininess." Due to the method the Generation II games use for calculating whether a Pokémon is Shiny or not, an Egg bred from an alternately-colored Pokémon has a chance as high as 1/64 of being alternately colored itself, but only if the offspring is of the opposite gender as the Shiny parent. This does not apply in later games, however.


Por eso te digo que casualmente puedes toparte con ese sistema ya existente.

Att: Doctor Juanjo
#22
Chamber4315♪ 26330
Iniciado por Juanjo
No hablo precisamente del Odd Egg, aunque podría estar equivocado.

Citaré a Bulbapedia:

[QUOTE]In Generation II, a player can breed for "Shininess." Due to the method the Generation II games use for calculating whether a Pokémon is Shiny or not, an Egg bred from an alternately-colored Pokémon has a chance as high as 1/64 of being alternately colored itself, but only if the offspring is of the opposite gender as the Shiny parent. This does not apply in later games, however.


Por eso te digo que casualmente puedes toparte con ese sistema ya existente.

Att: Doctor Juanjo[/QUOTE]

Tienes razon, ese sistema ya esta implementado y fui yo el que lo olvido. Por eso hay un "truco" muy famoso por la web, donde cambias el RED Gyarados a RBY para que un Ditto Copie sus IV's, capturas al Ditto y al pasarlo a GSC ya es shiny, lo que facilita la crianza.

Entonces caso cerrado jaja

Gracias y felicidades de nuevo por la investigacion!
#23
Kirito 28212
You put on a nice looking, I'm sorry not to have participated. Congratulations to all.