<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="26">
  <CheatEntries>
    <CheatEntry>
      <ID>0</ID>
      <Description>"asyncAob test"</Description>
      <LastState/>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript Async="1">

//// IMPORTANCE: timer created within async executing script will NOT FIRE


/////  testing setup
{$lua}
if syntaxcheck then return end
autoAssemble( [[
//// this has to be run success before others part of script for testing
  globalalloc(__,$4000)
  __+10:
  dq 0
  __+40:
  db 00 22 33 44 55 01 02 03
]] )

{$asm}

///// must set this to get memory record id of this script
{$lua}
return string.format("define(MRID,%d)",memrec.ID)
{$asm}

[ENABLE]
///      V--- match MRID from above memrec.ID, in decimal
asyncAob(MRID, 10, 2,   aobscan(symbol+0c,ff 22 33 44 55 01 02 03) )
// timeout(sec)^   ^--tryinterval(sec) ^--offset     ^^^^^--- aobscan* command

__+10:
dq symbol
 
[DISABLE]
unregistersymbol(symbol)
__+10:
dq -1

</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>1</ID>
      <Description>"click to make aob pattern search-able"</Description>
      <LastState/>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript Async="1">  globalalloc(__,$4000)

[ENABLE]
  __+40:
  db ff
[DISABLE]
  __+40:
  db 00

</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols>
    <SymbolEntry>
      <Name>__</Name>
      <Address>00720000</Address>
    </SymbolEntry>
  </UserdefinedSymbols>
  <LuaScript>
function aa_asyncaob(s,sc)
  local fmt,cat,sep,dec,any,ton,Int =
    string.format,table.concat,"%s*,%s*","(%d+)","(.-)",tonumber,math.floor
  local mrid,timeout,tryinterval,aob_cmd = s:match
    (cat{"^%s*",dec,sep,dec,sep,dec,sep,any,"%s*$"})
  if not mrid then
    return nil, "invalid format, should be asyncaob(MRID,TimeOut,TryInterval,aobscan_command)"
  end
  mrid,timeout,tryinterval = ton(mrid),ton(timeout),ton(tryinterval)
  timeout,tryinterval = Int(timeout*1000),Int(tryinterval*1000)
  local cmd,sym,offset,params = aob_cmd:match
    "^%s*([Aa][Oo][Bb][Ss][Cc][Aa][Nn]%w*)%s*%(%s*([_%a][_%w.]*)%s*([-+]?%x*)%s*,%s*(.-)%s*%)%s*$"
  if not sym then
    return nil,"invalid aob command:"..aob_cmd
  end
  if sc then -- syntaxcheck
    return fmt("define(%s,666)",sym)
  end
  if not readInteger(process) then
    return nil,"No process attached"
  end
--  if readInteger(sym) then -- already registered
--    return fmt("define(%s,%X)",sym,GetAddress(sym))--define a local of sym
--  end
  local mr = GetAddressList().getMemoryRecordByID(mrid)
  if not mr then return nil,"Memory Record not known, ID="..mrid end
  if not mr.Async then -- restart with Async for proper Async execution
    mr.Async= true
    local stateNext = not mr.Active
    local timer = createTimer()
    timer.Interval = 1
    timer.OnTimer = function(tm)
      tm.Destroy()
      mr.Active = stateNext
    end
    error("Restarting")
  end
  local dummy = "_dummy_"..math.random(10000,99999)
  local script = fmt([[
unregistersymbol(%s)
label(%s)
%s(%s,%s)
%s%s:
%s:
registersymbol(%s)
]],sym,sym,cmd,dummy,params,dummy,offset,sym,sym)

  local maxcnt = Int(timeout / tryinterval) + 1

  while maxcnt&gt;0 and mr.AsyncProcessingTime &lt; timeout and not autoAssemble(script)do
    maxcnt = maxcnt - 1
    sleep(tryinterval)
  end

  if readInteger(sym) then -- found?
    return fmt("define(%s,%X)",sym,GetAddress(sym))--define a local of sym
  else-- timeout
    return nil,"aob not found on timeout, cmd:"..s
  end
end
unregisterAutoAssemblerCommand"asyncaob"
registerAutoAssemblerCommand("asyncaob",aa_asyncaob)

</LuaScript>
</CheatTable>
