Page 1 of 1

Cheat Engine

Posted: Sun Jan 16, 2011 2:37 am
by zuel
Here is some code for anyone who wishes to utilize Cheat Engines xml. It simply loads the Cheat Engine XML into a table called memLocation. It then creates a sub table for each CheatEntry by name and creates two fields, Start and Offsets.

Example end result:

Code: Select all

MemLocation={
  Name1={
    Start=0xffffff,
    Offsets={0xffff,0xffff,0xffff},
  ,}
  Name2={
    Start=0xffffff,
    Offsets={0xffff,0xffff,0xffff},
  ,}
}
Here is the code:

Code: Select all



memLocation={};

mem = xml.open("./scripts/DOBotMem.XML");
elements = mem:getElement("CheatEntries"):getElements("CheatEntry");
for i,v in pairs(elements) do
	print(v:getElement("Description"):getValue());
	of = v:getElement("Pointer"):getElement("Offsets"):getElements("Offset");
	print (#of);
	if(#of > 1)then
		Offsets = {};
		for ii = #of,1,-1 do 
			table.insert(Offsets,tonumber(of[ii]:getValue(),16));
		end
		memLocation[v:getElement("Description"):getValue()] = {   
			["Start"] = tonumber(v:getElement("Pointer"):getElement("Address"):getValue(),16),
			["Offsets"] = Offsets,
		};		
	else
		Offset = tonumber(of[1]:getValue(),16);
		memLocation[v:getElement("Description"):getValue()] = {   
			["Start"] = tonumber(v:getElement("Pointer"):getElement("Address"):getValue(),16),
			["Offsets"] = Offset,
		};		
	end
end

tprint(memLocation);

Re: Cheat Engine

Posted: Sun Jan 16, 2011 12:28 pm
by Administrator
Nice, so once you create a table with Cheat Engine, you can use this to load the saved table? Or am I understanding this wrong?

Re: Cheat Engine

Posted: Sun Jan 16, 2011 1:33 pm
by zuel
Yup. Just get your address's with Cheat engine, Save it to XML. And the code will parse all the CheatEntries into a LUA table.

then just use memLocation like

memoryReadIntPtr(myProc, memLocation["PlayerHealth"]["Start"],memLocation["PlayerHealth"]["Offsets"]);


where PlayerHealth is the name you chose to give the address pointer in Cheat Engine.

Re: Cheat Engine

Posted: Sun Jan 16, 2011 2:33 pm
by zuel
Hang on. Terminology.

A table could mean one or more things, even in CheatEngine.

I do not mean this will load the Dissect Data Structures function accessed from the memory view.

It will load Cheat Engines main window address's that you have selected and are displayed in the bottom portion of the window.

Re: Cheat Engine

Posted: Sun Jan 16, 2011 3:36 pm
by Administrator
Yeah, this is pretty cool. Great idea, really. I'll probably end up using it myself. Definitely would be useful when it comes to managing adding/removing/editing all those pointers. Thanks for the code.

Re: Cheat Engine

Posted: Mon Jan 17, 2011 11:50 pm
by zuel
Okay, I am honestly a tweeker, without drugs even.

Here is a different version that creates a class and handles correctly reading the memory address's without you even needing to know what LUA functions to call.

I think this is a bit easier, requires no knowledge of what memory functions are needed when converting the cheatengine address to lua etc.. And it should handle all types.

but I am not sure if I did Type 5,7 or 8 correctly.

Code: Select all

--Byte            Type 0   
--2 Byte          Type 1   
--4 Byte          Type 2   
--Float           Type 3   
--Double          Type 4   
--Binary          Type 5   
--8 Byte          Type 6   
--Text            Type 7   
--Array of Bytes  Type 8   
                           

function LoadCheatEngine(file)
	memLocations={};
	local mem = xml.open("./scripts/DOBotMem.XML");
	local elements = mem:getElement("CheatEntries"):getElements("CheatEntry");
	for i,v in pairs(elements) do
		local memLocation=MemoryLocation(v);
		memLocations[memLocation.Name] = memLocation;
	end
	return memLocations;
end

MemoryLocation = class(function(memLoc,CEXMLCheatEntry)
	memLoc.Name = CEXMLCheatEntry:getElement("Description"):getValue();
	memLoc.Address = tonumber(CEXMLCheatEntry:getElement("Address"):getValue(),16);
	memLoc.Type = tonumber(CEXMLCheatEntry:getElement("Type"):getValue(),10);
	memLoc.IsPointer = (CEXMLCheatEntry:getElement("Pointer")~=nil);
	memLoc.Offsets = nil;
	memLoc.Length = 0;
	if(memLoc.IsPointer)then
		memLoc.Address = tonumber(CEXMLCheatEntry:getElement("Pointer"):getElement("Address"):getValue(),16);
		osets = nil;
		of = CEXMLCheatEntry:getElement("Pointer"):getElement("Offsets"):getElements("Offset");
		if(#of > 1)then
			osets = {};
			for ii = #of,1,-1 do 
				table.insert(osets,tonumber(of[ii]:getValue(),16));
			end
		elseif(#of == 1) then
				osets = tonumber(of[1]:getValue(),16);
		end
		
		memLoc.Offsets = osets;
	end
	if(memLoc.Type==7 or memLoc.Type==8 or memLoc.Type==5)then
		memLoc.Length = tonumber(CEXMLCheatEntry:getElement("Length"):getValue(),10);
	end
end)

function MemoryLocation:Value(process)
	if(self.IsPointer)then
		if(self.Type==0)then
			return memoryReadBytePtr(process, self.Address, self.Offsets);
		elseif(self.Type==1)then
			return memoryReadShortPtr(process, self.Address, self.Offsets);
		elseif(self.Type==2)then
			return memoryReadIntPtr(process, self.Address, self.Offsets);
		elseif(self.Type==3)then
			return memoryReadFloatPtr(process, self.Address, self.Offsets);
		elseif(self.Type==4)then
			return memoryReadDoublePtr(process, self.Address, self.Offsets);
		elseif(self.Type==5)then
			bytes = {};
			for i=1,self.Length do
					table.insert(bytes, memoryReadBytePtr(process, self.Address, self.Offsets));
			end
			return bytes;
		elseif(self.Type==6)then
			return memoryReadDoublePtr(process, self.Address, self.Offsets);
		elseif(self.Type==7)then
			return memoryReadStringPtr(process, self.Address, self.Offsets, self.Length);
		elseif(self.Type==8)then
			bytes = {};
			for i=1,self.Length do
					table.insert(bytes, memoryReadBytePtr(process, self.Address, self.Offsets));
			end
			return bytes;
		end
	else
		if(self.Type==0)then
			return memoryReadByte(process, self.Address);
		elseif(self.Type==1)then
			return memoryReadShort(process, self.Address);
		elseif(self.Type==2)then
			return memoryReadInt(process, self.Address);
		elseif(self.Type==3)then
			return memoryReadFloat(process, self.Address);
		elseif(self.Type==4)then
			return memoryReadDouble(process, self.Address);
		elseif(self.Type==5)then
			bytes = {};
			for i=1,self.Length do
					table.insert(bytes, memoryReadByte(process, self.Address));
			end
			return bytes;
		elseif(self.Type==6)then
			return memoryReadDouble(process, self.Address);
		elseif(self.Type==7)then
			return memoryReadString(process, self.Address, self.Length);
		elseif(self.Type==8)then
			bytes = {};
			for i=1,self.Length do
					table.insert(bytes, memoryReadByte(process, self.Address));
			end
			return bytes;
		end	
	end
end

-- Example calling
        myProc =openProcess( findProcess("MyApp") )

	memL =  LoadCheatEngine("./scripts/DOBotMem.XML");
	
	print(memL["PlayerName"]:Value(myProc));



Re: Cheat Engine

Posted: Wed Jan 19, 2011 3:26 am
by zuel
Okay. I can't believe this, but I just found out CheatEngine 6.0 has a new table structure.

here you go, this will handle the old and the new.

Example call:

Code: Select all


include("CheatEngine.lua");

appName = "Dragon*";

myProc = openProcess( findProcess(appName) );
	
window = findWindow(appName);

function main()

	memL =  LoadCheatEngine("./scripts/game.ct",findProcess(appName));
	
	print(memL["PlayerName"]:Value(myProc));
end
startMacro(main, true);

Code: Select all

function split(str, pat)
   local t = {}  -- NOTE: use {n = 0} in Lua-5.0
   local fpat = "(.-)" .. pat
   local last_end = 1
   local s, e, cap = str:find(fpat, 1)
   while s do
      if s ~= 1 or cap ~= "" then
	 table.insert(t,cap)
      end
      last_end = e+1
      s, e, cap = str:find(fpat, last_end)
   end
   if last_end <= #str then
      cap = str:sub(last_end)
      table.insert(t, cap)
   end
   return t
end


function LoadCheatEngine(file,process)
	memLocations={};
	local mem = xml.open(file);
	local cheatVersion = mem:getAttribute("CheatEngineTableVersion");

	if(cheatVersion == nil)then
		local elements = mem:getElement("CheatEntries"):getElements("CheatEntry");
		for i,v in pairs(elements) do
			local memLocation=MemoryLocation(v);
			memLocations[memLocation.Name] = memLocation;
		end
		return memLocations;
	elseif(cheatVersion==10)then
		local elements = mem:getElement("CheatEntries"):getElements("CheatEntry");
		for i,v in pairs(elements) do
			local memLocation=MemoryLocation10(v,process);
			memLocations[memLocation.Name] = memLocation;
		end
		return memLocations;		
	else
		print("unsupported CheatEngine file");
	end
	return nil;
end


MemoryLocation10 = class(function(memLoc,CEXMLCheatEntry,process)

	memLoc.Name = string.gsub(CEXMLCheatEntry:getElement("Description"):getValue(), '"', "");
	
	local addrS = CEXMLCheatEntry:getElement("Address"):getValue();
	local addrList = split(string.gsub(addrS, '"', ""),"+");

	if(#addrList == 1) then
		memLoc.Address = tonumber(addrList[1],16);
	else
		local addrOffset = tonumber(addrList[2],16);
		local addrModule = getModuleAddress(process, addrList[1]);
		memLoc.Address = addrModule + addrOffset;
	end
	
	memLoc.Type = CEXMLCheatEntry:getElement("VariableType"):getValue();
	memLoc.IsPointer = (CEXMLCheatEntry:getElement("Offsets")~=nil);
	memLoc.Offsets = nil;
	memLoc.Length = 0;
	if(memLoc.IsPointer)then
		osets = nil;
		of = CEXMLCheatEntry:getElement("Offsets"):getElements("Offset");
		if(#of > 1)then
			osets = {};
			for ii = #of,1,-1 do 
				table.insert(osets,tonumber(of[ii]:getValue(),16));
			end
		elseif(#of == 1) then
				osets = tonumber(of[1]:getValue(),16);
		end
		
		memLoc.Offsets = osets;
	end
	if(memLoc.Type=="String")then
		memLoc.Length = tonumber(CEXMLCheatEntry:getElement("Length"):getValue(),10);
	end
	if(memLoc.Type=="Array of byte")then
		memLoc.Length = tonumber(CEXMLCheatEntry:getElement("ByteLength"):getValue(),10);
	end
	if(memLoc.Type=="Binary")then
		memLoc.Length = tonumber(CEXMLCheatEntry:getElement("ByteLength"):getValue(),10);
		memLoc.Start = tonumber(CEXMLCheatEntry:getElement("BitStart"):getValue(),10);		
	end
end)


MemoryLocation = class(function(memLoc,CEXMLCheatEntry)
	memLoc.Name = CEXMLCheatEntry:getElement("Description"):getValue();
	memLoc.Address = tonumber(CEXMLCheatEntry:getElement("Address"):getValue(),16);
	memLoc.Type = tonumber(CEXMLCheatEntry:getElement("Type"):getValue(),10);
	memLoc.IsPointer = (CEXMLCheatEntry:getElement("Pointer")~=nil);
	memLoc.Offsets = nil;
	memLoc.Length = 0;
	if(memLoc.IsPointer)then
		memLoc.Address = tonumber(CEXMLCheatEntry:getElement("Pointer"):getElement("Address"):getValue(),16);
		osets = nil;
		of = CEXMLCheatEntry:getElement("Pointer"):getElement("Offsets"):getElements("Offset");
		if(#of > 1)then
			osets = {};
			for ii = #of,1,-1 do 
				table.insert(osets,tonumber(of[ii]:getValue(),16));
			end
		elseif(#of == 1) then
				osets = tonumber(of[1]:getValue(),16);
		end
		
		memLoc.Offsets = osets;
	end
	if(memLoc.Type==7 or memLoc.Type==8 or memLoc.Type==5)then
		memLoc.Length = tonumber(CEXMLCheatEntry:getElement("Length"):getValue(),10);
	end
end)

function MemoryLocation:Value(process)
	--tprint(self);
	if(self.IsPointer)then
		if(self.Type==0)then
			return memoryReadBytePtr(process, self.Address, self.Offsets);
		elseif(self.Type==1)then
			return memoryReadShortPtr(process, self.Address, self.Offsets);
		elseif(self.Type==2)then
			return memoryReadIntPtr(process, self.Address, self.Offsets);
		elseif(self.Type==3)then
			return memoryReadFloatPtr(process, self.Address, self.Offsets);
		elseif(self.Type==4)then
			return memoryReadDoublePtr(process, self.Address, self.Offsets);
		elseif(self.Type==5)then
			bytes = {};
			for i=1,self.Length do
					table.insert(bytes, memoryReadBytePtr(process, self.Address, self.Offsets));
			end
			return bytes;
		elseif(self.Type==6)then
			return memoryReadDoublePtr(process, self.Address, self.Offsets);
		elseif(self.Type==7)then
			return memoryReadStringPtr(process, self.Address, self.Offsets, self.Length);
		elseif(self.Type==8)then
			bytes = {};
			for i=1,self.Length do
					table.insert(bytes, memoryReadBytePtr(process, self.Address, self.Offsets));
			end
			return bytes;
		end
	else
		if(self.Type==0)then
			return memoryReadByte(process, self.Address);
		elseif(self.Type==1)then
			return memoryReadShort(process, self.Address);
		elseif(self.Type==2)then
			return memoryReadInt(process, self.Address);
		elseif(self.Type==3)then
			return memoryReadFloat(process, self.Address);
		elseif(self.Type==4)then
			return memoryReadDouble(process, self.Address);
		elseif(self.Type==5)then
			bytes = {};
			for i=1,self.Length do
					table.insert(bytes, memoryReadByte(process, self.Address));
			end
			return bytes;
		elseif(self.Type==6)then
			return memoryReadDouble(process, self.Address);
		elseif(self.Type==7)then
			return memoryReadString(process, self.Address, self.Length);
		elseif(self.Type==8)then
			bytes = {};
			for i=1,self.Length do
					table.insert(bytes, memoryReadByte(process, self.Address));
			end
			return bytes;
		end	
	end
end


function MemoryLocation10:Value(process)
	--tprint(self);
	if(self.IsPointer)then
		if(self.Type=="Byte")then
			return memoryReadBytePtr(process, self.Address, self.Offsets);
		elseif(self.Type=="2 Bytes")then
			return memoryReadShortPtr(process, self.Address, self.Offsets);
		elseif(self.Type=="4 Bytes")then
			return memoryReadIntPtr(process, self.Address, self.Offsets);
		elseif(self.Type=="Float")then
			return memoryReadFloatPtr(process, self.Address, self.Offsets);
		elseif(self.Type=="8 Bytes")then
			return memoryReadDoublePtr(process, self.Address, self.Offsets);
		elseif(self.Type=="Binary")then
			bytes = {};
			for i=self.Start,self.Length do
					table.insert(bytes, memoryReadBytePtr(process, self.Address, self.Offsets + i));
			end
			return bytes;
		elseif(self.Type=="Double")then
			return memoryReadDoublePtr(process, self.Address, self.Offsets);
		elseif(self.Type=="String")then
			return memoryReadStringPtr(process, self.Address, self.Offsets, self.Length);
		elseif(self.Type=="Array of byte")then
			bytes = {};
			for i=1,self.Length do
					table.insert(bytes, memoryReadBytePtr(process, self.Address, self.Offsets + i));
			end
			return bytes;
		end
	else
		if(self.Type=="Byte")then
			return memoryReadByte(process, self.Address);
		elseif(self.Type=="2 Bytes")then
			return memoryReadShort(process, self.Address);
		elseif(self.Type=="4 Bytes")then
			return memoryReadInt(process, self.Address);
		elseif(self.Type=="Float")then
			return memoryReadFloat(process, self.Address);
		elseif(self.Type=="8 Bytes")then
			return memoryReadDouble(process, self.Address);
		elseif(self.Type=="Binary")then
			bytes = {};
			for i=self.Start,self.Length do
					table.insert(bytes, memoryReadByte(process, self.Address + i));
			end
			return bytes;
		elseif(self.Type=="Double")then
			return memoryReadDouble(process, self.Address);
		elseif(self.Type=="String")then
			return memoryReadString(process, self.Address, self.Length);
		elseif(self.Type=="Array of byte")then
			bytes = {};
			for i=1,self.Length do
					table.insert(bytes, memoryReadByte(process, self.Address + i));
			end
			return bytes;
		end	
	end
end



Re: Cheat Engine

Posted: Tue Jul 19, 2011 5:18 am
by RicalEyl
what cheat engine are you refering to? cant find it :(

Re: Cheat Engine

Posted: Tue Jul 19, 2011 11:13 am
by Administrator
RicalEyl wrote:what cheat engine are you refering to? cant find it :(
http://www.google.com/search?q=cheat%20 ... channel=np