inv_gba
Thread Id: 25952
Thread Name: [Investigacion-GBC]Tutor de movimientos para G/S
#0
Chamber4315♪ 26330
A pesar de ser pocos los temas de investigacion GBC, abro este tema con el fin de que los usuarios mas experimentados apoyen con sus conocimientos técnicos y los mas novatos aporten ideas.

Objetivo: Emular/trasladar el tutor de movimiento(s) de Pokémon Crystal a Pokémon Gold & Silver.

Conocimentos previos: Gracias al desensamble de Crystal sabemos que el tutor de movimientos ocupa numero 0x83 del comando "special" (0xF).

Meta a corto plazo: A pesar de contar con toda la documentación para poder trasladar el tutor de movimientos de Crystal a Gold&silver, es mucho trabajo tener que adaptar y buscar todas las rutinas necesarias, por eso propongo una forma diferente de hacer los tutores, no mediante ASM, si no mediante Scripts (o la mezcla de ambos).

Usando la documentación del compendio de Tauwasser y la documentación Ram de KBC podemos escribir datos en la Ram y enseñarle movimientos a nuestros pokemon pero con algunas limitaciones.

Los movimientos a enseñar deberan ser "genericos", es decir, aquellos movimientos que los pueden aprender todos los pokemon con excepcion de Caterpie, Metapod, Weedle, Kakuna, Magikarp, Ditto, Unown, Wobbuffet, Smeargle,como Curse o Double Team, esto con el fin de simplificar la tarea y de paso ahorrar espacio en las TM.

Los movimientos que cuentan con estas caracteristicas son:


NOTA: Con un poco de trabajo extra podemos comprobar si el pokemon posee sexo y hacer un tutor para Attract.

El primer paso para el script es comprobar que el pokemon seleccionado NO sea uno de los anteriores mencionados y para ello podemos usar el comando "special" con su variable 0x4C, el cual abre el menu del pokemon y pone en la RAM de los scripts ($D173) el numero del pokemon y el nombre en la MEMORY1 ($CF91).



De ahi aplicamos tantos "if equal" como sean necesarios para indicar que el pokemon NO puede aprender el movimiento.

#org 0x000000
special 0x4C
if != 0x1B 0xYYXX ' 0xXXYYZZ
if != 0x1C ETC.
...


Segun Tauwasser, el special 0x4C devuelve 2 resultados, en la RAM el No. del pokemon seleccionado y en la MEMORY1 el nombre del pokemon. Tengo la teoria de que devuelve un tercer valor en $D006 (o $D005) , que vendría siendo el lugar en la party del pokémon seleccionado, de ser asi, nos podria ahorrar mucho trabajo de ASM.

Después de toda la comprobación, en el caso de que el pokemon SI pueda aprender el movimiento podemos partir de dos vertientes:



*Estos metodos propuestos no son tan profesionales, pero hasta no conocer como trabajan las TM al momento de sobrescribir movimientos, no podemos hacer nada mas.

Para escribir el movmiento del pokemon, solo hace falta hacer ramificaciones de scripts ayudados del comando "copyvartobyte", el cual escribe el index/valor del movimiento en la memoria Ram correspondiente de cada pokemon y de sus PP.

Lo mas importante de esta metodologia debe ser su versatildiad. El script debe estar hecho de tal forma que interactue con las variables, de esa forma podremos estar usando el mismo script (con 3jump) una y otra vez con tan solo estar cambiando las variables de cada movimiento.

Dentro de poco voy a publicar un borrador del script para un mejor entendimiento.

PD: Quizas los novatos no entienda muy bien de lo que hablo, pero tan pronto aprendan a hacer scripts en GBC les sera muy facil relacionar los terminos.

Saludos!
#1
G0LD_ZTHVARD0X! 27515
Bien, como primer punto, para el script veo necesario que miremos el script original de cristal (que debe ser mas complicado al ser un evento de un solo dia) y en base a el trasladarlo.

Suena facil, pero el problema viene en que el script usa specials exclusivos de cristal, donde viene el problema.

