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 


Fixing Lua String Compare
Goto page Previous  1, 2, 3
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1530

PostPosted: Fri Jun 14, 2024 1:56 pm    Post subject: Reply with quote

Csimbi wrote:

Code:
Count: 541
4D006900730073006900
460075006E0064007300
460075006E0064007300
5400610073006B004400
54007200610076006500
54007200610076006500
55007000670072006100
4D006500630068005400
4D006500640054006500
45007800700065007200
45007800700065007200
44006900660066006900
53006800690070005400
4D006500630068004200
42006100720072006100



We printed it just so you could see the output (And of course I had to see what the address was printing Smile ).

I don't know if you had a chance to check the outputs manually; Did it contain the codes "75007000650052" or "52006500700075"?

If so, the code should work.
This is an option added to replace the "readQword" pattern of your original code.

Play with this code some more and shift the offsets until you get the results you want. (Ah, just the idea of ​​course, otherwise the code you created is too complex and advanced for me. Smile )

_________________
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
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3326

PostPosted: Sun Jun 16, 2024 2:50 pm    Post subject: Reply with quote

AylinCE wrote:

We printed it just so you could see the output (And of course I had to see what the address was printing Smile ).

Well, yes, this works, but we are not looking for a string in a string Very Happy
We are looking for a fixed array.
And srtsrt-like call would be nice.
Back to top
View user's profile Send private message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1530

PostPosted: Sun Jun 16, 2024 5:15 pm    Post subject: Reply with quote

Now see what kind of result it will print.
Added "stringFromHex(aobs)".
This will allow you to get the aobs results as a string.
If this path is correct, the next step will be to compare the results as string or aobs.
Or you may need to scroll the address a little further and test the results.
Code:
[ENABLE]
{$lua}
if syntaxcheck then return end

for i=memrec.Count-1,0,-1 do
  memrec.Child[i].delete()
end

local pStatsAddress=readPointer("pStats")
local count
--------------------------------------------------
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 stringFromHex(aobs)
local fmttext = ""
 for wrd in aobs:gmatch("%x%x") do
   num = tonumber(wrd,16)
   --print("\nFormat byte:\n"..wrd.." to "..num)
    if num~=0 then
      fmttext = fmttext..string.char(tonumber(num))
    else
     fmttext = fmttext..""
    end
 end
return fmttext
end
---------------------------------------------------

if pStatsAddress~=nil and pStatsAddress~=0 then
  print(string.format("pStats: %X", pStatsAddress))
  count = readInteger('[[pStats]+18]+40')
  if count~=nil then print(string.format("Count: %d", count)) end
end

if count==nil then ShowMessage('Invalid pointer; refresh pointer and try again!')
elseif count <=0 then ShowMessage('No items found.')
elseif count >1000 then ShowMessage('Too many items; wrong pointer? Refresh pointer and try again!')
else
  AddressList.List.beginUpdate()
  for i=0, count do
    local iEntryLen = readInteger('[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+28]+10')
    -------------------------------------------------------------------------------------
    local addr1 = getAddress('[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+28]+14')
    local resultAobs1 = getByteString(addr1, 10)
    -- getByteString(addr1, 80) --> It is possible to query the word you are looking for in the longer aobs signature. Just increase the byte.
    if resultAobs1~=nil then print(resultAobs1) print(stringFromHex(resultAobs1)) end -- Check out what's in the results and see if it's what you're looking for!
    -------------------------------------------------------------------------------------
    if iEntryLen~=nil and iEntryLen > 11 and iEntryLen <35 then
     ------------------------------------------------------------------------------------
     if string.find(resultAobs1,"75007000650052") or string.find(resultAobs1,"52006500700075") then -- 75007000650052 = upeR .. 52006500700075 = Repu
     ------------------------------------------------------------------------------------
      local mr = AddressList.createMemoryRecord()
      mr.description = 'Stats['..(i)..']'
      mr.Type = vtString
      mr.String.Size = 64
      mr.String.Unicode = true
      mr.Address = '[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+28]+14'
      mr.Color = 0x0000FF
      mr.appendToEntry(memrec)

      local mrchild = AddressList.createMemoryRecord()
      mrchild.description = 'iRelationshipValue'
      mrchild.Type = vtDword --vtSingle
      mrchild.ShowAsSigned = true
      mrchild.Address = '[[[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+30]+18]+20]+10'
      mrchild.Color = 0xFF0000
      mrchild.appendToEntry(mr)
     end
    end
  end
  AddressList.List.endUpdate()
end
{$asm}

[DISABLE]
{$lua}
if syntaxcheck then return end
AddressList.List.beginUpdate()
for i=memrec.Count-1,0,-1 do
  memrec.Child[i].delete()
end
AddressList.List.endUpdate()
{$asm}

_________________
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
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3326

PostPosted: Mon Jun 17, 2024 11:13 am    Post subject: This post has 1 review(s) Reply with quote

