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 


[ASM]Why doesn't this work?

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

Joined: 13 Jun 2016
Posts: 8

PostPosted: Mon Jun 13, 2016 8:42 pm    Post subject: [ASM]Why doesn't this work? Reply with quote

I'm trying to use hotkeys to add/subtract from the values that control the X and Y coordinates on Stardew Valley. The problem is the values are 3 bytes long with the 4th byte doing something else. The game freaks out when I mess with the 4th byte so I haven't tried to figure out it's function. When I create a hotkey to add 100000 to the address as a 4 byte type, the character leaps farther across the screen as the value increases. Inversely, the the same problem arises when I subtract 100000 from the address so as my character moves across the screen, the distance moved becomes smaller until theres no movement visible.

In an attempt to rectify the situation, I added the following code as a custom value type.
Code:
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)
alloc(Alignment,1)

TypeName:
db '3 Bytes',0

ByteSize:
dd 3

Alignment:
dd 1

//The convert routine should hold a routine that converts the data to an nteger (in eax)
//function declared as: stdcall int ConvertRoutine(unsigned char *input);

//Note: Keep in mind that this routine can be called by multiple threads at the same time.

ConvertRoutine:
[32-bit]
push ebp
mov ebp,esp
push ecx
mov ecx,[ebp+8]
[/32-bit]

//at this point ecx contains the address where the bytes are stored

//put the bytes into the eax register
mov eax,[ecx] //second fun fact, addressing with 32-bit registers doesn't work in 64-bit, it becomes a 64-bit automatically (most of the time)
shr eax,3 //shift right by 3 bits (divide by 8)

//and now exit the routine
[64-bit]
ret
[/64-bit]
[32-bit]
pop ecx
pop ebp
ret 4
[/32-bit]

//The convert back routine should hold a routine that converts the given integer back to a row of bytes (e.g when the user wats to write a new value)
//function declared as: stdcall void ConvertBackRoutine(int i, unsigned char *output);
ConvertBackRoutine:
[32-bit]
push ebp
mov ebp,esp
push edx //save the registers
push ecx
mov edx,[ebp+0c]
mov ecx,[ebp+08]
[/32-bit]

//at this point edx contains the address to write the value to
//and ecx contains the value

push eax
push edx


mov edx,[edx] //edx now contains the original value
and edx,7 //only save the first 3 bits

mov eax,ecx //eax gets the user input value
shl eax,3 //shift left by 3 bits (multiply by 8)
or eax,edx //add the bits of the original value

pop edx
mov [edx],eax //write the new value into the old value
pop eax

[64-bit]
//everything is back to what it was, so exit
ret
[/64-bit]

[32-bit]
//cleanup first
pop ecx
pop edx
pop ebp
ret 8
[/32-bit]


When I change my x and y coords to 3 byte value type, the hotkey increments the same way it did as a 4 byte type but doesn't decrement at all. The value changes from 1159292670 to 12791007 when I change it to 3 bytes so CE must be reading it the way I want it to but I don't know how to get it to write the value correctly. I'm using CE 6.5 if it helps.

This idea came from viewtopic.php?p=5259595 and I'll admit, I really don't know what I'm doing when it comes to assembly. There might even be an easier solution to the problem I'm having but I've messed with this long enough that I'd prefer to see a custom value type solution.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4706

PostPosted: Mon Jun 13, 2016 9:20 pm    Post subject: Reply with quote

...are you sure that's not a float? It really seems like a single precision floating point value from absolutely everything you've described. Find that address, add it to the address list, and look at what instructions access it. If they're instructions used for modifying floats (e.g. movss, addss, fld dword ptr[...], etc.), then odds are, that's a float.

Here's an example of modifying a single precision float using SSE:
Code:
newmem:
  movss xmm0,[num1]
  addss xmm0,[num2]
  movss [num3],xmm0    // num3 is now 2100
  ret
num1:
  dd (float)2000
num2:
  dd (float)100
num3:
  dd 0

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

Joined: 13 Jun 2016
Posts: 8

PostPosted: Tue Jun 14, 2016 12:55 am    Post subject: Reply with quote

It was a float. Embarassed
Thank you.