Ademas, el tutor enseña tres movimientos, los cuales no son genericos, y no son posibles enseñarselos a todos los pokemon, por lo cual veo posible hacerlo con cualquier movimiento, asi que lo mejor seria ojear el script de pokemon cristal y ver como esta estructurado (obvio que el RAM map varia entre ambas versiones)
#2
Chamber4315♪ 26330
Ya he mirado varias (MUCHISIMAS) veces el script de crystal y no podemos hacerlo igual por las variables del comando special.

Ya tengo ubicadas las rutinas y todo lo necesario para trasladar la información, el problema es que se tiene que adaptar jumps, calls y direcciones a la RAM de Gold y eso es pesadisimo.

Lo que mencionas sobre el tutor movimientos, que los ataques que enseña son especificos (Flamethrower, Thunderbolt y Ice Beam) de momento no me parece relevante, por que si empezamos con lo mas dificil puede ser que no avancemos, por eso me parece mejor algo mas "generico".

En el caso del tutor de Crystal, el juego usa los ultimos 3 bits en los datos de los stats de los pokemon para revisar la compatibilidad. -En total son 7 bits libres los que tenemos, asi que podriamos tener 7 tutores especificos en total mas los genericos.

Ya antes [MENTION=28012]Crystal_[/MENTION] nos ha dicho como podemos chechar esa compatibiliad con una rutina ASM bastante sencilla, lo unico que no se es como hacer aparecer el texto "ABLE/NOT ABLE" para marcar la compatibilidad visualmente.

En Crystal, la rutina que abre la party y revisa los pokemon esta en 0x50000, asi que podemos hacer un callba y ir probando.
#3
Chamber4315♪ 26330
He aqui la documentacion de DataCrystal:

SpecialsPointers: ; c029, Tabla de pointers del comando "special"

Function4925b: ; 4925b, rutina del "special 0x83" - tutor de movimientos
call FadeToMenu; funciones de pantalla
call WhiteBGMap; funciones de pantalla
call Functionfdb; funciones de pantalla
call DelayFrame; funciones de pantalla
ld b, $14; funciones de pantalla
call GetSGBLayout; funciones de pantalla
xor a; exclusion logica que pone a en $0
ld [$d142], a
call Function492a5; determina el movimiento (Flamethrower, Thunderbolt o Ice Beam)
ld [$d265], a; carga el index del movimiento
ld [$d262], a
call GetMoveName ; carga el nombre a StringBuffer1 y...
call CopyName1 ; lo copia al StringBuffer2
callba Function2c7fb; copia el contenido de StringBuffer2 a $d066
jr c, .asm_4929c; si presionas B termina.
jr .asm_49291

.asm_49289
callba Function2c80a
jr c, .asm_4929c

.asm_49291
call Function492b9; abre el menu de la party
jr nc, .asm_49289
xor a
ld [ScriptVar], a
jr .asm_492a1

.asm_4929c
ld a, $ff
ld [ScriptVar], a

.asm_492a1
call Function2b3c
ret
; 492a5

Function492a5: ; 492a5
ld a, [ScriptVar]
cp $1
jr z, .asm_492b3
cp $2
jr z, .asm_492b6
ld a, $3a
ret

.asm_492b3
ld a, $35
ret

.asm_492b6
ld a, $55
ret
; 492b9

Esto nos puede dar una idea de como combinar ASM con los scripts.
#4
Chamber4315♪ 26330
Después de un mes de investigación los resultados son los siguientes:

En base a ASM he logrado hacer rutinas con las siguientes funciones.


Asuntos pendintes:
-Comprobar la compatibilidad a base de Bits y no de Bytes como se hace actualmente.
-Mostrar la compatibilidad en el menu del equipo.



Una primera versión del tutor puede ser vista en el siguiente video, sin embargo no se muestra la caja de seleccion.

Pronto actualizare con la nueva versión y un parche.


