 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Noobrzor Advanced Cheater
Reputation: 0
Joined: 19 May 2014 Posts: 74
|
Posted: Wed Jan 20, 2016 5:31 pm Post subject: Comparing/copying float and integer |
|
|
Greetings
[eax+0c] is the current condition of an item, stored as a float value.
[esp+8c] is the max condition of an item, stored as an integer, dword.
These are registers of one code, I'm trying to make the script first compare [esp+8c] to a certain threshold value, and then if above it have the [esp+8c] integer dword be 'translated' into a floating point value and then mov'ed into [eax+0c].
How does that work?
Can I just do something like:
Code: | mov [backupEAX],eax
movss eax,[eax+8c]
mov [eax+0c],eax
mov eax,[backupEAX] //i don't use push and pop, i had issues with that earlier and this works flawlessly |
as well how would comiss behave if I compared integer and float like that?
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4697
|
Posted: Wed Jan 20, 2016 7:25 pm Post subject: |
|
|
That exact code would absolutely not work. I'm guessing you mean to have [esp+8c] instead of [eax+8c]. Even then, moving it into eax and then trying to read from it like it's still an address would probably crash the game (segfault). This is because [eax+0c] isn't the same as it was before you moved stuff into eax.
Whenever you push/pop something, ESP is decremented/incremented by 4 each time respectively (8 for x64). So [esp+8c] would turn into [esp+90] if you pushed something onto the stack beforehand without popping it off. If you take this into account, you can push and pop stuff just fine.
You can convert a 4-byte integer to a floating point number and push it onto the x87 stack by using FILD m32int (include dword ptr just in case; use qword ptr for an 8-byte integer).
Do NOT try to compare integers and floats directly. Convert the integer to a float and compare them like that. If you're using the x87 stack, use FCOMI. If you're using SSE registers (e.g. xmm0), you can use comiss like you stated.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
akumakuja28 Master Cheater
Reputation: 16
Joined: 28 Jun 2015 Posts: 432
|
Posted: Thu Jan 21, 2016 3:06 am Post subject: |
|
|
Convert Floats And Integers
The Link has all SSE2 conversion.
But to make this easy.
movd xmm47,[integer]
cvtdq2ps xmm47,xmm47
xmm47 is now a Float instead of integer
Quote: |
[eax+0c] is the current condition of an item, stored as a float value.
[esp+8c] is the max condition of an item, stored as an integer, dword.
These are registers of one code, I'm trying to make the script first compare [esp+8c] to a certain threshold value, and then if above it have the [esp+8c] integer dword be 'translated' into a floating point value and then mov'ed into [eax+0c]. | [/quote]
IM confused at your logic here.
Do you mean compare current condition. [eax+0c]. To a Set Value. If Value is lower Convert Max Condition and then Move Max into Current?
_________________
|
|
Back to top |
|
 |
Noobrzor Advanced Cheater
Reputation: 0
Joined: 19 May 2014 Posts: 74
|
Posted: Thu Jan 21, 2016 3:36 am Post subject: |
|
|
ParkourPenguin wrote: | That exact code would absolutely not work. I'm guessing you mean to have [esp+8c] instead of [eax+8c]. Even then, moving it into eax and then trying to read from it like it's still an address would probably crash the game (segfault). This is because [eax+0c] isn't the same as it was before you moved stuff into eax.
Whenever you push/pop something, ESP is decremented/incremented by 4 each time respectively (8 for x64). So [esp+8c] would turn into [esp+90] if you pushed something onto the stack beforehand without popping it off. If you take this into account, you can push and pop stuff just fine.
You can convert a 4-byte integer to a floating point number and push it onto the x87 stack by using FILD m32int (include dword ptr just in case; use qword ptr for an 8-byte integer).
Do NOT try to compare integers and floats directly. Convert the integer to a float and compare them like that. If you're using the x87 stack, use FCOMI. If you're using SSE registers (e.g. xmm0), you can use comiss like you stated. |
Thanks for replying. As to regards to my code, I have this now:
Code: |
mycode:
fild dword ptr [esp+8c]
fstp dword ptr [ebp+08]
jmp originalcode
originalcode:
fld dword ptr [ebp+08]
fstp dword ptr [eax+0C] //game code
jmp returnhere
|
To my surprise, as I lack internal knowledge on how exactly that worked, it did so without problem. Any flaws in that piece of script?
The push/pop decrementing the esp could be the answer why I had the game crashed the way I did way back. I often use things like cmp [esp+1c],Game.exe+84B86 (secondary value of something in the stack) to make the code assess first if the changed game code is accessing the particular one of a whole bunch of addresses it does normally.
Still, any particular advantage of push/pop over mov [backup],eax /mov eax,[backup] like I did?
The thing with eax I noticed, terrible fail of mine. I was tired and sleepy and didn't pay attention. I meant to do:
Code: | mov [backupEBX],ebx
movss ebx,[esp+8c]
mov [eax+0c],ebx
mov ebx,[backupEBX] |
And that obviously wouldn't work, right?
Also, regarding FILD instruction - I'd read it converts an integer to a double-precision point, and that means Double (8 byte) not Float (4 byte) (I mean basic cheat engine value types). Dword ptr means it will turn it into a single point precision point instead of supposed double?
Or is there a separate instruction regarding single-point precision float, and the reason my code worked is just coincidence?
Again, thanks a lot!
@Akuma
I'll check these converts in a moment and how it works, thanks for sharing that.
Oh, my logic is that usually items have to have max condition of 50 or above. In an event it will be less, I don't want the script to 'repair' them, because it could make some non-typical items with condition bug out.
As in, all items that have max condition of 50 or above are repaired, all that below are not, regardles of what's their current one.
|
|
Back to top |
|
 |
