Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


FF7 Auto-Assembler Help

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Tutorials -> Auto Assembler tutorials
View previous topic :: View next topic  
Author Message
MechaCrab
How do I cheat?
Reputation: 0

Joined: 30 Dec 2015
Posts: 5

PostPosted: Thu Dec 31, 2015 12:49 am    Post subject: FF7 Auto-Assembler Help Reply with quote

Hey guys, hoping you could help. Had a quick question. So I'm trying to create a multiplier for experience and AP points, and I'm able to find the addresses for the values easy enough through memory viewer. I've been able to cobble a usable multiplier code using your tutorials, however I'm having a problem when I try to toggle the script off, as the game crashes whenever I do. The code in question currently multiplies any experience gained in battle by a factor of two. This is what I've got so far:

Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
shl ecx,1
sub ecx,[FF7_EN.exe+59E2C0]//place your code here

originalcode:
mov [FF7_EN.exe+59E2C0],ecx

exit:
jmp returnhere

"FF7_EN.exe"+3154B:
jmp newmem
nop
returnhere:


 
 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"FF7_EN.exe"+3154B:
mov [FF7_EN.exe+59E2C0],ecx
//Alt: db 89 0D C0 E2 99 00


If anybody could help me figure out what's wrong, it would be very much appreciated, as I'm clueless.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 137

Joined: 06 Jul 2014
Posts: 4250

PostPosted: Thu Dec 31, 2015 10:24 am    Post subject: Reply with quote

I'm not sure either; although, I might be missing something obvious.

A few questions:
What's with that sub ecx,[...]? Why have it there?
I'm guessing FF7_EN.exe+59E2C0 is the address of your experience?
Could you post the ASM around the instruction "FF7_EN.exe"+3154B? Either an image or copying the instructions would work. To do so, right click in CE's disassembler, select "Go to address", paste that address in, go up a few instructions, select a few via shift-click, right click on them, select "Copy to clipboard -> Bytes+Opcodes", and post that here.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
MechaCrab
How do I cheat?
Reputation: 0

Joined: 30 Dec 2015
Posts: 5

PostPosted: Thu Dec 31, 2015 12:53 pm    Post subject: Reply with quote

ParkourPenguin wrote:
I'm not sure either; although, I might be missing something obvious.

A few questions:
What's with that sub ecx,[...]? Why have it there?
I'm guessing FF7_EN.exe+59E2C0 is the address of your experience?
Could you post the ASM around the instruction "FF7_EN.exe"+3154B? Either an image or copying the instructions would work. To do so, right click in CE's disassembler, select "Go to address", paste that address in, go up a few instructions, select a few via shift-click, right click on them, select "Copy to clipboard -> Bytes+Opcodes", and post that here.


Code:
FF7_EN.exe+3153F - 8B 0D C0E29900        - mov ecx,[FF7_EN.exe+59E2C0]
FF7_EN.exe+31545 - 03 88 38B19A00        - add ecx,[eax+FF7_EN.exe+5AB138]
FF7_EN.exe+3154B - 89 0D C0E29900        - mov [FF7_EN.exe+59E2C0],ecx
FF7_EN.exe+31551 - 8B 55 FC              - mov edx,[ebp-04]
FF7_EN.exe+31554 - 83 C2 04              - add edx,04

EAX=000001A0
EBX=7FFDE000
ECX=0000001B
EDX=00000010
ESI=01053B58
EDI=00F6F2D0
ESP=001950E0
EBP=00195120
EIP=00431551


Here we go, I hope this is what you needed. These are the instructions which write to the address of the post-battle results screen for experience received. Another set of instructions also write to this address, which I will show below:

Code:
FF7_EN.exe+1C6F9F - 83 EC 08              - sub esp,08
FF7_EN.exe+1C6FA2 - C7 45 F8 00000000     - mov [ebp-08],00000000
FF7_EN.exe+1C6FA9 - C7 05 C0E29900 00000000 - mov [FF7_EN.exe+59E2C0],00000000
FF7_EN.exe+1C6FB3 - C7 05 C4E29900 00000000 - mov [FF7_EN.exe+59E2C4],00000000
FF7_EN.exe+1C6FBD - C7 05 C8E29900 00000000 - mov [FF7_EN.exe+59E2C8],00000000

