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 


Problem figure out how to use float as integer multiplier.

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
ichigoned
How do I cheat?
Reputation: 0

Joined: 09 Aug 2022
Posts: 4

PostPosted: Tue Aug 09, 2022 8:27 pm    Post subject: Problem figure out how to use float as integer multiplier. Reply with quote

Hi,

I write a heal and damage multiplier in an auto assembly that I learn from youtube video and it works great. For the damage, however, it little bit inconvenient to use IDIV command.
Then I stumbled upon a shared CE table that uses float as a multiplier which more convenience instead use IDIV command.
When I look at CE shared table code it uses FILD, FMUL/FDIV, and FISTP which as far as I know similar to POP and PUSH but convert integer to float, do the arithmetic, then convert back to integer. But the method still does not click for me.

Let's say my game uses a positive value to do healing and a negative value to do the damage. The original instruction when calculating the damage (which is where I injected to) is as follows:
Code:
code:
  add ecx,r11d
  cmp ecx,edx
  jmp return

ecx stores the current hero/enemy health
r11d stores the damage/heal value

Now this is my the current multiplier code
Code:
aobscanmodule(...)
alloc(...)

HealMult:
  dd #1

registersymbol(...)

newmem:
  cmp [r10+280],1    // check whether hero / enemy
  jne code
  cmp r11d,0         // check whether heal or damage
  jl code
  imul r11d,[HealMult]


Now the question is, how do I write the code so that the r11d register can be multiplied with a float type multiplier?

for reference, I try to copy the code from the shared table (different game) in the codebox below. But seems does not work as intended (either hero/enemy dies in one hit). I suspect that I did something wrong and decide to ask here for more detailed logic behind the shared table code.
Code:
push edx  // push edx into the stack
fild dword ptr [rsp] // push and load integer from rsp to the stack?
fmul dword ptr [HealMult] // multiply the value of rsp with the multiplier
fistp dword ptr [rsp] // pop the value of multiply back to rsp?
pop edx  // pop edx (that been push previously) value back to edx???, huh?

edx I believe it holds the value of heal



Would appreciate it if someone were also able to explain the way reference code work so that I understand the logic behind it.
Thanks in advance.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4291

PostPosted: Tue Aug 09, 2022 10:02 pm    Post subject: Reply with quote

ichigoned wrote:
When I look at CE shared table code it uses FILD, FMUL/FDIV, and FISTP which as far as I know similar to POP and PUSH but convert integer to float, do the arithmetic, then convert back to integer. But the method still does not click for me.
That uses x87, which is pretty much obsolete for 64-bit code. Use SSE instead. (and use doubles, not floats)
Code:
newmem:
  cmp [r10+280],1
  jne code
  cmp r11d,0
  jl code

  cvtsi2sd xmm0,r11d     // convert to double
  mulsd xmm0,[HealMult]  // multiply
  cvttsd2si r11d,xmm0    // convert back to int

code:
  add ecx,r11d
  cmp ecx,edx
  jmp return

HealMult:
  dq (double)1.0