hhhuut Grandmaster Cheater
Reputation: 6
Joined: 08 Feb 2015 Posts: 607
|
Posted: Thu Jan 21, 2016 3:45 am Post subject: |
|
|
Noobrzor wrote: |
The thing with eax I noticed, terrible fail of mine. I was tired and sleepy and didn't pay attention. I meant to do:
Code: | mov [backupEBX],ebx
movss ebx,[esp+8c]
mov [eax+0c],ebx
mov ebx,[backupEBX] |
Would that work? |
Easiest way to try if your code works is copying it into a AA-Form and assigning it to a cheat table. CE will tell you if all code is compileable or not, but I think your instruction
won't work, because for the "movss" command you need a SSE-register (not 100% sure about that though) ...
|
|
Back to top |
|
 |
mgr.inz.Player I post too much
Reputation: 222
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Thu Jan 21, 2016 5:23 am Post subject: |
|
|
I assume that:
[eax+0c] is the current condition of an item, stored as a single-precision floating-point value. In range <0,maxValue>
[esp+8c] is the max condition of an item, stored as an integer, dword.
And your threshold would be 75%
So, if current condition is 60%, script does nothing, if current condition is 80%, script should change it to 100%
Code: | alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(backup)
label(threshold)
newmem:
movups [backup],xmm0
cvtsi2ss xmm0,[esp+8c]
mulss xmm0,[threshold]
comiss xmm0,[eax+0c]
movups xmm0,[backup]
ja originalcode
fild dword ptr [esp+8c]
fstp dword ptr [eax+0c]
originalcode:
{orig code here}
jmp returnhere
backup:
dd 0 0 0 0
threshold:
dd (float)0.75 |
Edit:
I missed this:
Noobrzor wrote: | Oh, my logic is that usually items have to have max condition of 50 or above. In an event it will be less, I don't want the script to 'repair' them, because it could make some non-typical items with condition bug out.
As in, all items that have max condition of 50 or above are repaired, all that below are not, regardles of what's their current one. |
In that case:
Code: | alloc(newmem,2048)
label(returnhere)
label(originalcode)
newmem:
cmp [esp+8c],#50
jl originalcode
fild dword ptr [esp+8c]
fstp dword ptr [eax+0c]
originalcode:
{orig code here}
jmp returnhere |
_________________
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4697
|
Posted: Thu Jan 21, 2016 10:43 am Post subject: |
|
|
Noobrzor wrote: | Code: | mycode:
fild dword ptr [esp+8c]
fstp dword ptr [ebp+08]
jmp originalcode
originalcode:
fld dword ptr [ebp+08]
fstp dword ptr [eax+0C] //game code
jmp returnhere
| ... Any flaws in that piece of script? | None that I see. It could be optimized a bit more (e.g. remove jmp originalcode - it'll execute that code next anyways), but if it works, it works.
Noobrzor wrote: | Still, any particular advantage of push/pop over mov [backup],eax /mov eax,[backup] like I did? | Not really... it's just a different way of doing it. Doing that takes up significantly more memory in your code compared to using push/pop, but again, if it works, it works.
Noobrzor wrote: | Code: | mov [backupEBX],ebx
movss ebx,[esp+8c]
mov [eax+0c],ebx
mov ebx,[backupEBX] | And that obviously wouldn't work, right? | Correct. Even though they're both 4 bytes long, the game thinks [esp+8c] is an integer and [eax+0c] is a float. If you want to know why this is bad, take any standard 4 byte value in the address list and change its type to float. This won't change the bytes in memory (so it won't change the value), but it will change how CE displays that value.
Noobrzor wrote: | Also, regarding FILD instruction... | x87 works differently than how you'd initially expect it to work. Most instructions you'll see that load stuff onto the x87 stack (i.e. fld, fild) converts the data it's loading into a double extended-precision floating-point format (aka m80fp, or memory 80bits floating point). When you're pushing data onto the x87 stack, it needs to know the type of data so that it knows how many bytes to read. When you're writing something on the x87 stack into memory, it needs to know the type of data so it knows how many bytes to write.
From wikipedia:
Quote: | The temporary real (extended) format was designed not to store data at higher precision as such, but rather primarily to allow for the computation of double results more reliably and accurately by minimising overflow and roundoff-errors in intermediate calculations... [x87] automatically converts numbers to this format when loading floating point registers from memory and also converts results back to the more conventional formats when storing the registers back into memory. |
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
Noobrzor Advanced Cheater
Reputation: 0
Joined: 19 May 2014 Posts: 74
|
Posted: Thu Jan 21, 2016 10:47 am Post subject: |
|
|
ParkourPenguin wrote: | ... |
You're just too helpful, thanks a lot!
And thx magistrze for brilliant example.
|
|
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
|
|