EAX=00000020
EBX=7FFDE000
ECX=00000000
EDX=00000020
ESI=01053B58
EDI=00F6F2D0
ESP=001950D0
EBP=001950D8
EIP=005C6FB3


This set of instructions is executed after all monsters on-screen are defeated, during the "victory pose", and takes place before the first code I listed. I wasn't sure whether to include this or not, as I'm not sure what these instructions do exactly, but I thought it couldn't hurt to post as well.

As for the "sub" command in my code, it was my solution to how this game calculates experience in battle. A normal shl, while working fine on just one enemy, gave me more than double experience when I encountered multiple enemies. This is because the game begins calculating experience the moment a monster is defeated, since a player may "run" from a battle before the entire fight is concluded. The equation thus becomes (Base + Earned Exp) = EXP earned after battle, where if two monsters of 20exp each are defeated, it would look like:
(0+20) = 20
(20+20) = 40
40 = Exp

My shl code by itself created the equation ((Base + Earned)x2) = 2base +2earned, which gave me much higher exp than I was asking for. The experience resulted from my new equation:
((0+20)x2) = 40
((40+20)x2) = 120
120 = Exp

Thus the need to subtract the base, or ((Base + Earned)x2) - Base = Base +2earned, which was what I needed, "Base" being [FF7_EN.exe+59E2C0].

Thank you for answering my post, and I hope that you can help me in solving this last hurdle.


EDIT: Whoa, hold on. So I double checked, and the experience code toggle works just fine. The problem is actually in my AP and GIL modifiers, which I modeled on the EXP modifier. It's very strange, because what appears to be happening is when I disable these scripts, it puts the original code back into place, BUT for some reason changes several bits of instruction immediately after, which I assume result in the crash. I'll try to list a before/after for both of the problem scripts.

2x AP:
Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,1024)
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
shl eax,1
sub eax,[FF7_EN.exe+59E2C4]//place your code here

originalcode:
mov [FF7_EN.exe+59E2C4],eax

exit:
jmp returnhere

"FF7_EN.exe"+3157D:
jmp newmem
returnhere:


 
 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"FF7_EN.exe"+3157D:
mov [FF7_EN.exe+59E2C4],eax
//Alt: db A3 C4 E2 99 00


Before Injection:
Code:
FF7_EN.exe+31576 - A1 C4E29900           - mov eax,[FF7_EN.exe+59E2C4]
FF7_EN.exe+3157B - 03 C2                 - add eax,edx
FF7_EN.exe+3157D - A3 C4E29900           - mov [FF7_EN.exe+59E2C4],eax
FF7_EN.exe+31582 - 8B 4D FC              - mov ecx,[ebp-04]
FF7_EN.exe+31585 - 83 C1 04              - add ecx,04

EAX=00000003
EBX=7FFDE000
ECX=009A900C
EDX=00000003
ESI=010C3B58
EDI=00F6F2D0
ESP=001950E0
EBP=00195120
EIP=00431582


After injection:
Code:
FF7_EN.exe+31576 - A1 C4E29900           - mov eax,[FF7_EN.exe+59E2C4]
FF7_EN.exe+3157B - 03 C2                 - add eax,edx
FF7_EN.exe+3157D - E9 7EEAE4FF           - jmp 00280000
FF7_EN.exe+31582 - 00 4D FC              - add [ebp-04],cl
FF7_EN.exe+31585 - 83 C1 04              - add ecx,04


After Disabling:
Code:
FF7_EN.exe+31576 - A1 C4E29900           - mov eax,[FF7_EN.exe+59E2C4]
FF7_EN.exe+3157B - 03 C2                 - add eax,edx
FF7_EN.exe+3157D - 89 05 C4E29900        - mov [FF7_EN.exe+59E2C4],eax
FF7_EN.exe+31583 - 4D                    - dec ebp
FF7_EN.exe+31584 - FC                    - cld
FF7_EN.exe+31585 - 83 C1 04              - add ecx,04


2x GIL:
Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
shl eax,1
sub eax,[FF7_EN.exe+59E2C8]//place your code here

originalcode:
mov [FF7_EN.exe+59E2C8],eax

exit:
jmp returnhere

"FF7_EN.exe"+31565:
jmp newmem
returnhere:


 
 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"FF7_EN.exe"+31565:
mov [FF7_EN.exe+59E2C8],eax
//Alt: db A3 C8 E2 99 00


