Skip to content

memory

Raw memory access. memory, ffi and — on cocos/iOS builds — objc are installed together by the ffi capability, so they are nil unless it was granted. A loose dev script gets it automatically; a marketplace bundle lists ffi in manifest.json capabilities. arm64 iOS and Android.

Every read is guarded: an unmapped address returns nil, a bad write returns false. Nothing here crashes the game on a bad address.

The spine of the whole surface. A native address is a pointer userdata, never a bare Lua number. memory.at, memory.scan, p:deref(), an object’s .pointer and a field read that yields an address all return one. Its sealed metatable:

Method Returns Description
p:address() integer The raw uintptr. tostring(p) is "0x...".
p:add(n) / p + n pointer Advance by n bytes.
p:sub(n) / p - n pointer Retreat by n bytes.
p:at(off) pointer Sugar for p:add(off).
p == q boolean Address equality.
p:deref() / p:pointer() pointer Read a pointer-sized word.
p:is_null() boolean Whether the address is 0.

Typed reads, each returning the value or nil on an unreadable address:

p:i8() p:i16() p:i32() p:i64() p:u8() p:u16() p:u32() p:u64() p:f32() p:f64() p:bool(), plus p:bytes(n) (a string of n bytes) and p:string([max=4096]) (a C string).

Typed writes, each returning true/false: p:set_i8(v) ... p:set_f64(v) p:set_bool(v) p:set_bytes(str).

Call through a pointer: p:call(signature, ...) treats p as the callee address; see ffi.call.

memory.at(n: integer): pointer

Wraps a raw integer address as a pointer.

memory.main(): table|nil

Returns { base = pointer, size = integer } for the game executable, or nil.

memory.module(name: string): table|nil

Returns { base = pointer, size = integer } for a loaded module, or nil.

memory.scan(pattern: string): pointer|nil

Argument Type Description
pattern string IDA-style bytes, e.g. "48 8B ?? ?? 90"; ?? or ? is a wildcard.

Scans the main image’s text and data. Returns the first match or nil.

memory.scan_module(name: string, pattern: string): pointer|nil

Like scan, over one named module.

memory.symbol(module: string, name: string): pointer|nil

Resolves an exported symbol.

For scripts that hold addresses as numbers, memory.read_i32(n), memory.read_f64(n), and the matching writes mirror the pointer methods. They are thin wrappers over memory.at(n):i32() and friends.