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 


Write text with encoding technique

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
Razi
Expert Cheater
Reputation: 1

Joined: 17 Jan 2018
Posts: 205

PostPosted: Fri Jun 07, 2024 3:29 pm    Post subject: Write text with encoding technique Reply with quote

I have question about, how to write a text under a certain condition. The text/bytes must be written through the edit box. The conditions are: if the previous 64 bytes from the current symbol in the edit box contain 10/8/6/4 the same characters or bytes, then insert 0xF9 and a certain value. Below, a more detailed explanation.
Example of two items description in game: (raw data and decoded text)
Code:
32 45 53 54 4F 52 45 53 00 4C 49 46 45 FF 23 55 F9 0A 3B 30 4F 49 53 4F 4E 3D FF  --"0xFF-means end of text"
R  e  s  t  o  r  e  s     l  i  f  e     C  u "res " [  P  o  i  s  o  n  ]

23 55 F9 0A 3B 30 4F 49 53 4F 4E 3D FF - Cures [Poison]

F9: This is an encoding technique designed to make the raw data smaller. A byte following the 0xF9 will tell the game's memory the location of, and how much, text to read.

byte following the 0xF9 in binary:
YYXXXXXX
Where YY is the number of bytes to read:
number of bytes to read uses the formula: no_of_bytes = (YY) * 2 + 4 [Where YY is binary]. And XXXXXX + 1 is how far back from the F9 byte to look.

F9 0A
0x0A = 00 001010 in binary. Means go back 11 bytes from the F9 and read four characters. In the description we have one F9 function, that references the "res ", in bytes: "52 45 53 00". (We can have more than one F9 functions in the text description)

In this example: If CEEdit1 has text: Cures [Poison], I need to write bytes like this: 23 55 F9 0A 3B 30 4F 49 53 4F 4E 3D FF.

Example of two commands description in game: (raw data and decoded text)
Code:
35 53 45 00 41 56 41 49 4C 41 42 4C 45 00 49 54 45 4D FF 33 54 45 41 4C F9 4A FF  --"0xFF-end of text"
U  s  e     a  v  a  i  l  a  b  l  e     i  t  e  m     S  t  e  a  l  " item" --here F9 4A reads "00 49 54 45 4D FF"

33 54 45 41 4C F9 4A FF - Steal item
F9 4A
0x4A = 01 001010 in binary. Means go back 11 bytes from the F9 and read six characters/bytes.
In the description we have one F9 function, that references the " item", in bytes: "00 49 54 45 4D FF".

In this example: If CEEdit1 has text: Steal item, I need to write bytes like this: 33 54 45 41 4C F9 4A FF.

Main question is: How to redo the writeNameDesc function to insert (0xF9) byte not at the end of the bytes table, but in the right place? Other functions (decodeText and UDF1_CEEdit1.OnKeyPress) work correctly. What can you recommend in this situation?
Here's the code:
Code:
function decodeText(address,length) --function to read text
  local str = ''
  local charCount=0
  local bytelen=0
  local byte1,byte2 = readBytes(address,2)

  while byte1~=0xFF do
    if byte1==0xF9 then
      charCount = charCount + (byte2 >> 6) * 2 +4
      str = str .. decodeText( address-1-(byte2 & 0x3F) , (byte2 >> 6) * 2 +4 )
      address = address + 1
      bytelen = bytelen + 2

    else
      charCount = charCount + 1
      bytelen = bytelen + 1
      str = str .. string.char(byte1+0x20)
    end

    if length and (length==charCount) then break end

    address = address + 1
    byte1,byte2 = readBytes(address,2)
  end

  return str, bytelen
end


