|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Razi Expert Cheater Reputation: 1
Joined: 17 Jan 2018 Posts: 202
|
Posted: Sun Aug 12, 2018 9:43 am Post subject: How to read/write name of character? |
|
|
How to read name from address to Edit box? For example: name of character consist from 12 bytes (12 letters/symbols) . Each 1 letter is 1 byte. If 1 byte value == 0x21 then it is "A", or if == 0x41 then it is "a".
Code: |
Namestbl = {
[0x21] = 'A'
,[0x22] = 'B'
,[0x23] = 'C'
,[0x24] = 'D'
,[0x41] = 'a'
,[0x42] = 'b'
,[0x43] = 'c'
,[0x00] = ' ' -- SPACE
} |
How to write name from Edit box to address?
If we need to write name from Edit box, then after letters other bytes must be filled with 0xFF. For example: If we typed 3 letters "B","C","D", other 9 bytes must be written with 0xFF. Then 12 bytes should be written like this: 0x22, 0x23, 0x24, 0xFF, 0xFF, 0xFF, 0xFF , 0xFF, 0xFF, 0xFF ,0xFF, 0xFF.
|
|
Back to top |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Sun Aug 12, 2018 10:25 am Post subject: |
|
|
Code: | readString(address, maxlength, widechar OPTIONAL) : Reads a string till it encounters a 0-terminator. Maxlength is just so you won't freeze for too long, set to 6000 if you don't care too much. Set WideChar to true if it is encoded using a widechar formatting
writeString(address,text, widechar OPTIONAL) : Write a string to the specified address. Returns true on success |
source: celua.txt (though it's on the wiki as well https://wiki.cheatengine.org/index.php?title=Lua:readString)
Since it's 1 character per byte it's not a wide string so you could either pass false or just pass two and let it implicitly be nil which is a false expression.
Looks like if you don't pass maxlength to readString it defaults to 50 ([url=https://github.com/cheat-engine/cheat-engine/blob/d218638b19a67d74cb32a6c313bfa022da1984b1/Cheat%20Engine/LuaHandler.pas#L1598-L1601]github]), looked it up since I often don't but that didn't say it's optional like widechar
Code: | As for the edit box
Edit Class: (Inheritance: WinControl->Control->Component->Object)
createEdit(owner): Creates an Edit class object which belongs to the given owner. Owner can be any object inherited from WinControl
properties
Text: string - The current contents of the editfield
... |
so FormName.EditName.Text, eg. CETrainer.EditBox1.Text, is the text/name in the edit box and you'd just add = somestring or = readString(... args) to set it.
edit: just saw the 0xFF/255/-1... that's strange, typically strings just end with a 0 byte (or two for wide strings). But easy enough I suppose (assuming addr is a number)
For reading you can use eg. readString(addr,12):gsub('\xFF','') to remove the 0xFF bytes.
for writing you could use writeString(addr,newname .. ('\xFF'):rep(12-#newname)) to concatenate the needed bytes (or use two writeStrings to prevent the concatenation but with only 12 bytes it probably doesn't matter that lua strings are immutable and concatenating requires 2x the memory)
_________________
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4299
|
Posted: Sun Aug 12, 2018 11:44 am Post subject: |
|
|
That's a different character encoding. Seems like it's offset by -0x20 from ASCII.
I can't post example code because cloudfare thinks it's evil and CEF fails when posting is interrupted, but the code isn't too complicated. Use readBytes / writeBytes to deal with the game's memory and string.char / string.byte to convert between numbers and strings. table.concat and string.gmatch may also be useful.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
Razi Expert Cheater Reputation: 1
Joined: 17 Jan 2018 Posts: 202
|
Posted: Sun Aug 12, 2018 12:25 pm Post subject: |
|
|
Tried with readString, but without result. Or I do not know, how to work with readString. Found a solution for "read character's name" and it works:
Code: | Namestbl = {
[0x21] = 'A'
,[0x22] = 'B'
,[0x23] = 'C'
,[0x24] = 'D'
,[0x41] = 'a'
,[0x42] = 'b'
,[0x43] = 'c'
,[0x00] = ' ' -- SPACE
}
local n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12 = readBytes(0x009E8634,12)
UDF1.CEEdit505.Text = Namestbl[n1]..Namestbl[n2]..Namestbl[n3]..Namestbl[n4]
..Namestbl[n5]..Namestbl[n6]..Namestbl[n7]..Namestbl[n8]..Namestbl[n9]
..Namestbl[n10]..Namestbl[n11]..Namestbl[n12] |
But can not find solution to write name from Edit box.Trying next code, but it did not works:
Code: | for x = 0, 8 do
local currentCharNames = CharNames[x+1]
local offset1 = x * 0x84
CharNames[x+1].OnKeyPress = function(sender, key)
timer.Enabled = false
local a = sender.Text
if (a~=nil) and isKeyPressed(VK_RETURN) then
writeBytes(0x009E8634 + offset1, Namestbl[currentCharNames.Text[1]],Namestbl[currentCharNames.Text[2]])
timer.Enabled = true
end
return key
end
end |
Last edited by Razi on Tue Aug 14, 2018 3:33 am; edited 1 time in total |
|
Back to top |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Sun Aug 12, 2018 4:33 pm Post subject: |
|
|
Quote: | That's a different character encoding. Seems like it's offset by -0x20 from ASCII. | Ah, so it is. Perhaps something like this then
Code: | local function readName(addr, len)
len = len or 12 -- defaults to 12
local bytes = readBytes(addr, len, true)
local chars = {}
for k,v in ipairs(bytes) do
if v == 0xFF then break end
chars[#chars+1] = string.char(v+0x20)
end
return table.concat(chars,'')
end
local function writeName(addr, name, len)
len = len or 12 -- default to 12
assert(#name < len, 'Name must be less than len (default 12)')
local bytes = {}
for i=1,#name do bytes[#bytes+1] = name:byte(i)-0x20 end
for i=1,len-#bytes do bytes[#bytes+1] = 0xFF end -- pad with 0xFF
writeBytes(addr, bytes)
end |
_________________
|
|
Back to top |
|
|
Razi Expert Cheater Reputation: 1
Joined: 17 Jan 2018 Posts: 202
|
Posted: Mon Aug 13, 2018 3:32 am Post subject: |
|
|
FreeER wrote: | Ah, so it is. Perhaps something like this then |
Functions: readName and writeName, they work great, thank you very much.
Quote: "If we need to write name from Edit box, then after letters other bytes must be filled with 0xFF". I made a mistake, sorry.
This works in the game like this: If we need to write name from Edit box, then after letters first 2 bytes must be filled with 0xFF, and last 3 bytes must be filled with 0xFF. Bytes between first 2 bytes and last 3 bytes must be filled wih 0x00.
For example:
If we typed 3 letters "A","A","A". Then 12 bytes should be written like this: 0x21, 0x21, 0x21, 0xFF, 0xFF, 0x00, 0x00 , 0x00, 0x00, 0xFF ,0xFF, 0xFF.
Or 5 letters: AAAAA. Then 12 bytes should be written like this: 0x21, 0x21, 0x21, 0x21, 0x21, 0xFF, 0xFF, 0x00, 0x00, 0xFF ,0xFF, 0xFF.
Or 7 letters: AAAAAAA. Then 12 bytes should be written like this: 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0xFF , 0xFF , 0xFF ,0xFF, 0xFF.
So, only if letters 7 or more, then other bytes must be filled with 0xFF.
Can you change the function: local function writeName(addr, name, len) , to write bytes as in the examples?
|
|
Back to top |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Mon Aug 13, 2018 7:06 am Post subject: |
|
|
strange but simple enough I suppose.
Code: | local function writeName(addr, name, len)
len = len or 12 -- default to 12
assert(#name < len, 'Name must be less than len (default 12)')
local bytes = {}
for i=1,#name do bytes[#bytes+1] = name:byte(i)-0x20 end
-- add 0xFF 0xFF 0x00 ... 0xFF 0xFF 0xFF, as possible
if len - #bytes > 5 then
bytes[#bytes+1] = 0xFF; bytes[#bytes+1] = 0xFF -- starting 0xFFs
end
if len - #bytes > 3 then -- if more room than last 3 0xFFs take fill with 0x0s
for i=#bytes,len-3 do bytes[#bytes+1] = 0 end
end
for i=#bytes,len do bytes[#bytes+1] = 0xFF end -- end with 0xFFs
writeBytes(addr, bytes)
end |
What if you had 8-12 letters (where you don't have room for the starting 2 and ending 3, edge cases matter as far as correctness)? ^ should just fill with 0xFFs in those cases (well, if the assert was changed to <= rather than < for 12) so hopefully that's correct, or simply not an issue in your case lol
_________________
|
|
Back to top |
|
|
Razi Expert Cheater Reputation: 1
Joined: 17 Jan 2018 Posts: 202
|
Posted: Mon Aug 13, 2018 8:07 am Post subject: |
|
|
FreeER wrote: | should just fill with 0xFFs in those cases |
Yes, if 7-11 letters, then other bytes after letters should be filled with 0xFF. Example: If 10 letters: "A", then should be like this: 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 00x21, 0x21, 0xFF, 0xFF. Or if 11 letters: "A", then 12 bytes should be written like this: eleven 0x21, and one 0xFF.
(Maximum 11 letters for name, because after letters should be at least one 0xFF)
New function writeName does not work correctly. I altered it a bit. Now it works as was needed.
Code: | local function writeName(addr, name, len)
len = len or 12 -- default to 12
assert(#name < len, 'Name must be less than len (default 12)')
local bytes = {}
for i=1,#name do bytes[#bytes+1] = name:byte(i)-0x20 end
-- add 0xFF 0xFF 0x00 ... 0xFF 0xFF 0xFF, as possible
if len - #bytes > 1 then
bytes[#bytes+1] = 0xFF; bytes[#bytes+1] = 0xFF -- starting 0xFFs
elseif len - #bytes == 1 then
bytes[#bytes+1] = 0xFF
end
if len - #bytes > 3 then -- if more room than last 3 0xFFs take fill with 0x0s
for i=#bytes,len-3 do bytes[#bytes+1] = 0 end
end
for i=#bytes,len do bytes[#bytes] = 0xFF end -- end with 0xFFs
writeBytes(addr, bytes)
end |
|
|
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
|
|