| 
			
				|  | 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: | 7423 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
 
 |  |