Few things about Mini Games Patcher / debug info

  • Thread starter Thread starter dziugo
  • Start date Start date
Status
Not open for further replies.
D

dziugo

Guest
If you're unfamiliar with MGP, check this

Ok... first, the debug info from patching the ff7.exe ver 1.00.
Code: [Select]
Code:
1) Initial file analysis.Free space in text segment (info by image section header): 0xcbNeeded free space: 0xffNot enough free space. Let's see if we can get some more...Available free space: 0xacbEnlarging the segment by: 0x200Updated segment raw pointer at: 0x1d8 New value: 0x3aac00Updated segment raw pointer at: 0x200 New value: 0x3ae200Updated segment raw pointer at: 0x228 New value: 0x58c800Updated segment raw size at: 0x1b0 New value: 0x3aa800Analysing text segment...Checking free space... Offset: 0x3aa935 Free space: 0x2cbDone2)Searching for references.highway_init Raw: 0x24f63d Offset: 0x65023dhighway_main Raw: 0x24f2e2 Offset: 0x64fee2snowboard_main Raw: 0x31828f Offset: 0x718e8fget_actual_cc Raw: 0x25f240 Offset: 0x65fe40calculate_cc Raw: 0x25f270 Offset: 0x65fe70convert_cc_to_float Raw: 0x25f2fd Offset: 0x65fefdframe_cap Raw: 0x900 Offset: 0x401500 Raw: 0x1acd5 Offset: 0x41b8d5 Raw: 0x1f4016 Offset: 0x5f4c16 Raw: 0x237856 Offset: 0x638456 Raw: 0x2379c5 Offset: 0x6385c5 Raw: 0x2c2eda Offset: 0x6c3ada Raw: 0x341da4 Offset: 0x7429a4 Raw: 0x36f276 Offset: 0x76fe76 Raw: 0x381f91 Offset: 0x782b91 Raw: 0x39d57b Offset: 0x79e17bextra_call Virtual address: 0x675c8b Raw offset: 0x27508bimm_benchmark Immediate: 0xda4228imm_highway Immediate: 0xd76fe4imm_snowboard Immediate: 0xdc9218frame_cap 0x381f91imm_old_cc Immediate: 0xe65930imm_actual_cc Immediate: 0xe65920imm_cc_per_frame Immediate: 0xe65938Done3)Preparing the output file.Allocating space at: 0x3aa935 amount of space allocated: 0x5cAllocating space at: 0x3aa991 amount of space allocated: 0x22Allocating space at: 0x3aa9b3 amount of space allocated: 0x41Allocating space at: 0x3aa9f4 amount of space allocated: 0x40Inserted a new call/jmp, destination: ffeb48f9Inserted a new call/jmp, destination: ffeb4913Inserted a new call/jmp, destination: ffeb4994Inserted a new immediate, destination: e65920Inserted a new immediate, destination: e65930Inserted a new immediate, destination: e65920Inserted a new immediate, destination: e65938Inserted a new immediate, destination: e65920Inserted a new immediate, destination: e65930Inserted a new immediate, destination: e65924Inserted a new immediate, destination: e65934Inserted a new immediate, destination: da4228Inserted a new immediate, destination: e65938Inserted a new call/jmp, destination: ffeb486cInserted a new call/jmp, destination: ffffffb5Inserted a new call/jmp, destination: ffffff51Inserted a new call/jmp, destination: ffea48faInserted a new immediate, destination: d76fe4Inserted a new immediate, destination: d76fe4Inserted a new immediate, destination: e65930Inserted a new immediate, destination: d76fe4Inserted a new call/jmp, destination: ffeb482dInserted a new call/jmp, destination: ffffff76Inserted a new call/jmp, destination: ffffff12Inserted a new call/jmp, destination: fff6d865Inserted a new immediate, destination: dc9218Inserted a new immediate, destination: dc9218Inserted a new immediate, destination: e65930Inserted a new immediate, destination: dc9218Wrote: 0x5c bytes at offset: 0x3aa935Wrote: 0x22 bytes at offset: 0x3aa991Wrote: 0x41 bytes at offset: 0x3aa9b3Wrote: 0x40 bytes at offset: 0x3aa9f4Inserted a new jmp at: 24f2e7 jmp destination: 15b6c9Inserted a new jmp at: 318292 jmp destination: 9275fLast non-nop byte is at: 0x3aaa33 Size of image: 0x3aa634Updated segment virtual size at: 0x1b0 New value: 0x3aa634 Raw: 0x547be0Applying snowboard patch.Done4)Saving file.Done

