Sample of Cheat Engine Lua Script for Shared Memory Handling
Please Note: I just share my test case, it works but may not 100% correct...
The provided Lua script for Cheat Engine focuses on managing shared memory with specific data types and synchronization between processes by using CE's built-in lua functions. Here's a detailed breakdown of its purpose and functionality:
1. Initialization and Memory Management
The script begins with the [ENABLE]
section, executed upon enabling the script in Cheat Engine. You do not need to attach any process because share memory will be created by CE itself.
Memory Clearing: It ensures that any existing shared memory is deallocated to prevent conflicts and memory leaks.
Code: Select all
if _G.sharedMemory.mem ~= nil then deallocateSharedMemoryLocal(_G.sharedMemory.mem) _G.sharedMemory.mem = nil end
Memory Allocation: New memory blocks are allocated for data (64KB) and state management (8 bytes).
Code: Select all
local memSize = 65536 local memStatSize = 8 _G.sharedMemory.mem = allocateSharedMemoryLocal('MySharedMemory', memSize) _G.sharedMemoryState.mem = allocateSharedMemoryLocal('MySharedMemoryState', memStatSize)
In my test case, share memory is always there unless you close CE.
2. Shared Memory Operations
Functions for Memory Handling
readSignedInteger(address)
: Converts a memory-read integer into a signed 32-bit value.Code: Select all
function readSignedInteger(address) local value = readIntegerLocal(address) if value >= 0x80000000 then return value - 0x100000000 else return value end end
slowClearSharedMemory()
: Resets all shared memory locations to zero using 32-bit integer writes.Code: Select all
function slowClearSharedMemory() local intZero = 0 for offset = 0, memSize - 4, 4 do writeIntegerLocal(_G.sharedMemory.mem + offset, intZero) end end
waitForIdleState(timeout_ms)
: Waits until the shared memory is idle (state0
) or until a timeout occurs.State Functions:
setOperationState(state)
andsetDataType(dataType)
set operation state and data type for the shared memory block.
3. Writing Data to Shared Memory
Function: writeSharedMemory(data, dataType)
This function writes various data types into shared memory. Supported data types include:
32-bit int (dd)
64-bit int (dq)
32-bit Single (float)
64-bit double (double)
String (string)
64-bit address + 32-bit integer (12 bytes per entry)
64-bit address + 32-bit float (12 bytes per entry)
64-bit address + 64-bit integer (16 bytes per entry)
The script uses conditionals to set the data type, clear memory if needed, and write data accordingly.
Code: Select all
function writeSharedMemory(data, dataType)
if _G.sharedMemory.mem ~= nil then
waitForIdleState()
setOperationState(-1)
local offset = 0
if dataType == "dd" then
setDataType(1)
writeIntegerLocal(_G.sharedMemory.mem, data)
-- Additional data type conditions...
end
setOperationState(-3)
print("Data written to shared memory as type", dataType)
else
print("Shared memory is not created yet!")
end
end
4. Reading Data from Shared Memory
Function: readSharedMemory()
This function reads data from shared memory if it is in the -3
state, retrieving data based on its type.
Code: Select all
function readSharedMemory()
if _G.sharedMemory.mem ~= nil then
if readSignedInteger(_G.sharedMemoryState.mem) ~= -3 then
print("No new data to read.")
return nil
end
setOperationState(-2)
local dataType = readIntegerLocal(_G.sharedMemoryState.mem + 4)
local result = {dataType = dataType, dataValue = nil}
-- Data reading logic based on type...
setOperationState(0)
return result
else
print("Shared memory is not created yet!")
end
end
5. State Management and Cleanup
The script handles shared memory states carefully:
State Management: Sets states like
-1
(write),-2
(read), and0
(idle).Cleanup: The
[DISABLE]
section deallocates shared memory to free up resources.Code: Select all
[DISABLE] if syntaxcheck then return end if memrec then print(memrec.Description) end deallocateSharedMemoryLocal(_G.sharedMemory.mem) _G.sharedMemory.mem = nil deallocateSharedMemoryLocal(_G.sharedMemoryState.mem) _G.sharedMemoryState.mem = nil getLuaEngine().Close()
6. CE Lua example
I executed two CE instances & share data between them:
Left side: rendom write address:float numbers into memory
Right side: read data from share memory
7. CE <=> .EXE communication example
Executed one CE and one Windows executable. Share memory is created by CE. Need to enable CE script "Enable share memory block & do a read test" first. It's not allowed to attach zip or exe file here, so i just provide some code pieces & screenshot here.
We need to write some functions/procedures to access share memory:
Example:
Code: Select all
private
SharedMemoryHandle: THandle;
SharedMemoryStateHandle: THandle;
procedure OpenSharedMemory;
procedure CloseSharedMemory;
function IsMemoryIdle: Boolean;
procedure WaitForIdleState;
procedure SetMemoryState(State: Integer);
procedure AppendOutputWithTimestamp(const Msg: string);
procedure AppendSysOutputWithTimestamp(const Msg: string);
procedure ClearSharedMemory;
function GetOperationState: Integer;
procedure SetOperationState(State: Integer);
procedure SetDataType(DataType: Integer);
procedure StartWriteIntBlock;
procedure AppendIntBlockData(Address: Int64; Value: Integer);
procedure EndWriteIntBlock;
procedure StartWriteFloatBlock;
procedure AppendFloatBlockData(Address: Int64; Value: Single);
procedure EndWriteFloatBlock;
procedure StartWriteQWordBlock;
procedure AppendQWordBlockData(Address: Int64; Value: Int64);
procedure EndWriteQWordBlock;
public
Open share memory:
Code: Select all
procedure TMainForm.OpenSharedMemory;
begin
SharedMemorySize := 65536;
SharedMemoryName := 'MySharedMemory';
SharedMemoryStateName := 'MySharedMemoryState';
SharedMemoryHandle := OpenFileMapping(FILE_MAP_READ or FILE_MAP_WRITE, False, PChar(SharedMemoryName));
SharedMemoryStateHandle := OpenFileMapping(FILE_MAP_READ or FILE_MAP_WRITE, False, PChar(SharedMemoryStateName));
if SharedMemoryHandle = 0 then
begin
AppendSysOutputWithTimestamp('***Failed to open shared memory!');
end
else
AppendSysOutputWithTimestamp('Open shared memory successfully.');
if SharedMemoryStateHandle = 0 then
begin
AppendSysOutputWithTimestamp('***Failed to open shared memory state!');
end
else
AppendSysOutputWithTimestamp('Open shared memory state successfully.');
end;
Close Share memory:
Code: Select all
procedure TMainForm.CloseSharedMemory;
begin
if SharedMemoryHandle <> 0 then
CloseHandle(SharedMemoryHandle);
if SharedMemoryStateHandle <> 0 then
CloseHandle(SharedMemoryStateHandle);
end;
Read share memory:
Code: Select all
Ptr := MapViewOfFile(SharedMemoryHandle, FILE_MAP_READ, 0, 0, SharedMemorySize);
if Ptr = nil then
begin
AppendSysOutputWithTimestamp('***Unable to map shared memory for reading.');
SetOperationState(0);
Exit;
end;
.
.
.
try
Offset := 0;
OutputText := '';
case DataType of
1: begin
Move(Ptr^, IntData, SizeOf(IntData));
OutputText := 'dd: ' + IntToStr(IntData);
end;
2: begin
Move(Ptr^, QwordData, SizeOf(QwordData));
OutputText := 'dq: ' + IntToStr(QwordData);
end;
3: begin
Move(Ptr^, FloatData, SizeOf(FloatData));
OutputText := 'fp: ' + FloatToStr(FloatData);
end;
.
.
.
Lazarus source: ...