Output looks good.

Code:
pStats: 23ED3720A40
Count: 552
4D006900730073006900
Missi
54007200610076006500
Trave
55007000670072006100
Upgra
4D006500630068005400
MechT
4D006500640054006500
MedTe
45007800700065007200
Exper
43004F004D0050004100
COMPA

And so on...
Got 65 memrecs (they all look good), though I did progress in the game so there might be new ones.
Back to top
View user's profile Send private message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1530

PostPosted: Mon Jun 17, 2024 1:54 pm    Post subject: Reply with quote

Sometimes I cannot fully understand the questions.
Instead, I try to approach the question with code examples.
I hope the final codes come close to your answer (Solution).

Now there is an example entry in the link you provided;
Code:
--[[
int main () {
   const char haystack[20] = "TutorialsPoint";
   const char needle[10] = "Point";
   char *ret;

   ret = strstr(haystack, needle);

   printf("The substring is: %s\n", ret);

   return(0);
}
--]]

function strstr(haystack, needle)
local res = ""
  if string.find(haystack, needle) then
    res = "'"..needle.."' available!"
  else
   res = "'"..needle.."' not available!"
  end
return res
end

haystack = "TutorialsPoint"
needle = "Point"

ret = strstr(haystack, needle)

printf("The substring is: %s\n", ret)

-- > result: The substring is: Point available!



Note: It's still complicated for me since you have advanced coding (Especially asm.). I hope the codes you share continue to reach more users as "Archive".

Respects..

_________________
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
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3326

PostPosted: Tue Jun 18, 2024 12:19 pm    Post subject: Reply with quote

AylinCE wrote:
Sometimes I cannot fully understand the questions.
Instead, I try to approach the question with code examples.

I'm sure I'm the one asking the question the wrong way.
I learned long ago that the working code is the universal language.

So, I made the updates, but I am pretty sure I screwed up because now I get nothing:
Code:

[ENABLE]
{$lua}
if syntaxcheck then return end

for i=memrec.Count-1,0,-1 do
  memrec.Child[i].delete()
end

local pStatsAddress=readPointer("pStats")
local count
--------------------------------------------------
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 stringFromHex(aobs)
local fmttext = ""
 for wrd in aobs:gmatch("%x%x") do
   num = tonumber(wrd,16)
   --print("\nFormat byte:\n"..wrd.." to "..num)
    if num~=0 then
      fmttext = fmttext..string.char(tonumber(num))
    else
     fmttext = fmttext..""
    end
 end
return fmttext
end

function strstr(haystack, needle)
local res = ""
  if string.find(haystack, needle) then
    res = "'"..needle.."' available!"
  else
   res = "'"..needle.."' not available!"
  end
return res
end
---------------------------------------------------

if pStatsAddress~=nil and pStatsAddress~=0 then
  print(string.format("pStats: %X", pStatsAddress))
  count = readInteger('[[pStats]+18]+40')
  if count~=nil then print(string.format("Count: %d", count)) end
end

if count==nil then ShowMessage('Invalid pointer; refresh pointer and try again!')
elseif count <=0 then ShowMessage('No items found.')
elseif count >1000 then ShowMessage('Too many items; wrong pointer? Refresh pointer and try again!')
else
  --AddressList.List.beginUpdate()
  for i=0, count do
    local iEntryLen = readInteger('[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+28]+10')
    -------------------------------------------------------------------------------------
    if iEntryLen~=nil and iEntryLen > 11 and iEntryLen <35 then
      local addrS = getAddress('[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+28]+14')
      local sS=readStringLocal(addrS, 100, true)
      if sS~=nil and strstr(sS,"Reputation.") then
        local mr = AddressList.createMemoryRecord()
        mr.description = 'Stats['..(i)..']'
        mr.Type = vtString
        mr.String.Size = 64
        mr.String.Unicode = true
        mr.Address = '[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+28]+14'
        mr.Color = 0x0000FF
        mr.appendToEntry(memrec)

        local mrchild = AddressList.createMemoryRecord()
        mrchild.description = 'iRelationshipValue'
        mrchild.Type = vtDword --vtSingle
        mrchild.ShowAsSigned = true
        mrchild.Address = '[[[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+30]+18]+20]+10'
        mrchild.Color = 0xFF0000
        mrchild.appendToEntry(mr)
      end
    end
  end
  --AddressList.List.endUpdate()
end
{$asm}

[DISABLE]
{$lua}
if syntaxcheck then return end
AddressList.List.beginUpdate()
for i=memrec.Count-1,0,-1 do
  memrec.Child[i].delete()
end
AddressList.List.endUpdate()
{$asm}
Back to top
View user's profile Send private message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1530

PostPosted: Tue Jun 18, 2024 1:22 pm    Post subject: Reply with quote

"Reputation." Is the aobs value of the "." at the end "2E" or "00"?

Edited version of the code.