The debug info contains four headers:
Code: [Select]
Code:
1) Initial file analysis.2) Searching for references.3) Preparing the output file.4) Saving file.

Let's take a look at the first one... What the patcher does in it's first stage? Basically, it checks, if the amount of free space in the *.exe file is high enough (first release of my patch needs at least 0xFF bytes). If it's not it'll try to enlarge that area a bit... It requires writing new values into the file header. If the file can be enlarged, the patcher does it (the file will be a little bit bigger after patching). When the first step is successfull...

Patcher moves to the second stage... It will search for all needed functions in the text-segment of the exe file... Here is the full list of the functions:
Code: [Select]
Code:
highway_init - function which is called to prepare the HighwayMiniGame (needed only to get the extra_call function)highway_main - function which is responsible for creating each frame of the HighwayMiniGame (we'll do some modifications here)snowboard_main - we'll do some modifications here too :Pget_actual_cc - function gets a memory address, and writes there the rdtsc results...calculate_cc - function gets three memory addresses, subtracts the value in the second one from the value in the first one and writes the result to the third one :Pconvert_cc_to_float - gets memory address and converts a hex-value stored there into the float-variable, stores it on the FPU's stackframe_cap - ok... here ARE the functions responsible for frame-limiting of some modules of ff7 (field, menu, battle, submarine...) - explained belowextra_call - function returns the imm_benchmark value using EAX registry - we aren't exactly searching for this... we get the address from the highway_init function

Here is the first question: Can't we just use some of the existing frame-limiters? We can, but since they aren't optimized at all, and required some pre-call modifications... I decided to write my own (basing on the existing one of course :P). Then why do we search for those? We don't need the code, but we need some safe variables. By safe, I mean the variables which could be used freely. If we're playing HighwayMiniGame then we CAN use SubMarine variables, and we will :). We'll unpack the required variables from some function and hardcode it into our functions. Which function will we hijack? The 9th is the SubMarine frame-limiter and I think it's the best choice (you can always pick some other function, use the -hijack switch when using my patcher).

Immediates used when preparing the code:
Code: [Select]
Code:
imm_benchmark - value which stores the address of some MAIN variables... if we add 0x30 to this pointer we'd get a pointer to a value which contains the speed of our CPU in clock cycles (very importand value - VIV :P)imm_highway - value which contains 1 if the HighwayMiniGame is running - we'll hijack that value too :P see belowimm_snowboard - same as imm_highway, just refers to SnowboardMiniGameframe_cap - raw_pointer to our hijacked frame-limiting functionimm_old_cc - stores the old clock cycles countimm_actual_cc - stores the actual clock cycles countimm_cc_per_frame - imm_benchmark divided by the frame-rate - clock cycles per frame

After that, you can tell if the chosen frame-limiting function was a good one :P. Simply look at the imm_cc variables. If they are something like 0x<six digits here> and are similar, it was a good choice.

If the second part was successfull, patcher moves to the third section...

It'll "allocate" the free space for functions we need to inject into the *.exe file. If it happens, that there is enough free-space (to put our code) in the middle of the text segment it will do that (jumps at the beginning of each function will do the job if it was just a NOP-ed field inside of some bigger functions).

Functions to be injected:
Code: [Select]
Code:
frame_cap_main - function which will pause our game if the frame was processed to fastframe_cap_init - function which will fill the imm_cc values with the initial datahighway_hijack - code which will handle calling the frame_cap_main and frame_cap_init functionssnowboard_hijack - same as above
We will use the imm_highway and imm_snowboard variables to check, if the frame_cap_init was called already. Since these values are BOOLEANS, we will change some code to use (for example) TEST EAX, 0x01 instead of TEST EAX, EAX. Doing that will allow us to use other bits (we'll take the second one :P). If our bit isn't set we call the frame_cap_init and set that bit. Simple isn't it?

We'll do the necessary CMPs in our hijack_functions and use the CMP field in the highway_main and snowboard_main to to our hijack_ones...

When the patch is completed, it's written into the file. At the end the patcher checks if SnowboardMiniGame needs patching (don't know if it's the only problem with that minigame...) and do that if necessary...

When the third step is completed successfully, the patcher creates a new patched file... And that's it... If you read that, you'll know that this patch is somehow flexible. It'll accept ANY version of ff7 as long as the needed functions aren't heavy-modified. If there are any questions/comments (there won't be any :P that's for sure) post them below.

dziugo
 
Status
Not open for further replies.
Back
Top