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 


Problem with my code?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
the_elemental_of_creation
How do I cheat?
Reputation: 0

Joined: 19 Jul 2017
Posts: 5

PostPosted: Thu Jul 27, 2017 11:36 am    Post subject: Problem with my code? Reply with quote

Recently I have been trying to work on a code that will scan all memory regions from 0x00000000 to 0xffffffff to return a table containing the address of all values that are equal to the variable "value" and have run into a problem where my code causes cheat engine to stop responding, and will never finish. After doing a bunch of investigating into what cheat engine was doing while it was not responding, I found that the code was in fact continuing to execute. If anyone can tell me what the problem with my code is that would be greatly appreciated.

Code:
openProcess([process name])
maxMem=0xffffffff
function scanForVal(value,type,...)
--Ignore the variable "type" as it is not yet implemented properly
if #arg==0 then
    local tabl={}
    for x=0,maxMem,2 do
        if readInteger(x)==value then
            table.insert(tabl,x)
            print(x)
        end
    end
    return(tabl)
end

local x=1
end

a=scanForVal(22500,1)
Back to top
View user's profile Send private message
ParkourPenguin
Grandmaster Cheater Supreme
Reputation: 51

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

PostPosted: Thu Jul 27, 2017 12:50 pm    Post subject: Reply with quote

That code shouldn't run in the first place since arg isn't defined. If you want to use Lua 5.0 vararg features, put this line at the beginning of the function:
Code:
local arg = {...}


Executing that code should take more than an hour to complete. If you want to do it quickly, let CE do it for you. Here's a simple implementation using aobscan:
Code:
function scanForVal(value, type)
  local bt
  if type == vtDword then
    bt = dwordToByteTable(value)
  elseif type == vtSingle then
    bt = floatToByteTable(value)
--elseif  etc...
  end

  for i,v in ipairs(bt) do
    bt[i] = string.format('%02X', bt[i])
  end

  local t,res = {},AOBScan(table.concat(bt,' '), '-X-C+W', fsmAligned, '4')

  for i=0, res.Count-1 do
    t[i+1] = res[i]  -- results are strings by default
  end

  res.destroy()
  return t
end


local t = scanForVal(1, vtSingle)
for _,v in ipairs(t) do
  print(v)
end

Use memscan class for more advanced stuff (e.g. specifying start/stop region, next scans, value between scans, etc.).

_________________
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
the_elemental_of_creation
How do I cheat?
Reputation: 0

Joined: 19 Jul 2017
Posts: 5

PostPosted: Thu Jul 27, 2017 1:07 pm    Post subject: Reply with quote

ParkourPenguin wrote:
That code shouldn't run in the first place since arg isn't defined. If you want to use Lua 5.0 vararg features, put this line at the beginning of the function:
Code:
local arg = {...}


