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 


Read & Write Little & Big Endian

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting -> Lua Extensions
View previous topic :: View next topic  
Author Message
akumakuja28
Master Cheater
Reputation: 16

Joined: 28 Jun 2015
Posts: 432

PostPosted: Mon Apr 17, 2017 5:02 pm    Post subject: Read & Write Little & Big Endian Reply with quote

This was needed for my Cemu: Zelda , Breath of Wild Trainer.
Figure I could share this snippet of code as I couldnt find anything like this searching the forums and github had some overly complicated code.





GO to 3rd Post

THAT guy found some good code.

_________________


Last edited by akumakuja28 on Mon Apr 17, 2017 8:04 pm; edited 2 times in total
Back to top
View user's profile Send private message
ParkourPenguin
Grandmaster Cheater Supreme
Reputation: 52

Joined: 06 Jul 2014
Posts: 1778
Location: Arcadian Suburbia

PostPosted: Mon Apr 17, 2017 6:27 pm    Post subject: Reply with quote

I'm pretty sure you meant "big endian." With regards to primitive data types composed of multiple bytes, "little endian" means the least significant byte is stored first (used by x86 architectures) and "big endian" means the most significant byte is stored first (not uncommon to see on emulators).
Code:
32-bit integer:
0x1234ABCD

big endian:
12 34 AB CD

little endian:
CD AB 34 12

_________________
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
FreeER
Master Cheater
Reputation: 10

Joined: 09 Aug 2013
Posts: 307

PostPosted: Mon Apr 17, 2017 7:51 pm    Post subject: Reply with quote

Hm, this looks like it'd only work for 2 byte values (a word in other words)...

If so, why not take 20 minutes and create something like this (note I have not tested this and am no expert on lua but I _think_ it should work lol): https://pastebin.com/hHewwjBT

(same as attached file, I just like providing options)

Note that this reads Big Endian if used on a Little Endian system and Little Endian if used on a Big Endian system since the two are literally just byte reversals and that's what this code (at least theoretically) would do... I suppose if you spent some more time on it that you could determine whether the system was big/little endian (by performing a test if nothing else) and have both big and little endian functions which returned the result they are named after depending on that... but I don't have any real reason to do that Smile



Read_Write_Big_Endian.lua
 Description:
untested example

Download
 Filename:  Read_Write_Big_Endian.lua
 Filesize:  2.12 KB
 Downloaded:  336 Time(s)

Back to top
View user's profile Send private message
akumakuja28
Master Cheater
Reputation: 16

Joined: 28 Jun 2015
Posts: 432

PostPosted: Mon Apr 17, 2017 8:02 pm    Post subject: Reply with quote

FreeER wrote:
Hm, this looks like it'd only work for 2 byte values (a word in other words)...
I suppose if you spent some more time on it that you could determine whether the system was big/little endian (by performing a test if nothing else)


I dont know what tht means. Just going to use what you found on github now. Thank You for tht.

_________________
Back to top
View user's profile Send private message
FreeER
Master Cheater
Reputation: 10

Joined: 09 Aug 2013
Posts: 307

PostPosted: Mon Apr 17, 2017 8:19 pm    Post subject: Reply with quote