local function writeNameDesc(addr, name, len)  --function to write text, where 'name' is text in UDF1_CEEdit1, len = #CEEdit1.Text + 1
  len = len or 92 -- default to 92
  assert(#name < len+1, 'Name must be less than len (default 92)')
  local bytes = {}
  for i=1,#name do bytes[#bytes+1] = name:byte(i)-0x20 end

  for y=3, 0, -1 do
  local str1 = string.sub(name, -4-y*2, -1) --get 10/8/6/4 characters from edit box, starting from end of string
  for x=1, 64 do
  local str2 = decodeText(addr+len-x-6-y*2, 4+y*2) --read previous text
    if str1 == str2 then
    bytes[#bytes+1] = 0xF9; bytes[#bytes+1] = (y<<6) | x-1   --insert 0xF9
    break --exit from loop: for x=1, 64
    end
  end
    if str1 == str2 then
    break --exit from second loop: for y=3, 0, -1
    end
  end

  if len - #bytes == 1 then
    bytes[#bytes+1] = 0xFF --bytes table should end with 0xFF
  end

  writeBytes(addr, bytes)
end


UDF1_CEEdit1.OnKeyPress = function(sender, key)
local a = sender.Text
  if (a~='') and isKeyPressed(VK_RETURN) then

    local len = #sender.Text

    writeNameDesc(0x009AF600, sender.Text, len+1) --function to write text

    sender.Tag = #sender.Text
  end
  return key
end
Back to top
View user's profile Send private message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1530

PostPosted: Fri Jun 14, 2024 7:17 am    Post subject: Reply with quote

Code:
35 53 45 00 41 56 41 49 4C 41 42 4C 45 00 49 54 45 4D FF 33 54 45 41 4C F9 4A FF  --"0xFF-end of text"
U  s  e     a  v  a  i  l  a  b  l  e     i  t  e  m     S  t  e  a  l  " item" --here F9 4A reads "00 49 54 45 4D FF"


Tell me this; Are you planning to replace the code written in CEEdit1 with "steal"?
Otherwise, do you want to go back by the number of bytes (+1) after "f9" and write the code in CEEdit1 from there?

The following can be done; The code can be searched and the aob output can be obtained.
"F9" can be searched in the output and the next byte can be copied.
By going back by the copied byte, the text in CEEdit1 (formatted as aob) can be replaced with the current partition.
"F9 XX" can be written at the end of the changed section.

However, this change in the entire code may result in a meaningless sentence.

Where exactly do you want to paste the text from CEEdit1 and what addition (for "F9", if any) do you want to make after the change?

Also, your posts still do not appear as notifications on the CEF homepage. Did you tell this to DB?

_________________
Hi Hitler Different Trainer forms for you!
https://forum.cheatengine.org/viewtopic.php?t=619279
Enthusiastic people: Always one step ahead
Do not underestimate me Master: You were a beginner in the past
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Razi
Expert Cheater
Reputation: 1

Joined: 17 Jan 2018
Posts: 205

PostPosted: Fri Jun 21, 2024 2:21 pm    Post subject: Reply with quote

AylinCE wrote:
Are you planning to replace the code written in CEEdit1 with "steal"?
Otherwise, do you want to go back by the number of bytes (+1) after "f9" and write the code in CEEdit1 from there?
Sorry for the late reply, I have not seen your post.

Code:
32 45 53 54 4F 52 45 53 00 4C 49 46 45 FF 23 55 F9 0A 3B 30 4F 49 53 4F 4E 3D FF  --"0xFF - end of text"
R  e  s  t  o  r  e  s     l  i  f  e     C  u "res " [  P  o  i  s  o  n  ]
where F9 0A is a link to previous substring(part of the string): 52 45 53 00 = "res ". F9 0A: (0A+1) go back 11 bytes from the F9 and display four characters.

It is a little hard to explain. I need: If CEEdit1 has text: Cures [Poison], and "Enter" button was pressed I need to write bytes in address 0x009B0BB1 (address does not matter): 23 55 52 45 53 00 3B 30 4F 49 53 4F 4E 3D FF and this code already does this: for i=1,#name do bytes[#bytes+1] = name:byte(i)-0x20 end.
But, if previous bytes (converted to string) has same part of the string as part of the string in CEEdit1 and they match, then we need to count the number of bytes that we need to go back from part of the string in the CEEdit1.
For example: CEEdit1 text: Cures [Poison], "res " starts from 3-rd character, it is 3-rd byte (0xF9), then we need to count how many bytes we need to go back to find same part of the string "res ". In the example above "res " is located by 11 bytes back, and we need to get this value, to know which value to insert after 0xF9 to write bytes with CEEdit1 when we press "Enter" button and write bytes like this: 23 55 F9 0A 3B 30 4F 49 53 4F 4E 3D FF.

I have such a code for now, but it does not work correctly:
Code:
local function writeNameDesc(addr, name, len) --where 'name' is text in CEEdit1, len = #CEEdit1.Text + 1
  len = len or 92 -- default to 92
  --assert(#name < len+1, 'Name must be less than len (default 92)')
  local bytes = {}

  local b1,b2,afterF9 = 0,0,0
  for i=1, #name do
  for y=3, 0, -1 do
  local str1 = string.sub(name, -3-i-y*2, -i)
  for x=1, 64 do
  local str2 = decodeText(addr+len-x-5-i-y*2, 4+y*2)
    if str1 == str2 and str1~='' then
    b1,b2 = string.find(name, str1)
    afterF9 = (y<<6) | (x-1+b1)
    break
    end
  end
    if str1 == str2 then
    break
    end
  end
  end

  for i=1,#name do
  if i < b1 or i > b2 then
  bytes[#bytes+1] = name:byte(i)-0x20
  elseif i == b1 then
  bytes[#bytes+1] = 0xF9; bytes[#bytes+1] = afterF9
  end
  end

  if len - #bytes == 1 then
    bytes[#bytes+1] = 0xFF
  end


  writeBytes(addr, bytes)
end

UDF1_CEEdit1.OnKeyPress = function(sender, key)
local a = sender.Text
  if (a~='') and isKeyPressed(VK_RETURN) then
    local len = #sender.Text

    writeNameDesc(0x009B0BB1, sender.Text, len+1) --function to write text
    sender.Tag = #sender.Text
  end
  return key
end


"Steal item" example is a little more complicated, because there 0xFF at the end of the string, to which the 0xF9 refers.
The code for reading the text has already been written. The decodeText function does this.



01.JPG
 Description:
The design is mainly copied from another tool, with the permission of the author.
 Filesize:  114.77 KB
 Viewed:  3016 Time(s)

01.JPG




Last edited by Razi on Sat Jun 22, 2024 3:20 am; edited 2 times in total
Back to top
View user's profile Send private message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1530

PostPosted: Fri Jun 21, 2024 7:55 pm    Post subject: Reply with quote

1) Formats the code in Edit1 as hex.
2) It takes hex output equal to the given number of bytes of the address. (s1)
3) It scans "F9" in S1 and gets the number of bytes how far it will go back in the next byte. (f9rtn)
4) "bytcnt" creates the new address from where "f9rtrn" points with "num" and "byt" and at the same time the new byte number is added after "f9" for the new aobs code. (Recalculating as many bytes as the content of #Edit1.)
5) With "newcode", all results are combined and a new code is created.
6) Lastly, "newAddr" is replaced with "newcode".

Since the code is regenerated, old and new code lengths are not calculated.

In any transaction to try the code, you can type "E8 03 00 00 ???? ???? Scan aobs and pull down a result and replace the value with the existing code.
change: "32 45 53 54 4F 52 45 53 00 4C 49 46 45 FF 23 55 F9 0A 3B 30 4F 49 53 4F 4E 3D FF"

Copy the address and replace it with the "addr" value in the "CEEdit1.OnKeyPress" function and start the test.


Code:
if myForm1 then myForm1.Destroy() myForm1=nil end
DP1=getScreenDPI()/96
myForm1=createForm()
myForm1.height=115*DP1 myForm1.width=658*DP1 myForm1.left=395*DP1 myForm1.top=109*DP1
myForm1.PopupMode=0 myForm1.caption="Test"
myForm1.Position="poDesktopCenter" myForm1.ShowInTaskBar="stAlways"
myForm1.BorderStyle="bsSingle"
-------------------------
local UDF1 = {}
----------------------- UDF1.CEEdit1 ----- 
UDF1.CEEdit1=createEdit(myForm1)
UDF1.CEEdit1.AutoSize=true
UDF1.CEEdit1.height=23*DP1 UDF1.CEEdit1.width=96*DP1 UDF1.CEEdit1.left=11*DP1 UDF1.CEEdit1.top=58*DP1
UDF1.CEEdit1.text=""
UDF1.CEEdit1.alignment="taLeftJustify"
UDF1.CEEdit1.Font.Style="fsBold" UDF1.CEEdit1.Font.Size=0*DP1
-----------------------
----------------------- UDF1.CEEdit2 ----- 
UDF1.CEEdit2=createEdit(myForm1)
UDF1.CEEdit2.AutoSize=true
UDF1.CEEdit2.height=23*DP1 UDF1.CEEdit2.width=644*DP1 UDF1.CEEdit2.left=5*DP1 UDF1.CEEdit2.top=11*DP1
UDF1.CEEdit2.alignment="taLeftJustify"
UDF1.CEEdit2.Font.Style="fsBold" UDF1.CEEdit2.Font.Size=0*DP1
-----------------------

--############################################################################--
--############################################################################--
UDF1.CEEdit1.text="Cures [Poison]"
UDF1.CEEdit2.text=""

function getByteString(address, bytecount)
 local bytes = readBytes(address, bytecount, true)
 if bytes then
 local result = ""
 for i = 1, #bytes do
 if #result > 0 then result = result .. " " end
 result = result .. string.format("%02X", bytes[i]) end
 return result end
end

function getStringByte(val)
t = stringToByteTable(val)
  for k,v in ipairs(t) do
    t[k] = ('%02X'):format(v)
  end
  return table.concat(t, ' ')
end

function calByteRange(addr,val)
local s1 = getByteString(addr, 27)
UDF1.CEEdit2.text=s1
val1 = getStringByte(val)
val1 = val1:gsub("20","00")
local s2 = "" -- FF ~ F9
local s3 = "" -- f9 ?? ~ find aobs
local f9rtrn = ""
local wrdFind = "" -- addr ~ FF
local r1 = false
local r2 = false
local r3 = false
local byt = ""
local bytcnt = 0
local num = 0
  for wrd in s1:gmatch("%x%x") do
    if r3==true then s2 = s2..wrd.." "   end
    if wrd=="FF" then r3=true end
    if r2==true then s3 = s3..wrd.." " end
    if r1==true then
      f9rtrn = string.format("%02X", tonumber(wrd,16) + 1)
      r1=false r2=true
      num=tonumber(bytcnt) - tonumber(f9rtrn,16) - 1 --print(num)
      byt = string.format("%02X",  tonumber(num))
    end
    if wrd=="F9" then r1=true r3=false end
    bytcnt = tonumber(bytcnt) + 1
    --print(wrd)
  end
   local newAddr = addr.."+"..byt
   local s4 = getByteString(newAddr, 20)

    newcode = val1.." FF "..s2..f9rtrn.." "..s3
    print("s1: "..s1)
    print("s2: "..s2)
    print("s3: "..s3)
    print("f9rtrn: "..f9rtrn)
    print("new byte: "..byt)
    print("addr aobs: "..s4)
    print("new code: "..newcode)
     autoAssemble(newAddr..":\ndb "..tostring(newcode))
end


UDF1.CEEdit1.OnKeyPress = function(sender, key)
local a = sender.Text
  if (a~='') and isKeyPressed(VK_RETURN) then
    addr = "070AFC1C"
    val = UDF1.CEEdit1.Text
    --print(val)
    calByteRange(addr,val)
  end
  return key
end

_________________
Hi Hitler Different Trainer forms for you!
https://forum.cheatengine.org/viewtopic.php?t=619279
Enthusiastic people: Always one step ahead
Do not underestimate me Master: You were a beginner in the past
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Razi
Expert Cheater
Reputation: 1

Joined: 17 Jan 2018
Posts: 205

PostPosted: Sun Jun 23, 2024 9:16 am    Post subject: Reply with quote

Thank you, I’m testing your code for now.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting 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