 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
SirCabby Newbie cheater
Reputation: 0
Joined: 31 Aug 2020 Posts: 15
|
Posted: Mon Aug 31, 2020 1:13 pm Post subject: [SOLVED] Help with Doubles |
|
|
Hey all, I'm new to scripting and I've done a lot of reading and trials before posting. Hoping to continue expanding my understanding but starting to hit a bit of a roadblock on my ability.
I'm trying to do a somewhat tricky script. Here's what's going on:
1) There is a value that I've got a pointer to (multi-level pointer) that I've successfully mapped and can find on new games. I need to know when the value of this pointer is at 6.
2) When the above value is 6, I need to store the value of another pointer into a variable. This other pointer's value is a double type.
3) When the value of the first pointer is NOT 6, I want the script to copy the stored value back into the second pointer's location.
4) Regardless of pointer 1's value, I want the script to cycle on a ~10 second delay loop.
This script will be running continuously on a separate thread.
I've found most of this through various threads, but I've struggled to find posts that explain how to save the value of a register for a double, and then safely restore the register later. I know that different types of values should be handled in different registers. I was also wondering if it would be easier to manage all this through a LUA script instead of manipulating the memory directly. All guidance is greatly appreciated.
Here's a look at what I've come up with so far:
| Code: |
define(address,"PapersPlease.exe"+0037DC18)
[ENABLE]
globalalloc(mycode,4096,address) // because the script is shared and continuously running, used globalalloc
globalalloc(storedTime,8,address)
globalalloc(mustend,4,address) // saw this as a way to manage disabling of a script when created for threads
globalalloc(cleanup,2048,address)
CREATETHREAD(mycode);
mycode:
push esi // Get Clock Value, this is my attempt at traversing a multi-level pointer
mov esi,[["PapersPlease.exe"+0037DC18]+78]
cmp esi,0
je cleanup
mov esi,[esi+7C]
cmp esi,0
je cleanup
mov esi,[esi+80]
cmp esi,0
je cleanup
mov esi,[esi+78]
cmp esi,0
je cleanup
mov esi,[esi+68]
cmp esi,0
je cleanup
cmp esi,6 // If Clock is at 6 we want to store the timer (which is at the following multi-level pointer address)
jne cleanup
mov [storedTime],(double)5 // I don't think this works correctly for a double. I've also tried movsd and comisd
push edi
mov edi,[["PapersPlease.exe"+0037DC18]+78]
cmp edi,0
je cleanup
mov edi,[edi+7C]
cmp edi,0
je cleanup
mov edi,[edi+A8]
cmp edi,0
je cleanup
mov edi,[edi+38]
cmp edi,0
je cleanup
movsd [storedTime],xmm0 // I think this is wrong for the register type
pop edi
jmp cleanup
cleanup:
pop esi
push #1000
call sleep
cmp [mustend],1
jne mycode
ret
mustend:
dd 0
storedTime:
dq (double)0
[DISABLE]
mustend:
dd 1
|
This code doesn't produce any errors however it also doesn't behave like I expected. My storedTime remains at 0. I am able to move a value directly into the stored variable at the beginning of the script, but it's immediately set back to 0 when the script tries to update it.[/code]
Last edited by SirCabby on Fri Sep 11, 2020 10:47 am; edited 3 times in total |
|
| Back to top |
|
 |
MMM-304 Expert Cheater
Reputation: 0
Joined: 17 Aug 2020 Posts: 170 Location: Milkey Way
|
Posted: Mon Aug 31, 2020 9:19 pm Post subject: |
|
|
1st thing about thread is that every register in a new thread is free ie 0.
also when creating a new thread u dont need to allocate everything that u use inside the thread.
| Code: |
[ENABLE]
globalalloc(mycode,4096)
CREATETHREAD(mycode)
label(cleanup mustend storedTime)
registersymbol(mustend)
// Assuming ur 1st pointer is: [[[[["PapersPlease.exe"+0037DC18]+78]+7C]+80]+78]+68
// Assuming ur 2nd pointer is: [[[["PapersPlease.exe"+0037DC18]+78]+7C]+A8]+38
mycode:
mov esi,[["PapersPlease.exe"+0037DC18]+78]
mov esi,[esi+7C]
mov ebx,esi // to use in next poiner
mov esi,[esi+80]
mov esi,[esi+78]
cmp [esi+68],6 //By the way it will only work is 6 is an integer or hex otherwise declear type!
jne cleanup
mov eax,[storedTime+8]
mov [storedTime],eax // moves double five into stored time [althoug i see no use of it]
// NOTE: I have not registered 'storedTime'. register it in case ur planing to use it outside the script
mov edi,[["PapersPlease.exe"+0037DC18]+78]
mov edi,[edi+7C]
mov edi,[edi+A8] //although u can use 'mov edi,[ebx+A8]'
cmp [edi+38],0
je cleanup
movsd [storedTime],xmm0 //I have no idea what you want to do here
{if you want to make storedTime 0 then just do this
mov [storedTime],00}
jmp cleanup
cleanup:
push #10000 //1000 = 1sec
call sleep //Sleeps for 10 sec
cmp [mustend],1
jne mycode
ret
storedTime:
dq (double)0
dq (double)5
mustend:
dd 0
[DISABLE]
mustend:
dd 1
unregistersymbol(mustend)
|
All registers and stacks (both FPU and normal source) in a new thread are empty even base pointer and stack/store pointers
|
|
| Back to top |
|
 |
