|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
dancewithdead How do I cheat? Reputation: 0
Joined: 29 Mar 2018 Posts: 1
|
Posted: Thu Mar 29, 2018 9:17 am Post subject: How to increase performance of my lua code? |
|
|
for loop with 4000 offsets is very slow..
how can i improve it?
what it do?
I want read data from many addresses and save in file.
Then read in other software - but i want fast updates
Code: | [ENABLE]
{$lua}
filename = "C:/data.txt"
base = 0x00AA2B60
timer = createTimer()
timer.setInterval(1000)
timer.onTimer = function()
local f = io.open(filename, "w")
f:write(tostring('return {\n'))
offset = 0
check = readInteger('[[[test.exe+base]+74]+0]+F4')
isAlive = readInteger('[[[test.exe+base]+74]+0]+158')
if check and check > 0 and check < 100000 then
name = string.match(readString('[[[[[test.exe+base]+74]+0]+128]+0]+0'),'(%w+)%.')
d1 = readFloat('[[[test.exe+base]+74]+0]+F8')
d2 = readFloat('[[[test.exe+base]+74]+0]+FC')
d3 = readFloat('[[[test.exe+base]+74]+0]+100')
d4 = readInteger('[[[test.exe+base]+74]+0]+160')
f:write(tostring('[1] = {name='..'"'..name..'"'..',d1='..d1..',d2='..d2..',d3='..d3..',d4='..d4..'},\n'))
end
for n=1,4000 do
offset = offset + 4
check = readInteger('[[[test.exe+base]+74]+offset]+F4')
d4 = readInteger('[[[test.exe+base]+74]+offset]+160')
isAlive = readInteger('[[[test.exe+base]+74]+offset]+158')
name = readString('[[[[[test.exe+base]+74]+offset]+128]+0]+0')
if name and name~="" and isAlive==2049 then
if d4 and d4 < 32 then
if check > 0 and check < 100000 then
name = string.match(name,'(%w+)%.')
d1 = readFloat('[[[test.exe+base]+74]+offset]+F8')
d2 = readFloat('[[[test.exe+base]+74]+offset]+FC')
d3 = readFloat('[[[test.exe+base]+74]+offset]+100')
d4 = readInteger('[[[test.exe+base]+74]+offset]+160')
f:write(tostring('['..(n+1)..'] = {name='..'"'..name..'"'..',d1='..d1..',d2='..d2..',d3='..d3..',d4='..d4..'},\n'))
end
end
end
end
f:write(tostring('}'))
f:close()
end
{$asm}
[DISABLE]
{$lua}
timer.destroy() |
Is it possible write it in other language in cheatengine?
looks like readInteger, read"anything" in lua is slow
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4300
|
Posted: Thu Mar 29, 2018 11:48 am Post subject: |
|
|
When parsing the address string, CE will dereference every node in the pointer path. You're asking CE to do a ridiculous number of calls to ReadProcessMemory. Mitigate that and it'll run faster.
To mitigate calls to RPM, cache nodes in the pointer path (see this topic for an example), read blocks of memory at a time (e.g. d1/d2/d3 and the array of pointers), and check conditions as they're read.
For lower-level optimizations, use local variables and use table.concat instead of several sequential string concatenation operations (or just write it to the file and let Lua buffer it).
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 55
Joined: 01 Oct 2008 Posts: 942
|
Posted: Sat Mar 31, 2018 4:04 am Post subject: |
|
|
This is an alternative to cache the pointer node. usage save the script as *.lua into autorun directory, or include in an initializing memory record,
Code: |
--
local fmt = string.format
local debugNow = nil--true
local function dp(...)
if debugNow then print(...)end
end
local function call(fn,...)return fn(...)end
local function tApply(t)return call(table.unpack(t,1,t.n or #t))end
function wrapAccess(oriAccess, memoaddr, istable)
return function(sAddr,...)
if type(sAddr)=='table' then sAddr = tApply(sAddr) end
local addr = type(sAddr)=='string' and (istable and memoaddr[sAddr] or not istable and memoaddr(sAddr))
if not addr then dp('* * * raw getaddr',sAddr)addr = GetAddressSafe(sAddr)end
if addr then return oriAccess(addr,...) end
end
end
local memoAddr_mt = {
__index = function(me,s)
local c,e,r,addr = 1,0,s
if r:find"%b[]"then
while c+e >0 and r:find"%b[]" do
r,c = r:gsub("%[[^%[%]]+%]",function(ptr)-- search inner most of [...] form
dp("==>",ptr)
local pAddr = rawget(me,ptr) -- cached?
if not pAddr then -- no, try readPointer/GetAddress and save as cache
pAddr = readPointer(ptr:sub(2,-2)) --or GetAddressSafe(ptr)
dp("* * * GetPtr:",ptr)
if pAddr then rawset(me,ptr,pAddr) dp(fmt('new: %08X : %s',pAddr, ptr))end
else
dp("cached inner:",ptr)
end
if pAddr then return fmt("%X",pAddr)else e=e-1 end
end)
end--while
r = (r..' '):gsub("%f[_%w](%x+)(%f[^_%w].?)",function(x, tl)return tonumber(x,16)..tl end)-- convert hex to decimal
local ok,eval = pcall(load,'return '..r ) -- ... and eval it as numeric address
if ok then ok,eval = pcall(eval)end
if ok and eval then addr = eval end
end
if not addr then -- fall back to parse original symbolic address
addr = GetAddressSafe(s) dp("* * * GetAddr:",s)
else
dp("cached:",s)
end
if addr then rawset(me,s,addr)end
return addr
end,
__call = function(me,s)return me[s]end
}
function memoAddr() return setmetatable({},memoAddr_mt)end
|
then for example in your code, in each timer loop add this code:
Code: |
...
timer.onTimer = function()
local commonCache = memoAddr()
local readInteger = wrapAccess(readInteger, commonCache)
local readFloat = wrapAccess(readFloat, commonCache)
local readString = wrapAccess(readString, commonCache)
local f = io.open(filename, "w")
...
|
Then each part of the symbolic address used by readInter/readFloat/readString (local version) of the form '[...]' will be cached after 1st time encountered.
It should minimize CE internal parsing that require RPM, with minimal change of your code.
---
I think it will be more manageable for future maintenance if you refactor pointer node manually as ParkourPenguin suggestion.
---
It seems there is some bug on 'offset'.
Code: |
...
for n=1,4000 do
offset = offset + 4 -- this 'offset' is a Lua variable
check = readInteger('[[[test.exe+base]+74]+offset]+F4') -- this 'offset' is an AA symbol, this will not changed with the Lua 'offset' given it is already defined as AA symbol.
...
|
may be something like this can fix:
Code: |
...
for n=1,4000 do
offset = offset + 4
local partial = string.format("[[[test.exe+base]+74]+%X]", offset)
check = readInteger(partial..'+F4')
-- and replace other "[[[test.exe+base]+74]+offset]" with partial
...
|
There is also an optimizing opportunity for the 4000x offset parts.
Instead of reading each offset by RPM, we can read all 4000x4bytes outside the loop as a byteTable.
Then extract each pointer of the form "[[[test.exe+base]+74]+offset]" locally.
ie.
Code: |
...
local Offset = readBytes("[[test.exe+base]+74]",4000*4,true)
for n=1,4000 do
local offset = string.char(table.unpack(Offset, n*4-3, n*4))
local partial = string.format("%X", string.unpack("<i4",offset))-- i4 for 32bit
check = readInteger(partial..'+F4')
...
|
Not test, hopeful there is no typo or bug on my code.
bye~
_________________
- Retarded. |
|
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
|
|