Points about your code:
  1. `dd #1` - here 1 is an integer, not a float. Should've been `dd (float)1.0`
  2. No clue where you got edx from. You clearly say the change in health is stored in r11d.
  3. There are two stacks at play: the threadstack (rsp) and the x87 stack. The `push` instruction operates on the threadstack. Its purpose is to store the change in health in memory somewhere (`fild` can't read from a general purpose register- only memory).

_________________
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
ichigoned
How do I cheat?
Reputation: 0

Joined: 09 Aug 2022
Posts: 4

PostPosted: Tue Aug 09, 2022 10:54 pm    Post subject: Reply with quote

ParkourPenguin wrote:
ichigoned wrote:
When I look at CE shared table code it uses FILD, FMUL/FDIV, and FISTP which as far as I know similar to POP and PUSH but convert integer to float, do the arithmetic, then convert back to integer. But the method still does not click for me.
That uses x87, which is pretty much obsolete for 64-bit code. Use SSE instead. (and use doubles, not floats)
Code:
newmem:
  cmp [r10+280],1
  jne code
  cmp r11d,0
  jl code

  cvtsi2sd xmm0,r11d     // convert to double
  mulsd xmm0,[HealMult]  // multiply
  cvttsd2si r11d,xmm0    // convert back to int

code:
  add ecx,r11d
  cmp ecx,edx
  jmp return

HealMult:
  dq (double)1.0

Points about your code:
  1. `dd #1` - here 1 is an integer, not a float. Should've been `dd (float)1.0`
  2. No clue where you got edx from. You clearly say the change in health is stored in r11d.
  3. There are two stacks at play: the threadstack (rsp) and the x87 stack. The `push` instruction operates on the threadstack. Its purpose is to store the change in health in memory somewhere (`fild` can't read from a general purpose register- only memory).


Thanks for the reply.

I have a question.
Code:
cvtsi2sd xmm0,r11d

In this part, I can see that it will borrow xmm0 register to store the value.
Do I need to be concerned xmm0 register being used somewhere else?
Or it is safe to leave it as it is without storing the value of xmm0 before borrowing and then restoring it later?
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 942

PostPosted: Wed Aug 10, 2022 12:09 am    Post subject: Reply with quote

Using fpu instruction has benefit to less need to save register (general or xmm), as your concern.

The following code multiply 2 or -2 depend both if it is heal/dmg or enemy/not
Code:

aobscanmodule(...)
alloc(...)

HealMult:
  dd #2, #-1

registersymbol(...)

newmem:
  push r11
    fild    dword ptr[rsp]
    cmp     [r10+280],1 /// player or enemy?
    je      short @f
      fimul dword ptr[HealMult+4]// negate
@@:   
    cmp     dword ptr[rsp],0 /// negative change?
    jge     short @f
      fimul dword ptr[HealMult+4]// negate
@@:
    fimul   dword ptr[HealMult] // multiply
    fistp   dword ptr[rsp]      // save r11d   -- need qword ptr[rsp]? depend on how r11 use in following code
  pop r11
///  jl code
///  imul r11d,[HealMult]
... original code

HealMult can use float instead of integer, just change respective instruction to float version.

_________________
- Retarded.
Back to top
View user's profile Send private message
ichigoned
How do I cheat?
Reputation: 0

Joined: 09 Aug 2022
Posts: 4

PostPosted: Wed Aug 10, 2022 12:34 am    Post subject: Reply with quote

panraven wrote:
Using fpu instruction has benefit to less need to save register (general or xmm), as your concern.

The following code multiply 2 or -2 depend both if it is heal/dmg or enemy/not
Code:

aobscanmodule(...)
alloc(...)

HealMult:
  dd #2, #-1

registersymbol(...)

newmem:
  push r11
    fild    dword ptr[rsp]
    cmp     [r10+280],1 /// player or enemy?
    je      short @f
      fimul dword ptr[HealMult+4]// negate
@@:   
    cmp     dword ptr[rsp],0 /// negative change?
    jge     short @f
      fimul dword ptr[HealMult+4]// negate
@@:
    fimul   dword ptr[HealMult] // multiply
    fistp   dword ptr[rsp]      // save r11d   -- need qword ptr[rsp]? depend on how r11 use in following code
  pop r11
///  jl code
///  imul r11d,[HealMult]
... original code

HealMult can use float instead of integer, just change respective instruction to float version.


Now, this is interesting.

Correct me if I'm wrong. But...

Code:
fild dword ptr[rsp]

What does this line do?
From what I understand, this push whatever value in [rsp] to the top of stack and put it as a float. But I still don't understand the intention of doing this.


Code:
fistp dword ptr[rsp]

This pop whatever result of multiplication back to [rsp].
But, then how
Code:
pop r11

Will yield the result of multiplication, instead of [rsp]?
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 942

PostPosted: Wed Aug 10, 2022 12:56 am    Post subject: Reply with quote

fpu instruction work on an internal stack (limited size), which each is a 10 byte extended double float (EDF).

@"fild dword ptr[rsp]"
it load a 4byte (coz 'dword ptr') integer (i in fild) from the memory [rsp],
convert it to EDF and push into the internal fpu stack.

"This pop whatever result of multiplication back to [rsp]."
Yes, ie.
pop EDF from fpu stack top
convert it to 4byte integer (dword ptr, i in fistp)
then save the 4byte to memory [rsp]

@"pop r11"
It pop pc stack top [rsp] to r11, since we work on [rsp] previously, so ir11 got the multiply result.

_________________
- Retarded.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4291

PostPosted: Wed Aug 10, 2022 1:17 am    Post subject: Reply with quote

ichigoned wrote:
Do I need to be concerned xmm0 register being used somewhere else?

Look around the injection point. If you don't see xmm0 anywhere, it's probably fine.

If you want, use a different one- e.g. xmm6. It's less likely to be used than xmm0.

You could back it up to the stack if you're really concerned, but it's unnecessary.
Code:
sub rsp,20
movups [rsp],xmm0
...
movups xmm0,[rsp]
add rsp,20

_________________
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
Dark Byte
Site Admin
Reputation: 458

Joined: 09 May 2003
Posts: 25288
Location: The netherlands

PostPosted: Wed Aug 10, 2022 2:25 am    Post subject: Reply with quote

or if you don't want to deal with all this and it's not a super highperformance location in the game:
Code:

HealMult:
  dd (float)2.5
...

{$ccode value=r11}
extern float HealMult;
float f=HealMult; //extern float/double has a small bug in libtcc in 7.4 (this works as a bypass)

value=value*f;
{$asm}
//r11 is multiplied by HealMult now
...

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
ichigoned
How do I cheat?
Reputation: 0

Joined: 09 Aug 2022
Posts: 4

PostPosted: Wed Aug 10, 2022 9:04 am    Post subject: Reply with quote

Hi,

Very much appreciate all the different approaches to solving the issue.
The cvtsi2sd command is the most preferred as of now. Probably will stick with this until I found other difficulties ahead.

I will try both FPU instruction and Lua scripting once get more grasp of them.

And probably my last question, is the cvtsi2sd command only work for 64bit games?

Thank bunch.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4291

PostPosted: Wed Aug 10, 2022 12:11 pm    Post subject: Reply with quote

The version that takes a 32-bit operand works in 32-bit or 64-bit games. The version that takes a 64-bit operand only works in 64-bit games.
_________________
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 -> General Gamehacking 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