SirCabby Newbie cheater
Reputation: 0
Joined: 31 Aug 2020 Posts: 15
|
Posted: Tue Sep 01, 2020 9:49 am Post subject: |
|
|
| Thank you very much for going through this! I'll experiment and absorb what you suggested and reply in more depth when I've figured it out.
|
|
| Back to top |
|
 |
SirCabby Newbie cheater
Reputation: 0
Joined: 31 Aug 2020 Posts: 15
|
Posted: Tue Sep 08, 2020 3:40 pm Post subject: |
|
|
Ok I had time to dig into this. Thanks again for the feedback and help.
I have tweaked it a bit based on your advice, and put response comments as [SC] from me:
| Code: |
[ENABLE]
globalalloc(mycode,4096)
CREATETHREAD(mycode)
label(cleanup mustend storedTime)
registersymbol(mustend)
registersymbol(storedTime) // [SC] Yes I did want to inspect this outside to make sure it was working, so I went ahead and registered it
// Assuming ur 1st pointer is: [[[[["PapersPlease.exe"+0037DC18]+78]+7C]+80]+78]+68
// Assuming ur 2nd pointer is: [[[["PapersPlease.exe"+0037DC18]+78]+7C]+A8]+38
// [SC] The above assumptions are correct
mycode:
mov esi,[["PapersPlease.exe"+0037DC18]+78]
mov esi,[esi+7C]
mov esi,[esi+80]
mov esi,[esi+78]
cmp [esi+68],(Double)6 //By the way it will only work is 6 is an integer or hex otherwise declare type!
// [SC] this is a double type, do doubles work in the 'esi' register type? This is why I was trying to use 'xmm' type
jne cleanup
// moves double five into stored time [although i see no use of it]
// [SC] this was just me debugging, seeing if I could get a 5 into the stored variable, so I removed this line
// [SC] if the above pointer was at (Double)6, then we want to store the value of the second pointer into our storedTime variable
mov edi,[["PapersPlease.exe"+0037DC18]+78]
mov edi,[edi+7C]
mov edi,[edi+A8]
mov edi,[edi+38]
cmp edi,0
je cleanup
mov [storedTime],edi // [SC] this is where I struggled. I want the value of the double stored in the second pointer to be saved into storedTime.
// [SC] Later on, I'll want to push the value of storedTime back into the value of this pointer (not yet coded)
jmp cleanup
cleanup:
push #10000 //1000 = 1sec
call sleep //Sleeps for 10 sec
cmp [mustend],1
jne mycode
ret
storedTime:
dq (double)0
dq (double)5 // [SC] I didn't need the value of 5 saved from earlier in the script, is this needed?
mustend:
dd 0
[DISABLE]
mustend:
dd 1
unregistersymbol(mustend)
unregistersymbol(storedTime)
|
Basically the logic is meant to be something like this pseudo code:
| Code: |
if clock == (double) 6 {
// save the value of time
storedTime = (double) pLevelTime
} else {
pLevelTime = (double) storedTime
}
|
|
|
| Back to top |
|
 |
