25952-\[Investigacion-GBC]Tutor_de_movimientos_para_G\\S
#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!