Before Injection:
Code:
FF7_EN.exe+3155A - A1 C8E29900           - mov eax,[FF7_EN.exe+59E2C8]
FF7_EN.exe+3155F - 03 82 34B19A00        - add eax,[edx+FF7_EN.exe+5AB134]
FF7_EN.exe+31565 - A3 C8E29900           - mov [FF7_EN.exe+59E2C8],eax
FF7_EN.exe+3156A - 8B 4D DC              - mov ecx,[ebp-24]
FF7_EN.exe+3156D - 33 D2                 - xor edx,edx

EAX=0000001E
EBX=7FFDE000
ECX=0000001B
EDX=000001A0
ESI=01173B58
EDI=00F6F2D0
ESP=001950E0
EBP=00195120
EIP=0043156A


(This second set of instructions is exclusive to GIL, and also happens at the same time. This script I did not modify, but I will include it in case it proves meaningful.)
Code:

FF7_EN.exe+3167C - 0FAF D1               - imul edx,ecx
FF7_EN.exe+3167F - C1 FA 04              - sar edx,04
FF7_EN.exe+31682 - 89 15 C8E29900        - mov [FF7_EN.exe+59E2C8],edx
FF7_EN.exe+31688 - E8 E6AA2900           - call FF7_EN.exe+2CC173
FF7_EN.exe+3168D - C7 45 FC 00000000     - mov [ebp-04],00000000

EAX=00000010
EBX=7FFDE000
ECX=00000010
EDX=0000001E
ESI=01173B58
EDI=00F6F2D0
ESP=001950E0
EBP=00195120
EIP=00431688


After Injection:
Code:
FF7_EN.exe+3155A - A1 C8E29900           - mov eax,[FF7_EN.exe+59E2C8]
FF7_EN.exe+3155F - 03 82 34B19A00        - add eax,[edx+FF7_EN.exe+5AB134]
FF7_EN.exe+31565 - E9 96EAEDFF           - jmp 00310000
FF7_EN.exe+3156A - 8B 4D DC              - mov ecx,[ebp-24]
FF7_EN.exe+3156D - 33 D2                 - xor edx,edx

FF7_EN.exe+3167C - 0FAF D1               - imul edx,ecx
FF7_EN.exe+3167F - C1 FA 04              - sar edx,04
FF7_EN.exe+31682 - 89 15 C8E29900        - mov [FF7_EN.exe+59E2C8],edx
FF7_EN.exe+31688 - E8 E6AA2900           - call FF7_EN.exe+2CC173
FF7_EN.exe+3168D - C7 45 FC 00000000     - mov [ebp-04],00000000


After Disabling:
Code:
FF7_EN.exe+3155A - A1 C8E29900           - mov eax,[FF7_EN.exe+59E2C8]
FF7_EN.exe+3155F - 03 82 34B19A00        - add eax,[edx+FF7_EN.exe+5AB134]
FF7_EN.exe+31565 - 89 05 C8E29900        - mov [FF7_EN.exe+59E2C8],eax
FF7_EN.exe+3156B - 4D                    - dec ebp
FF7_EN.exe+3156C - DC 33                 - fdiv qword ptr [ebx]
FF7_EN.exe+3156E - D2 66 8B              - shl byte ptr [esi-75],cl
FF7_EN.exe+31571 - 91                    - xchg eax,ecx
FF7_EN.exe+31572 - 9E                    - sahf


I hope you'll be able to help me, as right now I'm completely baffled.


Last edited by MechaCrab on Thu Dec 31, 2015 2:08 pm; edited 1 time in total
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 137

Joined: 06 Jul 2014
Posts: 4250

PostPosted: Thu Dec 31, 2015 1:58 pm    Post subject: Reply with quote

Yup, I have no idea why it's crashing when you disable the script. Everything seems fine.
It might be a bug in how CE parses module names in instructions, but I doubt it. You can try putting FF7_EN.exe in quotes to make it more explicit. You should look at your allocated memory to find out if CE assembled your code correctly.

The best way to find out what's wrong is to debug it yourself.

