 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
lessthandan How do I cheat?
Reputation: 0
Joined: 20 Jun 2020 Posts: 2
|
Posted: Sat Jun 20, 2020 7:38 pm Post subject: Execute Scripts? |
|
|
Hello - new user here. Trying to get Cheat Engine to work with Final Fantasy V. I found a .CT file that appears to have everything I need, but I'm confused as to how I actually execute the script? Or does it just work on it's own?
See attachment in the Gil Multiplier and EXP Multiplier where it says 10? and 5? That description first read "x?" so I put in "10." No dice. Then I tried "10?" in the event I had to leave the "?" for some reason, but still nothing.
One thing to note is that I went back and enabled "Speedhack" and that seems to work just fine at x2 speed. This leads me to believe that it's not a version issue, but who knows.
| Description: |
|
| Filesize: |
41.25 KB |
| Viewed: |
10508 Time(s) |

|
|
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4706
|
Posted: Sat Jun 20, 2020 8:39 pm Post subject: |
|
|
We can't do much of anything besides guess. Wrong game version? Table author didn't know what they were doing? Injection point hasn't been executed yet? You changed something you shouldn't have? I don't know.
(you did try changing the value and not the description, right? try the first few steps of the CE tutorial if you haven't already)
Post the contents of the scripts for more educated guesses (at least Enable, [Battle Specific], and Gil or EXP scripts).
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
lessthandan How do I cheat?
Reputation: 0
Joined: 20 Jun 2020 Posts: 2
|
Posted: Sat Jun 20, 2020 9:49 pm Post subject: |
|
|
OK: as it turns out, cheats are working. It's the [Battle Specific] cheats that are not working (and it appears to be all of them).
Answers to some of your questions:
1) Looks like I WAS changing the DESCRIPTION and not the actual multiplier value, so thank you for pointing that out.
It appears that there is a float (I assume float = "default" in this case?) value of 4, so I think I can just check off the main line for Gil Multiplier and not check off the "x?" box in the next line.
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
fBattleGilMultiplier:
dd (float)4
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
fBattleGilMultiplier:
dd (float)1
2) It looks like SOMETHING is happening to the gil + exp value. Instead of giving me a "x4" multiplier it's just setting the gil to 0 and the exp to 1 at the end of every battle.
3) .CT file attached.
4)
Enable & Battle Specific Scripts Below:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
aobscan(battleHPReadAOB,8B 73 2C 8B C1)
registersymbol(battleHPReadAOB)
aobscan(battleResultsResetOnBattleStartAOB,C7 81 2C 9A 00 00 00 00)
registersymbol(battleResultsResetOnBattleStartAOB)
///
label(bUndead)
registersymbol(bUndead)
label(bIgnoreMP)
registersymbol(bIgnoreMP)
label(bNoPoison)
registersymbol(bNoPoison)
label(bNoToad)
registersymbol(bNoToad)
label(bNoSleep)
registersymbol(bNoSleep)
label(bNoDead)
registersymbol(bNoDead)
label(bNoOld)
registersymbol(bNoOld)
label(bNoStop)
registersymbol(bNoStop)
label(bNoSilence)
registersymbol(bNoSilence)
label(bNoSlow)
registersymbol(bNoSlow)
label(pBase1)
registersymbol(pBase1)
label(pBattleHeros)
registersymbol(pBattleHeros)
label(pBattleResultsBase)
registersymbol(pBattleResultsBase)
///
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
label(newmem2) //,2048)
label(returnhere2)
label(originalcode2)
label(exit2)
///
newmem: //this is allocated memory, you have read,write,execute access
//place your code here
mov esi,[esp+4c]
mov [pBattleHeros+esi*4],ebx
cmp byte ptr [bNoPoison],1
jne @f
and dword ptr [ebx+100],FFFFFFFB
@@:
cmp byte ptr [bNoToad],1
jne @f
and dword ptr [ebx+100],FFFFFFDF
@@:
cmp byte ptr [bNoSleep],1
jne @f
and dword ptr [ebx+101],FFFFFFDF
@@:
cmp byte ptr [bNoDead],1
jne @f
and dword ptr [ebx+100],FFFFFF7F
@@:
cmp byte ptr [bNoOld],1
jne @f
and dword ptr [ebx+100],FFFFBFFF
@@:
cmp byte ptr [bNoStop],1
jne @f
mov dword ptr [ebx+29c],0
//and dword ptr [ebx+100],FFF7FFFF
@@:
cmp byte ptr [bNoSlow],1
jne @f
and dword ptr [ebx+100],FFFDFFFF
@@:
cmp byte ptr [bNoSilence],1
jne @f
and dword ptr [ebx+100],FFFFFDFF
@@:
cmp byte ptr [bUndead],1
jne @f
cmp dword ptr [ebx+2C],1
jge @f
mov dword ptr [ebx+2C],1
@@:
cmp byte ptr [bIgnoreMP],1
jne originalcode
cmp dword ptr [ebx+34],0
jge originalcode
mov dword ptr [ebx+34],0
originalcode:
mov esi,[ebx+2C]
mov eax,ecx
exit:
jmp returnhere
///
newmem2:
mov [pBattleResultsBase],ecx
originalcode2:
mov [ecx+00009A2C],00000000
exit2:
jmp returnhere2
///
bUndead:
db 0
bIgnoreMP:
db 0
bNoPoison:
db 0
bNoToad:
db 0
bNoSleep:
db 0
bNoDead:
db 0
bNoOld:
db 0
bNoStop:
db 0
bNoSilence:
db 0
bNoSlow:
db 0
pBase1:
dd 0
pBattleHeros:
dd 0
dd 0
dd 0
dd 0
pBattleResultsBase:
dd 0
///
battleHPReadAOB: //"FFV_Game.exe"+14126:
jmp newmem
returnhere:
battleResultsResetOnBattleStartAOB: //"FFV_Game.exe"+11DB8:
jmp newmem2
nop
nop
nop
nop
nop
returnhere2:
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
battleHPReadAOB: //"FFV_Game.exe"+14126:
db 8B 73 2C 8B C1
//Alt: mov esi,[ebx+2C]
//Alt: mov eax,ecx
unregistersymbol(battleHPReadAOB)
battleResultsResetOnBattleStartAOB: //"FFV_Game.exe"+11DB8:
db C7 81 2C 9A 00 00 00 00 00 00
//Alt: mov [ecx+00009A2C],00000000
unregistersymbol(battleResultsResetOnBattleStartAOB)
unregistersymbol(bUndead)
unregistersymbol(bIgnoreMP)
unregistersymbol(bNoPoison)
unregistersymbol(bNoToad)
unregistersymbol(bNoSleep)
unregistersymbol(bNoDead)
unregistersymbol(bNoOld)
unregistersymbol(bNoStop)
unregistersymbol(bNoSilence)
unregistersymbol(bNoSlow)
unregistersymbol(pBase1)
unregistersymbol(pBattleHeros)
unregistersymbol(pBattleResultsBase)
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
aobscan(gilEarnedWriteOnBattleEndAOB,89 83 30 9A 00 00)
registersymbol(gilEarnedWriteOnBattleEndAOB)
aobscan(EXPEarnedWriteOnBattleEndAOB,89 83 2C 9A 00 00 85 C0)
registersymbol(EXPEarnedWriteOnBattleEndAOB)
aobscan(ABPEarnedWriteOnBattleEndAOB,89 83 34 9A 00 00 85 FF)
registersymbol(ABPEarnedWriteOnBattleEndAOB)
///
label(fBattleGilMultiplier)
registersymbol(fBattleGilMultiplier)
label(fEXPMultiplier)
registersymbol(fEXPMultiplier)
label(fABPMultiplier)
registersymbol(fABPMultiplier)
///
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
label(newmem2) //,2048)
label(returnhere2)
label(originalcode2)
label(exit2)
label(newmem6) //,2048)
label(returnhere6)
label(originalcode6)
label(exit6)
///
newmem: //this is allocated memory, you have read,write,execute access
//place your code here
mov [pBattleResultsBase],ebx
mov [ebx+9a30],eax
fild dword ptr [ebx+9a30]
fmul dword ptr [fBattleGilMultiplier]
fistp dword ptr [ebx+9a30]
mov eax,[ebx+9a30]
originalcode:
//mov [ebx+00009A30],eax
exit:
jmp returnhere
///
newmem2:
mov [pBattleResultsBase],ebx
mov [ebx+9a2c],eax
fild dword ptr [ebx+9a2c]
fmul dword ptr [fEXPMultiplier]
fistp dword ptr [ebx+9a2c]
mov eax,[ebx+9a2c]
originalcode2:
//mov [ebx+00009A2C],eax
exit2:
jmp returnhere2
///
newmem6:
mov [pBattleResultsBase],ebx
mov [ebx+9a34],eax
fild dword ptr [ebx+9a34]
fmul dword ptr [fABPMultiplier]
fistp dword ptr [ebx+9a34]
mov eax,[ebx+9a34]
originalcode6:
mov [ebx+00009A34],eax
exit6:
jmp returnhere6
///
fBattleGilMultiplier:
dd (float)1
fEXPMultiplier:
dd (float)1
fABPMultiplier:
dd (float)1
///
gilEarnedWriteOnBattleEndAOB: //"FFV_Game.exe"+C3F3:
jmp newmem
nop
returnhere:
EXPEarnedWriteOnBattleEndAOB: //"FFV_Game.exe"+C4DD:
jmp newmem2
nop
returnhere2:
ABPEarnedWriteOnBattleEndAOB: //"FFV_Game.exe"+C3CB:
jmp newmem6
nop
returnhere6:
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
gilEarnedWriteOnBattleEndAOB: //"FFV_Game.exe"+C3F3:
db 89 83 30 9A 00 00
//Alt: mov [ebx+00009A30],eax
unregistersymbol(gilEarnedWriteOnBattleEndAOB)
EXPEarnedWriteOnBattleEndAOB: //"FFV_Game.exe"+C4DD:
db 89 83 2C 9A 00 00
//Alt: mov [ebx+00009A2C],eax
unregistersymbol(EXPEarnedWriteOnBattleEndAOB)
ABPEarnedWriteOnBattleEndAOB: //"FFV_Game.exe"+C3CB:
db 89 83 34 9A 00 00
//Alt: mov [ebx+00009A34],eax
unregistersymbol(ABPEarnedWriteOnBattleEndAOB)
unregistersymbol(fBattleGilMultiplier)
unregistersymbol(fEXPMultiplier)
unregistersymbol(fABPMultiplier)
|
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4706
|
Posted: Sat Jun 20, 2020 10:45 pm Post subject: |
|
|
I can't see any errors in those scripts. There's some bad coding practice, but nothing that would make it not work.
There are other scripts (possibly hidden) in that table that register the same symbols as the [Battle Specific] script. Don't enable those.
Why are those multipliers set to that value? The scripts set it to 1 or 4, not whatever that number is. Have you tried leaving it at the default value of 4 after the script is enabled?
Some AA scripts require the user to do some action in the game in order for the code it changes to have any noticeable effect.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
happyTugs Cheater
Reputation: 0
Joined: 23 Apr 2020 Posts: 26
|
Posted: Sun Jun 21, 2020 9:16 pm Post subject: Bad practices |
|
|
| Quote: | | There's some bad coding practice |
Out of curiosity (and because the OP has yet to reply), what did you consider bad practice within the script?
The script is not mine if you were wondering.
_________________
This is a block of text that can be added to posts you make. There is a 300 character limit |
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4706
|
Posted: Sun Jun 21, 2020 10:52 pm Post subject: |
|
|
Values aren't aligned (as can be seen in the first screenshot).
There are many jumps that could be using the short form (i.e. jne short @f).
Among other more minor optimizations, that whole @@/cmp/jne/and... section could be more optimized.
None of these things make the script wrong in any way. It doesn't even make the script any measurably slower (probably less than a microsecond per invocation). It's just stuff I see that annoys me.
Still better than the majority of scripts I've seen from other people.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
happyTugs Cheater
Reputation: 0
Joined: 23 Apr 2020 Posts: 26
|
Posted: Mon Jun 22, 2020 12:13 am Post subject: |
|
|
| Quote: | | Values aren't aligned |
So, could this be resolved by declaring each variable to a dword (or qword) and ensuring that each variable is aligned to its respective (4 byte or 8-byte) boundary?
Would you also ensure that each opcode is aligned on a 4-byte boundary as well?
| Quote: | | many jumps that could be using the short form |
From my readings, you would use short form since less bytes would be needed and jumps are relatively small?
One more thing that I have wanted to ask you is what resources would you recommend regarding memory allocations and page sizes since I am still unsure as to how much memory I should allocate (4096, 2048, or even less) in my scripts.
I am currently reading the Intel architecture manual since you have recommended that in your past articles, so perhaps that topic will be covered there.
Thanks for the reply; I have learned a lot from you (and just about everyone here in the forum)!
_________________
This is a block of text that can be added to posts you make. There is a 300 character limit |
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4706
|
Posted: Mon Jun 22, 2020 10:32 am Post subject: |
|
|
You could just put "align 4 90" before the first value:
| Code: | ...
///
align 4 90
fBattleGilMultiplier:
dd (float)1
fEXPMultiplier:
dd (float)1
... | Or use separate allocs for each value:
| Code: | alloc(newmem,2048)
alloc(fBattleGilMultiplier,4)
... |
Instructions don't need to be aligned (in general). There are esoteric cases where it could be advantageous in theory (stackoverflow answer), but the difference is certainly negligible and it isn't worth any concern when hand writing assembly.
"jmp short x" basically means you guarantee the destination x is within 128 bytes of the next instruction. Such an instruction takes up 2 bytes instead of 5 (sometimes 3 instead of 6) and is probably negligibly faster.
For the most part, memory is organized by the OS and hardware on a granularity of page sizes (4096, or 0x1000, bytes). e.g. if you allocate 2048 bytes, you're going to get at least 4096 bytes because it isn't possible to allocate any less. If you put multiple allocs in the same script, the minimum number of pages required to contain all that memory will be allocated.
Windows has a separate memory allocation granularity of 65536 (0x10000) bytes. i.e. the address returned by VirtualAlloc will always be aligned on a 64KiB boundary. This doesn't mean it's always better to allocate at least 16 pages at a time- there is a negligible performance penalty for that, and as such there's no reason to do that if you're not going to use all that memory.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
happyTugs Cheater
Reputation: 0
Joined: 23 Apr 2020 Posts: 26
|
Posted: Mon Jun 22, 2020 1:18 pm Post subject: |
|
|
| Quote: | | You could just put "align 4 90" before the first value |
Since I have seen this quite often, would there be any difference if you had padded the extra bytes with 0xCC instead?
| Code: | ...
///
align 4 CC
fBattleGilMultiplier:
dd (float)1
fEXPMultiplier:
dd (float)1
... |
| Quote: | | if you allocate 2048 bytes, you're going to get at least 4096 bytes because it isn't possible to allocate any less. | From my understanding, you should allocate memory that is at least 4096-bytes in size since that is the smallest page size possible for most architectures?
| Quote: | This doesn't mean it's always better to allocate at least 16 pages at a time- there is a negligible performance penalty for that
| I'll keep that in mind since I don't intend to use that much memory for a slight gain in performance.
_________________
This is a block of text that can be added to posts you make. There is a 300 character limit |
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4706
|
Posted: Mon Jun 22, 2020 3:21 pm Post subject: |
|
|
Sure, the padding bytes don't really matter. You could leave it at the default of 0 and it would be fine. The only reason why you should change it is to more easily see where code ends and data begins in the memory viewer.
The OS allocates virtual memory in multiples of 4096 bytes, and you don't have any say in the matter.
In CE AA scripts, if you're only using one alloc in the script, take up the whole 4096 bytes. If there are multiple allocs in the script, maybe try to have their sum be less than or equal to 4096 bytes. That way CE just has to ask for one page of memory and not two or more.
| Code: | // allocates 1 page:
alloc(newmem,4096)
// allocates 1 page:
alloc(newmem,3072)
alloc(foo,8)
alloc(bar,4)
// allocates 2 pages:
alloc(newmem,4096)
alloc(foo,8)
alloc(bar,4) |
I was a bit confusing when I talked about allocating 16 pages. One wrong way to think about the 64KiB allocation granularity is that if you don't allocate all 16 pages, the empty space in the process's virtual address space can never be used. It's like seeing an empty space somewhere and thinking "it's wasted space; something needs to go there," but if you don't have anything to put there, it's a moot thought. Allocating 16 pages at a time will only slow the system down (negligibly so) and won't do anything good for you if you don't need to use all of it.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
happyTugs Cheater
Reputation: 0
Joined: 23 Apr 2020 Posts: 26
|
Posted: Mon Jun 22, 2020 10:25 pm Post subject: |
|
|
| Quote: | | The padding bytes don't really matter ... [but] you should change it ... to more easily see where code ends and data begins in the memory viewer. |
| Quote: | | Windows has a separate memory allocation granularity of 65536 (0x10000) bytes. i.e. the address returned by VirtualAlloc will always be aligned on a 64KiB boundary. |
| Quote: | | Allocating 16 pages at a time ... won't do anything good for you if you don't need to use all of it. |
| Quote: | | Memory is organized by the OS and hardware on a granularity of page sizes (4096, or 0x1000, bytes) ... If you allocate 2048 bytes, you're going to get at least 4096 bytes because it isn't possible to allocate any less. |
| Quote: | | If there are multiple allocs in the script, maybe try to have their sum be less than or equal to 4096 bytes.That way CE just has to ask for one page of memory and not two or more. |
| Quote: | | Instructions don't need to be aligned (in general)... [but] there are esoteric cases where it could be advantageous in theory. |
Thank you for the replies; I will keep all of what you have said in mind!
_________________
This is a block of text that can be added to posts you make. There is a 300 character limit |
|
| Back to top |
|
 |
|
|
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
|
|