YouTube Video
#5
G0LD_ZTHVARD0X! 27515
Muy bien, creo que aun no llega a ser como un tutor al estilo NDS va muy bien la rutina, me estan gustando tus avances, falta poco para tenerla al 100%

Te echaria una mano, pero ando ocupado investigando otras cosas, Saludos!!
#6
Chamber4315♪ 26330
Actualizo!


Gracias a Miksy91 (y cierta domentacion escrita hace mucho tiempo), he podido dar con una de las rutinas que le hacia falta a mi tutor, aquella que se encarga de cargar los movimientos del pokemon seleccionado a la ram y desplegarlos en una caja de texto para asi poder seleccionar que movimiento queremos reemplazar.

Aqui una muestra:


YouTube Video


Con esto cumplo el objetivo de la investigador, el de tener tutores de movimientos genericos, sin embargo esto no sacia mi sed de aprendizaje y no descansare hasta perfeccionar la rutina y tener gran cantidad de tutores igual que en GBA o DS.

Por el momento dejo la documentación empleada.

Rutinas para el move Tutor

---------
Glossary:
---------
CE63 = Alojamiento temporal del ID del Movimiento
D173 = ID del Movimiento en la rutina de carga de nombre (o RAM de scripts)
D005 = Lugar del pokemon en el equipo(00=1ro, ..., 05=6to)
D006 = Alojo temporal del espacio libre para poner el nuevo Movimiento (01=1ro, ..., 04=4to)
D173 = RAM en los Scripts
CF6B = StringBuffer1
CF7E = StringBuffer2
CF91 = StringBuffer3
CFA4 = StringBuffer4
CFB7 = StringBuffer5

call $317B; CopyName1, copia texto del StringBuffer1 al StringBuffer2
call $317E; CopyName2, copia texto de de a hl. Siempre se tiene que especificar antes un ld hl,nn
; para indicar el destino.
call $311A; CopyBytes, copia bc bytes de hl a de
call $31A3; AddNTimes, agrega de a hl igual al numero de a


-----Rutina de carga de nombre-----$1BE920,0x69206F(PKSV)
1.0- Previo necesitamos cargar el ID del movimiento a la RAM
1.1- Se deja un respaldo del ID en $CE63
1.2- Se carga el nombre del move a la StringBuffer1 y se copia a StringBuffer5


ld a,[$D173]// Toma el valor de la RAM
ld [$D151],a
ld [$CE63],a// respaldo del ID
call $373D// GetMoveName, devuelve el nombre en StringBuffer1 ($CF6B) y deja en
// 'de' la direeccion de StringBuffer1 para poder usar CopyName1 o CopyName2
ld hl,$CFB7// StringBuffer5
call $317E// CopyName2
ret



-----Checa compatibilidad-----$1BE940,0x69406F(PKSV)
1.0- Si el tutor es de 'Attract', carga una rutina extra.
1.1- Compatible = (RAM $01)
No Compatible = (RAM $00)

ld a,[$CE63]
cp a,$D5// comprueba si el tutor es de Attract
jr z,@attract
@next
ld a,[$D173]
ld b,a
ld de,$69E0//@noTMHMPkmnTable-1
@loop4
ld a,[de]
inc de
cp a,b
jr z,@NoCompatible
cp a,$FF
jr nz,@loop4
ld a,$1
ld [$D173],a
ret
@NoCompatible
xor a,a
ld [$D173],a
ld hl,$6B00// @UnknownText1
call $0F5E// PrintText
ret
@attract// rutina que comprueba que el pokemon tenga sexo
ld a,[$D004]
cp a,$97// mew queda excluido
jr z,@next
dec a
call @getGender
cp a,$FF
jr z,@NoCompatible
jr nz,@next

@getGender
push hl
push de
ld hl,$5B18// pointer del gender ratio del primer pokemon
ld bc,$0020// longitud en base stats
call $31A3// AddNTimes
ld a,$14// Bank
call $3128// GetFarByte, recupera un byte de ZZ:YYXX (a:hl) y lo devuelve en a, en este caso el PP
pop de
pop hl
ret