Set a breakpoint (Debug -> Toggle Breakpoint) at the instruction FF7_EN.exe+31545 (the one before where you're writing the jump to). This will stop the game when that instruction is run.

If you do something in-game to trigger the breakpoint (i.e. kill a monster) before enabling the script, you should be able to step through (Debug -> Step) the next couple instructions just fine. You can continue running (Debug -> Run) when you're past the instruction FF7_EN.exe+31551.

Now enable the script, and do something in-game to trigger the breakpoint. This time, you should see a jmp at FF7_EN.exe+3154B. Step into that, and you should see your code. Compare that with what you have written down. If it logically makes sense (i.e. sub ecx,[FF7_EN.exe+59E2C0] may be interpreted as sub ecx, [0099E2C0]), then you're good, and can continue stepping though it until after you reach the jmp back to the instruction FF7_EN.exe+31551. If everything seems fine, then continue running.

Now disable the script. I'm assuming it doesn't immediately crash upon disabling the script. Look at the instructions around FF7_EN.exe+3154B again. If everything looks the same as it was before enabling the script, then it should run just fine and nothing should crash.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
MechaCrab
How do I cheat?
Reputation: 0

Joined: 30 Dec 2015
Posts: 5

PostPosted: Thu Dec 31, 2015 2:41 pm    Post subject: Reply with quote

Unfortunately, when I try to establish breakpoints at FF7_EN.exe+3155F (for GIL) and FF7_EN.exe+3157D (for AP), selected one at a time of course, I am unable to successfully run it after I step through, as the game crashes once I click back to the window.

Sorry, I'm quite new at this so I might be doing it wrong, since I assume, being unaltered by my script, the game should continue to run after I've used the Step function past a certain extent.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 137

Joined: 06 Jul 2014
Posts: 4250

PostPosted: Thu Dec 31, 2015 3:08 pm    Post subject: Reply with quote

Nevermind my previous post, that was written without me having seen your edit.

The problem is that there are different ways of translating the mnemonics humans understand (i.e. mov) into the bytes computers understand. More specifically, even though the mnemonic of that instruction is the exact same, CE isn't translating that into bytes the same way as was originally done by the game. It's putting one more byte than is needed, and as such, is overriding part of the next instruction. This subsequently throws numerous instructions after that out of alignment, which will almost certainly crash the game.

To solve this, just write the bytes directly back to that memory address with db. You can probably trust that it'll be the same whenever you restart the process since it's loaded at 0x00400000, so you can do that directly. If it fails or you just want to be save, globalalloc some backup region of memory and use readmem to backup the bytes into there when enabling scripts. Then just use readmem again when disabling the script to read from the backup.

Here's an example of doing it directly with your 2x AP Script:
Code:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,1024)
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
shl eax,1
sub eax,[FF7_EN.exe+59E2C4]//place your code here

originalcode:
mov [FF7_EN.exe+59E2C4],eax

exit:
jmp returnhere

"FF7_EN.exe"+3157D:
jmp newmem
returnhere:




[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"FF7_EN.exe"+3157D:
db A3 C4 E2 99 00
//Alt (Doesn't work; will crash the game): mov [FF7_EN.exe+59E2C4],eax

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
MechaCrab
How do I cheat?
Reputation: 0

Joined: 30 Dec 2015
Posts: 5

PostPosted: Thu Dec 31, 2015 3:45 pm    Post subject: Reply with quote

Thank you! Your first solution worked, and I've tested it with all my scripts. I would have had no idea that was what was causing the problem. I had thought that the mnemonic instructions were always 1:1, and was baffled on why the code wasn't disabling to the proper place, but I guess it isn't always 100% translated correctly as you said.

So what exactly does the db do? Is it just the memory address in bytes instead of assembly language?

Regardless, thank you again very much for helping me. I've learned a lot from my first script.

Edit: Sorry, this is a bit embarrassing, but I would like to give you a positive review for your help. Trouble is I have no idea how to do that on this site.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 137

Joined: 06 Jul 2014
Posts: 4250

PostPosted: Thu Dec 31, 2015 4:08 pm    Post subject: Reply with quote

db ("declare bytes") is a pseudo-instruction that directly writes some bytes to an address. Normally, ASM code is parsed and translated into bytes that are then written to an address, but you can bypass that step and write the bytes yourself if you want to. It's very useful in this case.

A thumbs up icon appears next to a user's reputation when you are signed into an account that has 15 or more posts. But you should also read the FAQ if you haven't already.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Tutorials -> Auto Assembler tutorials All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites