 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
Sidvicious512 How do I cheat?
Reputation: 0
Joined: 13 Jun 2016 Posts: 8
|
Posted: Mon Jun 13, 2016 8:42 pm Post subject: [ASM]Why doesn't this work? |
|
|
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 |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4706
|
Posted: Mon Jun 13, 2016 9:20 pm Post subject: |
|
|
...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 |
|
 |
Sidvicious512 How do I cheat?
Reputation: 0
Joined: 13 Jun 2016 Posts: 8
|
Posted: Tue Jun 14, 2016 12:55 am Post subject: |
|
|
It was a float.
Thank you.
Well since this post is already here, do you see why it won't decrement?
|
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4706
|
Posted: Tue Jun 14, 2016 9:52 am Post subject: |
|
|
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 |
|
 |
Sidvicious512 How do I cheat?
Reputation: 0
Joined: 13 Jun 2016 Posts: 8
|
Posted: Tue Jun 14, 2016 11:27 am Post subject: |
|
|
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.
| Description: |
|
| Filesize: |
289.43 KB |
| Viewed: |
7415 Time(s) |

|
|
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4706
|
Posted: Tue Jun 14, 2016 1:13 pm Post subject: |
|
|
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 |
|
 |
|
|
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
|
|