$1BE9E0
@noTMHMPkmnTable-1
0A - Caterpie
0B - Metapod
0D - Weedle
0E - Kakuna
81 - Magikarp
84 - Ditto
C9 - Unown
CA - Wobbuffet
EB - Smeargle


$1BEB00
@UnknownText1(PKSV)
= Lo siento, pero\ntu
text-ram 0xCF91
= \lno puede aprender\l
text-ram 0xCFB7
= !\e

; codigo para copiar en HEX
0 139 174 127 178 168 164 173 179 174 244 127 175 164 177 174 79 179 180 127 80 1 145 207 0 85 173 174 127 175 180 164 163 164 127 160 175 177 164 173 163 164 177 85 80 1 183 207 0 231 87



-----Comprobar que no conosca el movimiento-----$1BE9C0,0x69C06F(PKSV)
1.0- Previo necesitamos el ID en $CE63
1.1- Checa el movepool del pokemon seleccionado:
NO Conoce = (RAM $00)
Si conoce = (RAM $01)

call $6990//@objetslot ; regresa en hl la direccion del objeto del PKM seleccionado.
ld a,[$CE63]//carga respaldo del ID
ld b,$04
@loop1
inc hl
cp a,[hl]
jr z,@repetido
dec b
jr nz,@loop1
xor a,a//a = $0
ld [$D173],a
ret
@repetido
ld a,$1
ld [$D173],a
ld hl,$6B40//@UnknownText2
call $0F5E//PrintText
ret

$1BEB40
@UnknownText2(PKSV)
= Lo siento, pero\n
text-ram 0xCF91
= \lya conoce\l
text-ram 0xCFB7
= !\e

; codigo para copiar en HEX
0 139 174 127 178 168 164 173 179 174 244 127 175 164 177 174 79 80 1 145 207 0 85 184 160 127 162 174 173 174 162 164 85 80 1 183 207 0 231 87



-----Comprobar si hay espacio-----$1BEA00,0x6A006F(PKSV)
1.0- Comprube si alguno de los 4 slots esta en $0
1.1- Si NO hay espacio libre regresa la RAM a $1
1.2- Si hay espacio libre regresa la RAM a $0 y...
1.3- Guarda un respaldo del slot libre en D006

call $6990//@objetslot;regresa en hl la direccion del objeto del PKM seleccionado.
inc hl//;$DA2B + $1 = first move
ld b,$04
ld c,$01
@loop
ldi a,[hl]
cp a,$00//;da como resultado el propio a sin modificar, si es 0 = set flag Z
jr z,@positivo
inc c
dec b
jr nz,@loop
ld a,$01//;a = $0
ld [$D173],a
ret
@positivo
ld a,$00
ld [$D173],a
add a,c
ld [$D006],a//;pone el no. del slot libre en $D006 para posteriores usos
ret


-----Enseña el movimiento en un espacio libre-----$1BEA30,0x6A306F(PKSV)
1.0- Carga el respaldo de D006 y...
1.1- "Enseña el movimiento"

call $6990//@objetslot
ld a,[$D006]
ld e,a
ld d,00
add hl,de
call $699D//@GetNewMove
ret


-----Reemplaza al jugador con 0x00-----$1BEA40,0x6A406F(PKSV)

ld hl,$8000
ld de,$7F40
ld bc,$270c
jp $0E72



-----Carga de movimientos y Choosing Box-----$1BEA50,0x6A506F(PKSV)
1,0- Copia los movimientos del pokemon seleccionado a D149 (slots del oponente en batalla)
1.1- Despliega una caja de seleccion del movimiento a reemplazar

