[ASM][FR] ¡Sistema de Scripts Periódicos!

Avisos


Like Tree7Gracias
  • 7 Post By Turambar
Respuesta
 
Herramientas Desplegado
  #1  
09/04/2019
Predeterminado [ASM][FR] ¡Sistema de Scripts Periódicos!
[ASM][FR] ¡Sistema de Scripts Periódicos!

Para comprender y llevar a cabo este tutorial se requieren de unos conociemientos de ASM suficientes. El tutorial será muy técnico y en ningún momento se explicará nada que no sea relativo al tema en concreto.

Esto viene a raíz de un tema de Pokeco de FBI: https://www.pokecommunity.com/showpo...&postcount=309

En la ROM de Pokemon Fire Red en el offset 0x0805486C encontramos esta función interna del propio juego, se trata ni más ni menos que la rutina que cumple la función de actualizar el reloj interno:

Código:
ROM:0805486C                 PUSH    {LR}
ROM:0805486E                 LDR     R0, =time_something @ this is 2 when the game-time is beyond 999:59
ROM:08054870                 LDRB    R0, [R0]        @ this is 2 when the game-time is beyond 999:59
ROM:08054872                 CMP     R0, #1
ROM:08054874                 BNE     loc_80548C4
ROM:08054876                 LDR     R2, =saveblock2_trainerdata
ROM:08054878                 LDR     R0, [R2]
ROM:0805487A                 LDRB    R1, [R0,#0x12]  @ frames
ROM:0805487C                 ADDS    R1, #1          @ frame++
ROM:0805487E                 MOVS    R3, #0
ROM:08054880                 STRB    R1, [R0,#0x12]
ROM:08054882                 LDR     R1, [R2]
ROM:08054884                 LDRB    R0, [R1,#0x12]
ROM:08054886                 CMP     R0, #59
ROM:08054888                 BLS     loc_80548C4
ROM:0805488A                 STRB    R3, [R1,#0x12]
ROM:0805488C                 LDR     R0, [R2]
ROM:0805488E                 LDRB    R1, [R0,#0x11]  @ sec
ROM:08054890                 ADDS    R1, #1          @ sec++
ROM:08054892                 STRB    R1, [R0,#0x11]
ROM:08054894                 LDR     R1, [R2]
ROM:08054896                 LDRB    R0, [R1,#0x11]
ROM:08054898                 CMP     R0, #59
ROM:0805489A                 BLS     loc_80548C4
ROM:0805489C                 STRB    R3, [R1,#0x11]
ROM:0805489E                 LDR     R0, [R2]
ROM:080548A0                 LDRB    R1, [R0,#0x10]  @ min
ROM:080548A2                 ADDS    R1, #1          @ min++
ROM:080548A4                 STRB    R1, [R0,#0x10]
ROM:080548A6                 LDR     R1, [R2]
ROM:080548A8                 LDRB    R0, [R1,#0x10]
ROM:080548AA                 CMP     R0, #59
ROM:080548AC                 BLS     loc_80548C4
ROM:080548AE                 STRB    R3, [R1,#0x10]
ROM:080548B0                 LDR     R0, [R2]
ROM:080548B2                 LDRH    R1, [R0,#0xE]   @ hours
ROM:080548B4                 ADDS    R1, #1          @ hr++
ROM:080548B6                 STRH    R1, [R0,#0xE]
ROM:080548B8                 LSLS    R1, R1, #0x10
ROM:080548BA                 LDR     R0, =0x3E70000
ROM:080548BC                 CMP     R1, R0
ROM:080548BE                 BLS     loc_80548C4
ROM:080548C0                 BL      sav2_set_gametime_to_max
ROM:080548C4
ROM:080548C4 loc_80548C4:                            @ CODE XREF: gametime_increment+8#j
ROM:080548C4                                         @ gametime_increment+1C#j ...
ROM:080548C4                 POP     {R0}
ROM:080548C6                 BX      R0
ROM:080548C6 @ End of function gametime_increment
Nuestro objetivo será hace un hook allá donde nos interese. Es decir, imaginad que quiero ejecutar una rutina a cada minuto, pues haremos un hook en la parte referente a los minutos, si lo quiero ejecutar cada segundo haremos el hook en la parte de los segundos.

La idea es hacer un hook a una rutina que cumplirá la función de ejecutar las rutinas que nosotros queramos. Para llevar esto a cabo haremos una en la ROM donde cada elemento será un pointer a una rutina que queramos ejectar a cada periodo de tiempo. La tabla termina con un 0xFF FF FF.

La rutina que vaya a analizar la tabla seguirá este algoritmo:

Código:
cargar offset de la primera rutina en la tabla

…

ejecutar rutina

…

ejecutar la siguente, y así hasta ejecutar todas la rutinas

…

instrucciones necesarias para noCrash y volver a la rutina del reloj
La rutina en cuestión es la siguiente:

Código:
.text
.align 2
.thumb
.thumb_func	

main:
	push {r0-r7}
	mov r4, #0x0
	
loop:
	ldr r0, .TABLE	//r0=offset de la tabla
	mov r1, #0x4
	mul r1, r1, r4
	add r0, r0, r1	//r0=offset de la rutina a ejecutar
	ldr r0, [r0]
	mov r1, r0
	lsr r1, r1, #0x18
	cmp r1, #0xFF	//comprobar final de la tabla
	beq noCrash
	bl linker	//saltar al label para ejecutar la rutina
	add r4, r4, #0x1	//contador de la tabla +1
	b loop
	
linker:
	bx r0
	

noCrash:

//instrucciones para no crashear el juego

linker:

	bx r0

end:
	pop {r0}
	bx r0	//volver a la rutina donde hemos hecho el hook

.align 2

.TABLE:
	.word 0x8[offset del primer elemento de la tabla, no hacer +1]

Doy por hecho que el que esté leyendo este tutorial sabe como hacer un hook, pero bueno, si no os apetece buscar un sitio donde hacer el hook os recomiendo estos offsets:

• Hook en frames: 0x54880
• Hook en segundos: 0x54894
• Hook en minutos: 0x548A8

Entiendo que el tutorial no es fácil de seguir sin conocimientos previos de ASM, pero bueno, si algún día me apetece hacerlo más comprensible para un mayor segmento de usuarios lo haré.

Como ejecutar un script

Simplemente seguid este otro tutorial, y poned en la tabla el offset donde hayais compilado la rutina.

Personalizar el tiempo de periodo

No es algo que haya que explicar pero bueno. Mi recomendación es usa runa flag para activar vuestro script y usar una variable como contador, es decir, un script activará una flag y seteará un valor como contador. Os recomiento meter esto como script de gatillo o de nivel.

Código:
#dynamic 0x800000

#org @start
lock
setflag 0x(número de flag para activar o no el script)
setvar 0x( variable a usar como contador) 0x0
setvar 0x( variable que determina el periodo) 0x(valor del periodo)
release
end
El script que queramos que se ejecute debe empezar así:

Código:
#dynamic 0x800000

#org @start
lock
checkflag 0x(flag antes determinada)
if 0x1 got  @CheckTime
release
end

#org  @CheckTime
comparevars 0x(número de variable que hace de contador) 0x(numero de variable que determina el periodo)
if 0x0 goto @end
setvar 0x(contador) 0x0
goto @main


#org @end
addvar 0x(variable del contador) 0x1
release
end

#org @main
(aquí va el script)
Cualquier duda preguntad
Respuesta

Herramientas
Desplegado

Permisos para publicar mensajes
No puedes crear nuevos temas
No puedes responder mensajes
No puedes subir archivos adjuntos
No puedes editar tus mensajes

Los BB code están Activado
Los Emoticones están Activado
El código [IMG] está Activado
El Código HTML está Desactivado
Trackbacks are Activado
Pingbacks are Activado
Refbacks are Desactivado



Extra
Estilo clásico
La franja horaria es GMT +1. Ahora son las 12:35.