To be clear I found only the reverseTable function on github (I googled since I figured it'd be a common issue even if it was in the standard lua library which I don't really know), the rest I wrote myself (and haven't tested) Smile

As for checking what the system is, something like (again, untested)

Code:
-- get some memory we can write 2 bytes in to test on
local mem = allocateSharedMemory('luaBigEndianTesting', 2)
assert(mem, "Failed to allocate memory to test system endianness!")

-- write a test value
writeWord(mem, 0x0011)

-- set variables to be checked by everything else depending on result
-- might want to make these read-only (metatables? not sure)
-- big endian if most significant byte was written first
systemIsBigEndian = readBytes(mem,1) == 0
systemIsLittleEndian = not systemIsBigEndian -- just an alternative

readIntegerBigEndian = function(address)
  if systemIsBigEndian then
    return readInteger(address) -- already in correct byte order just read and return it.
  else
    local bytes = readBytes(address,4,true)
    reverseTable(bytes)
    return byteTableToDword(bytes)
  end
end

readIntegerLittleEndian = function(address)
  if systemIsLittleEndian then
    return readInteger(address) -- already in correct byte order just return it.
  else
    local bytes = readBytes(address,4,true)
    reverseTable(bytes)
    return byteTableToDword(bytes)
  end
end


Though I can't say for sure whether readInteger would work as shown in the example or if it would always try to read the value as a little endian value even on a big endian system (this would actually be my guess if I had to make one)... either way, you can see that the functions check whether the system is already big endian or not to determine what gets done so that (in theory) the big endian function isn't reversing the bytes when it doesn't need to (thus getting little endian bytes).

Also obviously there could be a third function that always reverses the bytes and then the else sections of the other two would simply return the result of that, purely to reduce code duplication / file size.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 341

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

PostPosted: Tue Apr 18, 2017 2:53 am    Post subject: Reply with quote

you can also try
Code:

be4=registerCustomTypeAutoAssembler([[alloc(TypeName,256)
alloc(ByteSize,4)
alloc(ConvertRoutine,1024)
alloc(ConvertBackRoutine,1024)

TypeName:
db '4 Byte Big Endian',0

ByteSize:
dd 4

//The convert routine should hold a routine that converts the data to an integer (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:
//jmp dllname.functionname
[64-bit]
//or manual:
//parameters: (64-bit)
//rcx=address of input
xor eax,eax
mov eax,[rcx] //eax now contains the bytes 'input' pointed to
bswap eax //convert to big endian

ret
[/64-bit]

[32-bit]
//jmp dllname.functionname
//or manual:
//parameters: (32-bit)
push ebp
mov ebp,esp
//[ebp+8]=input
//example:
mov eax,[ebp+8] //place the address that contains the bytes into eax
mov eax,[eax] //place the bytes into eax so it's handled as a normal 4 byte value

bswap eax

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:
//jmp dllname.functionname
//or manual:
[64-bit]
//parameters: (64-bit)
//ecx=input
//rdx=address of output
//example:
bswap ecx //convert the little endian input into a big endian input
mov [rdx],ecx //place the integer the 4 bytes pointed to by rdx

ret
[/64-bit]

[32-bit]
//parameters: (32-bit)
push ebp
mov ebp,esp
//[ebp+8]=input
//[ebp+c]=address of output
//example:
push eax
push ebx
mov eax,[ebp+8] //load the value into eax
mov ebx,[ebp+c] //load the address into ebx

//convert the value to big endian
bswap eax

mov [ebx],eax //write the value into the address
pop ebx
pop eax

pop ebp
ret 8
[/32-bit]
]])


and then use be4.byteTableToValue(readBytes(address,4,true))

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Back to top
View user's profile Send private message MSN Messenger
FreeER
Master Cheater
Reputation: 10

Joined: 09 Aug 2013
Posts: 307

PostPosted: Tue Apr 18, 2017 5:51 am    Post subject: Reply with quote

Dark Byte wrote:
you can also try
Code:

be4=registerCustomTypeAutoAssembler([[alloc(TypeName,256)
...


and then use be4.byteTableToValue(readBytes(address,4,true))


Hm, be4 seems to be nil for me in 6.6, though that would also beg the question of whether you can use existing custom types for that purpose or if you'd need to change from using the registry-based custom types to using a lua file in autorun. I did find getCustomType when searching github though it also appears to be nil in 6.6 rather than a function (though github does say the file changed in November and 6.6 was released in October according to the site so not too surprising, it's also not in main.lua for 6.6).
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 341

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

PostPosted: Wed Apr 19, 2017 4:43 am    Post subject: Reply with quote

ah yes, looks like it was a bug in 6.6 where it didn't return the type
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting -> Lua Extensions 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