call $6990//@objetslot
inc hl
ld bc,$0004
ld de,$D149
call $311A// CopyBytes
ld hl,$C3CD
ld b,$08
ld c,$0D
call $0EEF// textbox; Draw a text box width c height b at hl
call $3456// funcion de pantalla
call $3546// funcion de pantalla
ld hl,$C3F7
ld a,$28
ld [$D0D3],a
ld a,$20
call $2E49//call Predef
ld a,$04
ld [$CED8],a
ld a,$06
ld [$CED9],a
ld a,[$CFE3]
inc a
ld [$CEDA],a
ld a,$01
ld [$CEDB],a
ld [$CEE0],a
ld [$CEE1],a
ld a,$03
ld [$CEDF],a
ld a,$20
ld [$CEDC],a
xor a,a
ld [$CEDD],a
ld a,$20
ld [$CEDE],a
ld hl,$7BFA
ld a,$09
rst $8
ret

$27BFA//unica rutina fuera del banco
call $4255
call $4141
ret



-----Escribe el nuevo movimiento segun la opcion seleccionada-----$1BEAC0,0x6AC06F(PKSV)
1,0- Carga el valor elegido de CEE0 y...
1.1- Escribe el nuevo movimiento.


ld hl,$D148
ld a,[$CEE0]//Seleccion del menu
ld e,a
ld d,$00
add hl,de
ld a,[hl]
ld [$D151],a
call $373D// GetMoveName, devuelve el nombre en StringBuffer1 ; $CF6B
ld hl,$CFA4//StringBuffer4
call $317E//CopyName2
call $6990//@objetslot
ld a,[$CEE0]//Seleccion del menu
ld e,a
ld d,$00
add hl,de
call $699D//@GetNewMove
ret



----- Subrutinas -----
; encontrar movimientos del pokemon seleccionado

$1BE990//; call $6990
@objetslot
ld hl,$DA2B//; objeto del primer pokemon (uno antes de los movimientos)
ld a,[$D005]//; no. de pokemon seleccionado 1ro=$00, 2do=$01...
ld bc,$0030//; longitud de los datos del pokemon
call $31A3//; AddNTimes
ret

$1BE99D
@GetNewMove//; call $699D
ld a,[$CE63]
ld [hl],a
ld de,$0015
add hl,de
dec a
call @getPP
ld [hl],a
ret
@getPP//; call $69AB
push hl
push de
ld hl, Moves + MOVE_PP; pointer de los moves + $5, en mi caso ld hl,$5505
ld bc, Move2 - Move1 ; ld bc,$0007 longitud de los moves
call $31A3; AddNTimes
ld a,BANK(Moves) ; en mi caso $26
call $3128; GetFarByte, recupera un byte de ZZ:YYXX (a:hl) y lo devuelve en a, en este caso el PP
pop de
pop hl
ret




Para los que no se les da el ASM, he creado un parche para que puedan probar el tutor. El parche hace 3 modificaciones:



Una vez aplicado el parche no es necesario cargar todo el script en cada NPC, ya que he desarrollado un sistema en el que solo tienes que usar 7 bytes para cada tutor. Esta es la sintaxis que usaremos en PKSV para cada caso:

#org 0xXXXXXX
'-----------------------------------
faceplayer
loadvar 0xD5
3jump 0x6B836F





Con estos sencillos pasos podremos hacer todo lo mostrado en los vídeos.

La investigación sigue, ya lo único que hace falta es que se muestre la compatibilidad con el tutor en el menú del equipo, llegando a es punto creo que podre dar por finalizada la investigación, mientras tanto, queda el tema abierto.

DESCARGA DEL PARCHE

Saludos y hasta la proxima!
#7
WiZaRD 25635
waao compadre . tu si que eres tremendo en el arte del hack , no cabe duda que eres maestro de maestros xD siempre sorprendiendonos con las novedades , a este paso no dudo que también implementaras la rutina de las megae voluciones , ya casi dominas el sistema ASM cosa que no es facil , mis mas sinceras felicitaciones y mis respetos compadre , eres grande, respecto al parche es compatible con cualquier room aun asi contenga los demas parches ya mostrados por ti ?
nuevamente felicidades !!!!
#8
Chamber4315♪ 26330
Muchas gracias por las flores Wizard.

En este caso si, la compatibilidad es con todos los roms de GBC, debido a que las rutinas son TOTALMENTE independientes de cualquier otra funcion del juego, solo como mencione antes, revisa que los offsets mensionados no tengas informacion (en $27BFA y de $1BE920 a 1BEE70).

Quizas lo que pueda llegar a fallar en roms diferentes a GOLD es que las 3 letras extras de la fuente no se carguen (o se dañen), en caso de ser asi, es facil reparalo.
#9
WiZaRD 25635
Pregunta [MENTION=26330]Chamber[/MENTION] , mencionas que para que enseñe el movimiento (el tutor ) pide un HEART SCALE , has modificado algún ítem en el parche ? algún terusama ? o se tendrá que hacer manualmente ? , respecto al parche , una vez aplicado haces mención que tenemos que cargar el comando de movimientos en la npc , pero ha que npc tendremos que cargar y cuantos nps hay con el scrip para así modificar-lo ! .
gracias por la atención y mas aun por las respuestas :D...
#10
Chamber4315♪ 26330
[MENTION=25635]WiZaRD[/MENTION]:

No, en el parche no se modifica ningun item, pero para que funcione bien el script debes modificar el item 0x74 (teru-sama) para convertirlo en el HEART SCALE.

Una vez aplicado el parche cambias el script del NPC por:

faceplayer
loadvar 0xD5
3jump 0x6B836F

... de esta manera se carga automaticamente el script principal alojado en $1BEB80 (segun recuerdo).

Igualmente te dejo la descargar del script principal por si lo quieres modificar.

Link
#11
WiZaRD 25635
Gracias por eso [MENTION=26330]Chamber[/MENTION] , pero aun no me respondes... ha cuantos tutores se les puede poner el scrip? , hay un limite de tutores o puedes poner las que quieras? osea cuantos NPC estarían disponibles , podría ser cualquier NPC ? o ya hay algunos definidos ! y cuales son esos NPC en el caso de que ya estén designados ?
#12
Chamber4315♪ 26330
Lo siento, es que no te entendia [MENTION=25635]WiZaRD[/MENTION]

Tu puedes poner este tutor a todos los NPC del juego si gustas, no tiene limite, pero como los movimientos que se enseñan no tienen restricciones es recomendable que solo uses maximo 11 con los siguientes movimientos:


#13
WiZaRD 25635
Iniciado por Chamber
Lo siento, es que no te entendia [MENTION=25635]WiZaRD[/MENTION]

Tu puedes poner este tutor a todos los NPC del juego si gustas, no tiene limite, pero como los movimientos que se enseñan no tienen restricciones es recomendable que solo uses maximo 11 con los siguientes movimientos:


  • Curse
  • Double Team
  • Frustration
  • Hidden Power
  • Mimic
  • Protect
  • Rest
  • Return
  • Sleep Talk
  • Substitute
  • Toxic


entonces puedes poner ha cualquier NPC o un nuevo NPC en el game verdad ? respecto a los ataques , tiene que ser necesariamente los que mencionas o puede ser cualquier otro , según desicion de cada uno ?
#14
Chamber4315♪ 26330
Iniciado por WiZaRD
entonces puedes poner ha cualquier NPC o un nuevo NPC en el game verdad ? respecto a los ataques , tiene que ser necesariamente los que mencionas o puede ser cualquier otro , según desicion de cada uno ?


Si, cualquier NPC se puede convertir en un tutor de movimientos, ya que lo que importa es el script.

Debido a que no hay limitantes (aun) sobre que pokemon aprende "x" ataque, si se te ocurre poner un tutor de Draco Meteor, TODOS los pokemon aprenderian Draco Meteor, por eso el titulo del tema es "tutor de movimentos genericos", osea, aquellos movs. que los aprenden "todos" los pokemon (con excepción de caterpie, magikarp, ditto y similares)
#15
WiZaRD 25635
Gracias por la aclaración [MENTION=26330]Chamber[/MENTION] , solo quería saber eso , y no pienso poner ataques como lo que dices , seria desastroso , jejej gracias compa :D