You see that "..." in the function that I had defined? That is the table arg, defined by lua for the function. Any additional arguments in the function (this function is designed to take an "infinite" (only limited by lua's capabilities) number of arguments) are put into the table arg. If you were to do, for example,
Code:
function test(...)
    for x=1,#arg do
        print(arg[1])
    end
end
test("hello",35,"see")

the output would be
Code:
hello
35
see


Also, if arg was not defined,
Code:
#arg
would not work.

I will try your code example when I have a chance, but I need to know, is the output for scanForVal() a table in your example?
Back to top
View user's profile Send private message
ParkourPenguin
Grandmaster Cheater Supreme
Reputation: 51

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

PostPosted: Thu Jul 27, 2017 1:23 pm    Post subject: Reply with quote

You're using an old version of CE then. Under the current version of CE, this code:
Code:
local function f(...)
  print(type(arg))
  print(...)
end
f('str')
has this output:
Code:
nil
str

Read this section of the Lua 5.3 reference manual for more information. Specifically:
Quote:
A vararg function does not adjust its argument list; instead, it collects all extra arguments and supplies them to the function through a vararg expression, which is also written as three dots. The value of this expression is a list of all actual extra arguments, similar to a function with multiple results.


the_elemental_of_creation wrote:
...is the output for scanForVal() a table in your example?

In my example, scanForVal returns a table of strings properly formatted as a Lua array (i.e. contiguous integer indices starting at 1).

_________________
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
the_elemental_of_creation
How do I cheat?
Reputation: 0

Joined: 19 Jul 2017
Posts: 5

PostPosted: Thu Jul 27, 2017 1:38 pm    Post subject: Reply with quote

ParkourPenguin wrote:
You're using an old version of CE then. Under the current version of CE, this code:
Code:
local function f(...)
  print(type(arg))
  print(...)
end
f('str')
has this output:
Code:
nil
str

Read this section of the Lua 5.3 reference manual for more information. Specifically:
Quote:
A vararg function does not adjust its argument list; instead, it collects all extra arguments and supplies them to the function through a vararg expression, which is also written as three dots. The value of this expression is a list of all actual extra arguments, similar to a function with multiple results.


the_elemental_of_creation wrote:
...is the output for scanForVal() a table in your example?

In my example, scanForVal returns a table of strings properly formatted as a Lua array (i.e. contiguous integer indices starting at 1).

Okay, so my new code is
Code:
openProcess([process name])
maxMem=0xffffffff
function scanForVal(value,type,...)
local arg={...}
--Ignore the variable "type" as it is not yet implemented properly
if #arg==0 then
    local tabl={}
    for x=0,maxMem,2 do
        if readInteger(x)==value then
            table.insert(tabl,x)
            print(x)
        end
    end
    return(tabl)
end

local x=1
end

a=scanForVal(22500,1)


Why would this code never finish executing even after more than 5 hours?
Back to top
View user's profile Send private message
ParkourPenguin
Grandmaster Cheater Supreme
Reputation: 51

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

PostPosted: Thu Jul 27, 2017 1:57 pm    Post subject: Reply with quote

Because it takes a long time to scan through over 2 billion values with a single thread in Lua. Try testing it at a lower number and see how long it takes. For example:
Code:
local maxMem = 0x100000
function scanForVal(value, type)
  local tBeg = getTickCount()
  local tabl = {}
  for x=0, maxMem, 2 do
    assert(getTickCount() - tBeg < 60000, 'timeout')  -- timeout after 1 minute
    if readInteger(x) == value then
      table.insert(tabl,x)
    end
  end
  print('Milliseconds elapsed:', getTickCount() - tBeg)
  return(tabl)
end

scanForVal(22500,1)

Scanning through the first 256 pages of memory of the CE Tutorial takes a little over a second for me.

_________________
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
panraven
Grandmaster Cheater
Reputation: 26

Joined: 01 Oct 2008
Posts: 652

PostPosted: Thu Jul 27, 2017 2:47 pm    Post subject: Reply with quote

Reading remote memory has a much high overhead than local memory
because the inter-process mechanism eg. through readProcessMemory API.
so it is better to have a buffer to batch read local memory of remote process,
with larger size the batch, then to have a lesser number of inter-process transfer eg.
to read A*B unit of remote memory, it is better to do
A times of remote transfer, by reading B unit buffer of local memory each than
A*B times of remote transfer of 1 unit of local memory read each.

Lua function readBytes can use as such buffer, but care should be make that the buffer size should match the memory region granularity (1K or 4K ?) , can there may be instance of reading a unreadable region etc.

ParkourPenguin's AOBScan solution should be better than buffer approach since less care of the detail.

_________________
- Retarded.
dropbox
Back to top
View user's profile Send private message
the_elemental_of_creation
How do I cheat?
Reputation: 0

Joined: 19 Jul 2017
Posts: 5

PostPosted: Thu Jul 27, 2017 4:04 pm    Post subject: Reply with quote

ParkourPenguin wrote:
That code shouldn't run in the first place since arg isn't defined. If you want to use Lua 5.0 vararg features, put this line at the beginning of the function:
Code:
local arg = {...}


Executing that code should take more than an hour to complete. If you want to do it quickly, let CE do it for you. Here's a simple implementation using aobscan:
Code:
function scanForVal(value, type)
  local bt
  if type == vtDword then
    bt = dwordToByteTable(value)
  elseif type == vtSingle then
    bt = floatToByteTable(value)
--elseif  etc...
  end

  for i,v in ipairs(bt) do
    bt[i] = string.format('%02X', bt[i])
  end

  local t,res = {},AOBScan(table.concat(bt,' '), '-X-C+W', fsmAligned, '4')

  for i=0, res.Count-1 do
    t[i+1] = res[i]  -- results are strings by default
  end

  res.destroy()
  return t
end


local t = scanForVal(1, vtSingle)
for _,v in ipairs(t) do
  print(v)
end

Use memscan class for more advanced stuff (e.g. specifying start/stop region, next scans, value between scans, etc.).


So, after a few tweaks to change the way it works with the values the code works perfectly for my needs. Thanks for your help. This is the new code:
Code:
openProcess([process name])
function DEC_HEX(IN)
    local B,K,OUT,I,D=16,"0123456789ABCDEF","",0
    while IN>0 do
        I=I+1
        IN,D=math.floor(IN/B),math.mod(IN,B)+1
        OUT=string.sub(K,D,D)..OUT
    end
    return OUT
end
function scanForVal(value,type,...)
  local bt
  local arg={...}
  if type==vtDword then
    bt=dwordToByteTable(value)
  elseif type==vtSingle then
    bt=floatToByteTable(value)
--elseif  etc...
  end

  for i,v in ipairs(bt) do
    bt[i] = string.format('%02X', bt[i])
  end

  local t,res={},AOBScan(table.concat(bt,' '),'-X-C+W',fsmAligned,'4')

  for i=0,res.Count-1 do
    t[i+1] = res[i]  -- results are strings by default
  end

  res.destroy()
  local g=0
  --[[
Hello there. Let me give you a quick explanation on how to properly input arguments into this function. The first argument is "value"
This argument is the first value that we are searching for. The next argument is "type". This currently only works with vtDword
After that is the magical "...". This is symbolic for the rest of the arguments. The first line
checks to see if there are any more arguments. If that is the case, it executes the following lines which will return a table of every occurance of "value"
Otherwise, it will do much more complicated work starting with setting that variable x to 1
Each odd argument in the ... is a second value to look for, in relation to the first value. I'll explain what that means in a moment. Each even argument is the hexadecimal offset for the argument before it.
Let me explain what is happening. The function will first search for the first value. Once it finds it, it will read the value of each number that is a certain distance away from it. So if you have the first value at 0x00000001, and argument 1 and argument 2 are 17 and 345 respectively, the function will then check to see if the value at 0x00000001+345(0x00000346) is equal to the value of argument1 (17). If it is, then it will do the same for the next to arguments (should they exist).
If they are not the same, however, then it will search for the next occurence of "value" and repeat those checks until it is true for all arguments.
]]
  if #arg==0 then
    return t
  else
    for x=1,#t do
    local address=tonumber("0x"..t[x])
      for z=1,#arg,2 do
        if readInteger(address+arg[z])~=arg[z+1] then
          g=0
          break
        else
          g=g+1
        end
      end
      if g==(#arg/2) then
        local addTable={}
        addTable[1]=DEC_HEX(address)
        for z=1,#arg,2 do
            table.insert(addTable,DEC_HEX(address+arg[z]))
        end
        return(addTable)
      end
    end
  end
end


t=scanForVal(220055555,vtDword,0x00000008,243,0x00000020,6)
Back to top
View user's profile Send private message
dl748
Cheater
Reputation: 0

Joined: 05 Mar 2016
Posts: 39

PostPosted: Sat Jul 29, 2017 5:35 pm    Post subject: Reply with quote

i use a simpler script for converting to hex

Code:
local function hex(a, c)
  if a == nil then
    return "(nil)"
  end
  local fmt = "%X"
  if type(c) == "number" then
    fmt = "%0"..c.."X"
  end
  return string.format(fmt, a)
end


has the ability to specify a size as well (for padding) if you don't want that

Code:
local function hex(a, c)
  if a == nil then
    return "(nil)"
  end
  return string.format("%X", a)
end
Back to top
View user's profile Send private message
the_elemental_of_creation
How do I cheat?
Reputation: 0

Joined: 19 Jul 2017
Posts: 5

PostPosted: Wed Aug 02, 2017 8:04 pm    Post subject: Reply with quote

dl748 wrote:
i use a simpler script for converting to hex

Code:
local function hex(a, c)
  if a == nil then
    return "(nil)"
  end
  local fmt = "%X"
  if type(c) == "number" then
    fmt = "%0"..c.."X"
  end
  return string.format(fmt, a)
end


has the ability to specify a size as well (for padding) if you don't want that

Code:
local function hex(a, c)
  if a == nil then
    return "(nil)"
  end
  return string.format("%X", a)
end

Why is c there in the second code?
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