Thank you, so, what have I done to get this working: I injected some code in the function that is called to get random encounters. I pasted this code over the code that checks for the frank horrigan encounter. The code I pasted do the following:
- get a script identifier for obj_dude
- executes the script
- get the gvar's value
- if it's -1, do what the prog usually does
- else do what's needed to load the map
The function that executes the script checks if you're on a map, so I also had to crack this.
In the encounter function, there's two jumps to the code I replaced, to return true, I had to redirect them.
Now, the code (not very easy to understand I know) that I injected:
Code:
; asmsyntax=fasm
format binary
use32
; functions called
exec_script_proc=0x4a4810
get_gvar=0x443c68
set_gvar=0x443c98
scr_set_dude_script=0x4a4f90
; locations used
bye=0x4c0bd4
;continue=0
; variable accessed
obj_dude_ptr=0x6610b8
mapposX=0x672e0c
mapposY=0x672e10
; constants
drop_proc=5
gvar_encounter=695
org 0x4C06AA
call scr_set_dude_script ; inits obj_dude's script
mov edx, drop_proc
mov eax, [obj_dude_ptr]
mov eax, [eax+0x78] ; gets obj_dude's script id
call exec_script_proc ; executes obj_dude's script function drop_p_proc
mov eax, gvar_encounter
call get_gvar
inc eax ; check if gvar_encounter is set
jz continue
mov ebx, eax
dec ebx
cdq
dec edx
mov ecx, edx
mov eax, gvar_encounter
call set_gvar ; set the gvar_encounter to -1
lea eax, [0x672e4c]
;mov dword [0x672e4c], ecx
mov dword [eax], ecx ; must be -1
;add ecx, 2
inc ecx
inc ecx
;mov dword [0x672e04], ecx
mov dword [eax-0x48], ecx ; must be 1
;cmp dword [0x672e64], ecx
cmp dword [eax+0x18], ecx ; does the player have the car?
jnz @f
;mov edx, 0x672e68
lea edx, [eax+0x1C]
call 0x4c59a4
@@:
mov eax, ebx
call 0x482b34 ; loads the map
;xor eax, eax
inc eax
jmp 0x4c0624 ; the end
continue:
lea ebx, [esp+0xac] ; if gvar_encounter not set, do what the prog is supposed to do
mov edx, [mapposY]
mov eax, [mapposX]
call 0x4c3f00
mov edi, [esp+0xac]
inc edi
jnz bye
; taille max 129 octets
What is at the address where I jump when I'm done is some code to return true, I didn't have enough room to fit a far jump at this place...
To be able to do that, I had to do some "quick and dirty" reverse engineering: finding what might be useful and how it seems to work without looking too deep into the code.
Now, here are the instructions for patching the exe:
0xb0aaa: the code I pasted (assembled with fasm)
0x94c26: EB
0xb0fa1: EB 24
0xb0f0f: B4 00 00 00
0xb0a24: 40 81 c4 c0 00 00 00 5d 5f 5e 5a 59 5b c3
Well, this was the first shot for having scripts on the map, I think I might be able to remove the gvar and use load_map instead, it would be a cleaner hack. I have some clues on how to do it, i'll try it when i'll have some time.
BTW what disassembler you use? IDA?
Yep, IDA, it's hard to imagine some reverse engineering without this wonderful disassembler
If there's any questions, i'll try to answer them.