Well since this post is already here, do you see why it won't decrement?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4706

PostPosted: Tue Jun 14, 2016 9:52 am    Post subject: Reply with quote

A bit is not the same thing as a byte. 1 byte = 8 bits. If you only took into account the 3 least significant bytes of the value 1159292670 (FE 66 19 45), it would be 1664766 (FE 66 19 00), not 12791007 (DF 2C C3 00).

Sidvicious512 wrote:
Code:
mov edx,[edx] //edx now contains the original value

This is wrong. This script is used by CE when it searches for a value and changes a value, and as such, is using CE's virtual address space. In order to access the game's memory, you'd have to use some kernel function (i.e. ReadProcessMemory).

3 Byte custom value type:
Code:
alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(UsesFloat,1)
alloc(CallMethod,1)

TypeName:
db '3 Bytes',0

ByteSize:
dd 3

UsesFloat:
db 0 //Change to 1 if this custom type should be treated as a float

CallMethod:
db 1 //Remove or change to 0 for legacy call mechanism

//The convert routine should hold a routine that converts the data to an integer (in eax)
//function declared as: cdecl int ConvertRoutine(unsigned char *input, PTR_UINT address);
//Note: Keep in mind that this routine can be called by multiple threads at the same time.
ConvertRoutine:
[64-bit]
mov eax,[rcx]
[/64-bit]

[32-bit]
mov eax,[esp+4]
mov eax,[eax]
[/32-bit]

and eax,00FFFFFF
ret

//The convert back routine should hold a routine that converts the given integer back to a row of bytes (e.g when the user wats to write a new value)
//function declared as: cdecl void ConvertBackRoutine(int i, PTR_UINT address, unsigned char *output);
ConvertBackRoutine:
[64-bit]
and ecx,00FFFFFF
mov [r8],ecx
ret
[/64-bit]

[32-bit]
push eax
push ebx
mov eax,[esp+C] //load the value into eax
and eax,00FFFFFF
mov ebx,[esp+14] //load the output address into ebx
mov [ebx],eax //write the value into the address
pop ebx
pop eax
ret
[/32-bit]

Make sure to modify or turn off "Fast Scan" options when searching for any value types that aren't aligned on a boundary of a power of 2.

Note that if you only want to search/modify the fractional part of floats, only take into account the least significant 23 bits (i.e. and eax,007FFFFF). 24-31 = exponent, 32 = sign. See wikipedia for more information.

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

Joined: 13 Jun 2016
Posts: 8

PostPosted: Tue Jun 14, 2016 11:27 am    Post subject: Reply with quote

Doesn't work. When I switch my values that I now know to be floats to 3 byte, they neither increment nor decrement. Sad because I picked out a reaction gif and everything. Meh, I'll still put it up.


flawless_victory-65136.gif
 Description:
 Filesize:  289.43 KB
 Viewed:  7415 Time(s)

flawless_victory-65136.gif


Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4706

PostPosted: Tue Jun 14, 2016 1:13 pm    Post subject: Reply with quote

I'm sure it's changing the bytes in memory. It's just that changing the least significant bits of the fractional part of a float have so little effect that it's hardly noticeable in-game. For example:
Code:
dword (hex)  3 bytes (dec)   float
44FA0000     16384000        2000
44FA0001     16384001        2000.000122   (0.0000061% increase)

However, I did look through CE's source and found out why it's allowing it to increase but not decrease. It seems like the TMemoryRecord.decreaseValue procedure in Cheat Engine/MemoryRecordUnit.pas doesn't take into account the value type vtCustom unlike the increaseValue procedure. For now, one workaround would be to use Lua to make the hotkey:
Code:
local incXHK = createHotkey(function(hk)
    local mr = getAddressList().getMemoryRecordByDescription("X Coordinate")
    mr.Value = tostring(tonumber(mr.Value)+1)
  end, VK_SHIFT, VK_J)
-- etc.

If you have a pointer or a registered symbol referencing your coordinates, use those instead with readFloat(address) and writeFloat(address, value).


Regardless, you shouldn't be using this 3 byte value type template in the first place.

_________________
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 programming 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