Code:
[ENABLE]
{$lua}
if syntaxcheck then return end

for i=memrec.Count-1,0,-1 do
  memrec.Child[i].delete()
end

local pStatsAddress=readPointer("pStats")
local count
--------------------------------------------------
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 stringFromHex(aobs)
local fmttext = ""
aobs1 = aobs:gsub(" ","")
 for wrd in aobs1:gmatch("%x%x") do
   num = tonumber(wrd,16)
   --print("\nFormat byte:\n"..wrd.." to "..num)
    if num~=0 then
      fmttext = fmttext..string.char(tonumber(num))
    else
     fmttext = fmttext..""
    end
 end
return fmttext
end

---------------------------------------------------

if pStatsAddress~=nil and pStatsAddress~=0 then
  print(string.format("pStats: %X", pStatsAddress))
  count = readInteger('[[pStats]+18]+40')
  if count~=nil then print(string.format("Count: %d", count)) end
end

if count==nil then ShowMessage('Invalid pointer; refresh pointer and try again!')
elseif count <=0 then ShowMessage('No items found.')
elseif count >1000 then ShowMessage('Too many items; wrong pointer? Refresh pointer and try again!')
else
  --AddressList.List.beginUpdate()
  for i=0, count do
    local iEntryLen = readInteger('[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+28]+10')
    -------------------------------------------------------------------------------------
    if iEntryLen~=nil and iEntryLen > 11 and iEntryLen <35 then
      local addrS = getAddress('[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+28]+14')
      local sS=getByteString(addrS,64) -- 0~64 byte full aobs (mr.String.Size)
      print(i.."- 64 bytes of aob output;\n"..sS)
      local str1 = stringFromHex(sS) -- (string result) or readString(sS)
      print(i.."- Aob's string format;;\n"..str1)
      if str1~=nil and string.find(str1,"Reputation%.") then -- use: string.find(string,search)
        local mr = AddressList.createMemoryRecord()
        mr.description = 'Stats['..(i)..']'
        mr.Type = vtString
        mr.String.Size = 64
        mr.String.Unicode = true
        mr.Address = '[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+28]+14'
        --mr.Value = str1
        mr.Color = 0x0000FF
        mr.appendToEntry(memrec)

        local mrchild = AddressList.createMemoryRecord()
        mrchild.description = 'iRelationshipValue'
        mrchild.Type = vtDword --vtSingle
        mrchild.ShowAsSigned = true
        mrchild.Address = '[[[[[[pStats]+18]+18]+18*'..string.format('%x',i)..'+30]+18]+20]+10'
        mrchild.Color = 0xFF0000
        mrchild.appendToEntry(mr)
      end
    end
  end
  --AddressList.List.endUpdate()
end
{$asm}

[DISABLE]
{$lua}
if syntaxcheck then return end
AddressList.List.beginUpdate()
for i=memrec.Count-1,0,-1 do
  memrec.Child[i].delete()
end
AddressList.List.endUpdate()
{$asm}


If there is still a problem with "Unicode" characters, I can add something about it.

_________________
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
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3326

PostPosted: Thu Jun 20, 2024 11:49 am    Post subject: Reply with quote

AylinCE wrote:
"Reputation." Is the aobs value of the "." at the end "2E" or "00"?


That last character is a dot.

Perfect, this works great!

Only issue is, it reads bytes it's not supposed to because we are not reading a string, we are reading 64 bytes and converting that to hex.
Produces results like this:
Code:
Influence.Kurita??????tE?rz*?

Might be an issue when reading unallocated memory in the future.
However, it does indeed find entries where 'Reputation.' is not at the beginning - yei!

ParkourPenguin said when we read it as string, UTF-16 gets converted to UTF-8 internally. I thought we could leverage that somehow.
I did not think it would be this difficult in LUA...
Anyway, good enough, thank you!
Much appreciated!
I'll tidy it up and post the updated script.

May I ask what's the purpose of the % sign in the string?
Code:
string.find(str1,"Reputation%.")
Back to top
View user's profile Send private message
AylinCE
Grandmaster Cheater Supreme
Reputation: 37

Joined: 16 Feb 2017
Posts: 1530

PostPosted: Thu Jun 20, 2024 12:21 pm    Post subject: Reply with quote

Code:
string.find(str1,"Reputation%.")



Lua (20.2 – Patterns) wrote:
Some characters, called magic characters, have special meanings when used in a pattern. The magic characters are

( ) . % + - * ? [ ^ $
The character `%´ works as an escape for those magic characters. So, '%.' matches a dot; '%%' matches the character `%´ itself. You can use the escape `%´ not only for the magic characters, but also for all other non-alphanumeric characters. When in doubt, play safe and put an escape.


When in doubt, it is best to use the escape character (%). Smile

_________________
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
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting All times are GMT - 6 Hours
Goto page Previous  1, 2, 3
Page 3 of 3

 
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