SirCabby Newbie cheater
Reputation: 0
Joined: 31 Aug 2020 Posts: 15
|
Posted: Wed Sep 09, 2020 3:43 pm Post subject: |
|
|
I guess at this point most of my question is really about working with doubles
I'll update the subject to reflect this.
|
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4711
|
Posted: Thu Sep 10, 2020 6:51 pm Post subject: |
|
|
This would be far easier with Lua. Anyway...
- The third parameter to alloc isn't needed for 32-bit processes.
- You don't need that extra alloc for cleanup.
- The variables should be aligned. This is fine in the first post (everything has its own alloc), but labels should have an align pseudoinstruction before them.
- Why mix static and dynamic resolution of pointer paths? If only the first node doesn't change and can't be null, then I guess it's fine.
- {$try} / {$except} macros are a better alternative to what you're doing with null pointers.
- You didn't specify the value type of the first value in your first post, but I'm assuming it's a double.
- I really don't think you need to compare if the value is 0. (this goes against your third requirement)
- e** registers contain 4 bytes. Doubles take up 8 bytes.
- cmp is used for integer data, not floating point data.
- In x86 (32-bit), there is no way to move an 8 byte immediate in a single instruction.
- movsd can't move immediates, and comisd is used for comparing floating point numbers.
- You're redoing work by traversing part of the pointer path twice.
- Volatile registers can be used without being backed up with push/pop (this isn't a code injection)
- I don't know where you got xmm0 from. Throwing stuff at a wall won't help you much here.
- Passing 1000 to sleep is 1 second; 10000 would be 10 seconds.
Something like this:
| Code: | [ENABLE]
globalalloc(mycode,4096)
CREATETHREAD(mycode)
label(save wait loop noerror cmpvalue mustend storedTime)
registersymbol(mustend)
registersymbol(storedTime)
mycode:
{$try}
movsd xmm1,[cmpvalue]
jmp short loop
save:
movsd xmm0,[edx+38]
movsd [stored_value],xmm0
mov eax,[mustend]
test eax,eax
jne noerror
wait:
push #10000
call sleep
loop:
mov ecx,["PapersPlease.exe"+0037DC18]
mov ecx,[ecx+78]
mov ecx,[ecx+7C]
mov edx,ecx
mov ecx,[ecx+80]
mov ecx,[ecx+78]
movsd xmm0,[ecx+68] // [[[[["PapersPlease.exe"+0037DC18]+78]+7C]+80]+78]+68
mov edx,[edx+A8] // [[[["PapersPlease.exe"+0037DC18]+78]+7C]+A8]+38
comisd xmm0,xmm1
je short save
// load:
movsd xmm2,[stored_value]
movsd [edx+38],xmm2
mov eax,[mustend]
test eax,eax
je short wait
jmp noerror
{$except}
push 1
call ExitThread
noerror:
xor eax,eax
ret
align 8 CC
cmpvalue:
dq (double)6
storedTime:
dq (double)0
mustend:
dd 0
[DISABLE]
mustend:
dd 1
unregistersymbol(mustend)
unregistersymbol(storedTime)
|
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
SirCabby Newbie cheater
Reputation: 0
Joined: 31 Aug 2020 Posts: 15
|
Posted: Fri Sep 11, 2020 10:46 am Post subject: |
|
|
I really appreciate the time you took to point out all the flaws in my example. It was very constructive and I learned a lot from seeing your example.
I was able to get this working based on your help!
I did have a few follow up questions though if you don't mind.
1) Is there a place for me to see what macros are available and how they work from your {$try} / {$except}? Are these Lua?
2) Since you mentioned it'd be a lot easier with Lua, I'd like to learn more... I found this link to get started but if you have anything better for someone at ground level knowledge can you please share? <snip-because-I-can't-post-urls-yet>cheatengine/index.php?title=Tutorials:Lua:Basics
3) When you say "movsd can't move immediates", from what I've learned immediates are constants in ASM? So I can't do something like "movsd xmm0,(double)6" because the 6 is an immediate? So by your storing it in a variable and then loading it into another register you're able to leverage movsd correct?
4) When you say "I don't know where you got xmm0 from. Throwing stuff at a wall won't help you much here.", I want to make sure I understand what you mean. I read up on register types and learned that xmm registers are used for floating point / double values... I thought I needed those. And I see you used them in your example as well. What was I doing wrong here?
Thanks again, really appreciate your help.
|
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4711
|
Posted: Fri Sep 11, 2020 11:41 am Post subject: |
|
|
1) Not really. I guess you can read the source code to see how it works, but that's not exactly easy.
I learned of this in particular by reading stuff on the forums (e.g. this post)
2) First, learn Lua. CE uses Lua 5.3 (Lua 5.4 is out now, but it's not worth switching to it). The best resource I know of is the book "Programming in Lua" (fourth edition), but there are plenty of free resources online.
Then, learn the stuff CE adds to Lua. I don't know of any easy and fast way of doing this. The file celua.txt is good but long. Browsing through the forums and the wiki can be faster but also might give some bad information.
3) Yes, that's exactly correct. If you look at an instruction set reference (e.g. this one), there are three opcodes associated with the movsd mnemonic:
| Code: | MOVSD xmm1, xmm2
MOVSD xmm1, m64
MOVSD xmm1/m64, xmm2
... | Ignore all the other AVX stuff on that page.
The first moves a double from an xmm register to an xmm register, the second moves a double from a memory location (something in square brackets) to an xmm register, and the third moves a double in an xmm register into either an xmm register or a memory location.
There is no instruction that lets you move an imm64 (64-bit immediate value) into an xmm register.
4) In the first post, you're reading from xmm0 but never writing anything to it. I don't know what kind of magic you thought was in xmm0- that would never work. The difference in my code is that I write something to xmm0 before reading from it:
| Code: | movsd xmm0,[edx+38] // write to xmm0
movsd [stored_value],xmm0 // read from xmm0 |
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
SirCabby Newbie cheater
Reputation: 0
Joined: 31 Aug 2020 Posts: 15
|
Posted: Fri Sep 11, 2020 12:23 pm Post subject: |
|
|
Awesome, thanks for the follow up. I don't think my account is old enough to award rep yet but you've earned it either way.
Looking forward to growing more and contributing new tables.
|
|
| 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
|
|