View previous topic :: View next topic |
Author |
Message |
akumakuja28 Master Cheater Reputation: 16
Joined: 28 Jun 2015 Posts: 432
|
Posted: Mon Apr 17, 2017 5:02 pm Post subject: Read & Write Little & Big Endian |
|
|
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 |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
Posted: Mon Apr 17, 2017 6:27 pm Post subject: |
|
|
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 |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
|
Back to top |
|
|
akumakuja28 Master Cheater Reputation: 16
Joined: 28 Jun 2015 Posts: 432
|
Posted: Mon Apr 17, 2017 8:02 pm Post subject: |
|
|
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 |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Mon Apr 17, 2017 8:19 pm Post subject: |
|
|
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)
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 |
|
|
Dark Byte Site Admin Reputation: 457
Joined: 09 May 2003 Posts: 25262 Location: The netherlands
|
Posted: Tue Apr 18, 2017 2:53 am Post subject: |
|
|
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.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Tue Apr 18, 2017 5:51 am Post subject: |
|
|
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 |
|
|
Dark Byte Site Admin Reputation: 457
Joined: 09 May 2003 Posts: 25262 Location: The netherlands
|
Posted: Wed Apr 19, 2017 4:43 am Post subject: |
|
|
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.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
|