PCSX2 1.7+ Cheat Engine Script Compatibility
#1
How to Use Cheat Engine with PCSX2 v1.7+
Credit: Fobes (Git Pull Request - Core: Export Recompiler Offsets #5531)

General Overview

To put it simply, you basically assign EEmem (A) as a pointer and use the PS2 Memory Address as an Offset (B) to the EEmem Pointer.

Porting Example
Imagine for a moment that our cheat address is 2033CD68 in PCSX2 v1.6
PCSX2x64.EEmem would be assigned as a pointer,
0x33CD68 would be assigned as the first offset

Code:
Dereferencing<process name>.EEmem (example pcsx2x64-avx2-dev.EEmem ) in CheatEngine will give you the address to use as a base pointer.
~ Fobes

A)
   

B)
   
The images are provided as reference. The actual address for EEmem (7FF200000000) will change and is the whole reason for needing to go about doing things this way
Furthermore, the provided address (0x33CD68) would typically be written as 0x2033CD68 however with the recent changes to PCSX2 , prefixing our offsets with 0x2 is not necessary.

IMPORTANT NOTE:
As with PCSX2 v1.6 and previous releases, the same problem of applying patches to certain regions of memory will still result in no affect. This is due to how virtual memory is compiled , stored and cached.


Cheat Engine : PCSX2 Scripting Tutorial

Assigning EEMem as a Symbol
This took me a little bit of time to figure out but should make things much easier on everybody. Basically we are going to define a word as an address to be accessible in cheat engine. We can do this in a few simple steps Smile
- Open Cheat Engine and open the memory viewer
- Press CTRL+A to open the Script Assembler
- Its here that we will define "PCSX2x64.EEmem" as a symbol "EEmem" so that we can always access it by creating a new address in our table with EEMem as the address.
- Paste the following into your script entry window and then save it to your table. We do not need to run this script ever, it simply sits there and upon attaching to a said process it will assign an address to the symbol
- Go ahead and launch pcsx2, attach and add a new address with the Address of "EEmem"
From here you just assign a pointer with the offset value to your address in question (PS2 Format without "0x20")
Code:
{$lua}
[ENABLE]
-- Register EEmem Symbol --
local EEmem = getAddress("PCSX2x64.eemem")
registerSymbol("EEmem", PS2Mem, true)

[DISABLE]
unregisterSymbol("EEmem")

Assigning PS2mem as a Symbol
Having EEmem accessible as an address is pretty slick , but thanks to the PCSX2 dev team we were already able to access that with "PCSX2x64.eemem" as we discussed at the beginning. So while it might be cool that we can access the pointer with less characters , we havent really simplified anything and some might view that as a waste of time. However , there may be instances where one might want simple quick access to EEmem and having direct access to PS2Memory might not always be beneficial. This next part will walk you through creating a symbol to access PS2Memory all the time, just like EEmem.

- Open Cheat Engine and open the memory viewer
- Press CTRL+A to open the Script Assembler
- Paste the following into your script window and save it to your table.
You can get direct access to PS2Memory by using the address "PS2mem", offsets can be accessed by adding the offset to the address like so "PS2mem+033CD68"
Code:
{$lua}
[ENABLE]
-- Register PS2mem Symbol --
local PS2mem = getAddress("PCSX2x64.eemem")
PS2mem = readPointer(PS2mem)
registerSymbol("PS2mem", PS2mem, true)

[DISABLE]
unregisterSymbol("PS2mem")


ESSENTIAL FUNCTIONS
The following functions will prove to be very helpful in creating your PCSX2 Cheat Engine table. For instance, with PCSX2 it is very hard to deal with pointers , classes and their fields / methods.
Say you have a pointer to an Actor Object. To gain access to the structure, you will need to read 4 bytes from the pointer and then take that value and apply it to the PS2EEmem base. 
Cheat Engine has no way built in methods to normalize this, so using cheat engine as you normally would to navigate pointers ... simply put will not work.

I have created the following functions as somewhat of a bandaid to this issue. In this way , you can automate the process ahead of time with a script and just activate it to gain access to said fields and methods.

Function List:
- GetEEmem
- ResolveAddress
- GetPS2Address
- GetPS2AddrFromPointer
- GetPS2AddrFromPointerChain
Code:
{$lua}
-- Globals
PCSX2_VER="pcsx2-qtx64-avx2.exe"
PCSX2_EEMEM="pcsx2-qtx64-avx2.eemem"
-- Pointers
RAW_PlayerPointer = 0x20440C38
PlayerPointer = 0x440C38
-- Offsets
coordsX = 0x1C
coordsY = 0x20
coordsZ = 0x24
TeamID = 0xC8
Health = 0x1044
-- Resolves input RAW PS2 address
-- example input: 0x20440C38
-- example output: 0x440C38
function ResolveAddress(RAW_Address)
    return RAW_Address - 0x20000000
end
--  Gets EEMem Address
function GetEEMem()
    return readPointer(getAddress(PCSX2_EEMEM))
end
--  Resolves RAW PS2 Address relative to EEMem offset
--  input must be RAW PS2 Offset i.e [ 0x20440C38 ] remove the 0x20
--  Alternatively call Resolve Offset and input everything as RAW PS2 format
function GetPS2Address(offset)
    local base = GetEEMem()
    local result = base + offset     
    return result                    
end
--  Gets pointer address by reading 4bytes from input
-- returns result + eemem
function GetPS2AddrFromPointer(Pointer)
    local base = GetEEMem()
    local value = readInteger(Pointer)
    local result = base + value       
    return result                      
end
-- Get address by navigating pointer chain
-- input Base Address must be in shorthand RAW PS2 Format, this gets resolved
function GetPS2AddrFromPointerChain(BaseAddress, Offsets)
    local base = GetPS2AddrFromPointer(GetPS2Address(BaseAddress))
    for k,v in pairs(Offsets) do
        base = GetPS2AddrFromPointer(base + v)
    end
    return base
end


ATTACH ON LOAD
Code:
-- NightFyre Cheat Engine Script Framework --
---------------------------------------------
-- Establish Window Title --
PCSX2VERSION="PCSX2 v1.7.2912"
getAutoAttachList().add('PCSX2x64.exe')
MainForm.Caption = string.format('PCSX2::CheatTable - %s', PCSX2VERSION)

-- Remove Scan Panel --
MainForm.Panel5.visible = false

-- Set Dark Mode --
GetAddressList().Control[0].BackgroundColor=0x545454

-- Attach to Process + Generate PS2mem Symbol--
-- you may need to adjust the process name depending on the name of your executable
if not openProcess('PCSX2x64.exe')
then sleep(250)
  if getOpenedProcessID()== 0
   then getAutoAttachList().add('PCSX2x64.exe') sleep(250)
   local PS2mem = getAddress("PCSX2x64.eemem")
   PS2mem = readPointer(PS2mem)
   registerSymbol("PS2mem", PS2mem, true)
  end
end

--- This is not functional in its present state.
--- Essentially all it does it abort if PCSX2 is not found to be running when the table is loaded.
--- If you want to use it all you have to do is wrap "attach to Process" as a function that either returns true or false.
--- I originally had it wrapped this way but got tired of it as I debug trainers and internal menus quite frequently.
--- I could have just ripped out the skeleton code but I've left it for however long so I will leave it here for you to do what yo please with it
---
-- Search for Process --
-- if ISPCSX2Running() == false then
--   return
-- end

Example Cheat Engine Table
Game: Sly Cooper and the Thievius Raccoonus
Offset Credits: Sly Cooper Modding Community
Table Author: NightFyre
   

The following code provides as an example of a game utilizing all of the scripts contained above. This is how most CheatTable makers for PC games are accustomed to utilizing Cheat Engine. The above provided scripts simplify the process in accessing Playstation 2 Memory Variables while the following should give you an understanding on how to properly put everything together to get a decent table going. 

Special thanks to the Sly Cooper Modding Community. Their efforts made it possible for me to provide this simple example.  
I would also like to express some gratitude towards PeaceBeUponYou, for without his help and patience I would have had a much tougher time creating these scripts

Code:
---------------------------------------------
--  PCSX2 Cheat Engine Script Framework  --
---------------------------------------------

PCSX2_VER="pcsx2x64.exe"                --  Module
PCSX2_EEMEM="pcsx2x64.eemem"            --  EEMainMemory Module

-- Pointers
GameStatePointer = 0x2623C0            --  RAW PS2 Offset
WorldStatePointer = 0x2623C4            --  RAW PS2 Offset

-- Classes
local GameState = {
  GameStateFlags  = 0x0,
  nCheckSum      = 0x4,
  Unknown        = 0x8,
  GlobalPlayTimer = 0xC,
  WorldSaves      = 0x10,
  CurrentWorldID  = 0x19d8,
  CurrentLevelID  = 0x19dC,
  LivesCount      = 0x19E0,
  CharmsCount    = 0x19E4,
  CoinsCount      = 0x19E8,
  SettingsFlags  = 0x19EC,
  UnlockedThiefMoves  = 0x19F0,
  UnlockCutscenes    = 0x19F4,
  GameCompletionFlags = 0x19F8,
  LastThiefMove      = 0x19FC
}

local WorldState = {
  LevelSaves    = 0x0,
  KeysCount      = 0x438,
  VaultsCount    = 0x43C,
  MTSCount      = 0x440,
  WorldPlayTimer = 0x444,
  WorldStateFlags = 0x448
}

-- Establish Window Title
TITLE="PCSX2::SlyCooper(v1.0.0)"
MainForm.Caption = string.format('%s - Sly Cooper Modding Community', TITLE)

-- Remove Scan Panel
MainForm.Panel5.visible = false

-- Set Dark Mode
GetAddressList().Control[0].BackgroundColor=0x101010

-- Get Process Path
function GetEXEFilePath(addr,pid)
    local mods=enumModules(pid)
    for k,v in pairs(mods) do
        if v.Address==addr then
          return v.PathToFile
        end
    end
end

-- Attach Process
function AttachProcess(name)
  if not (openProcess(name) and readInteger(name))then
      registerSymbol(name,true)
  end

  if not getOpenedProcessID() then
      messageDialog('PCSX2 1.7 Process Not Found.',1)
      error('PCSX2 NOT RUNNING')
  end

  local FilePath=GetEXEFilePath(getAddressSafe(name),getOpenedProcessID())
  if not FilePath then
    messageDialog("WRONG PROCESS - PCSX2 ERROR",0)
    error("Process not found.")
  end
end

--  Gets EEMem Address
function GetEEMem()
    return readPointer(getAddress(PCSX2_EEMEM))
end

--  Resolves RAW PS2 Address relative to EEMem offset
--  input must be RAW PS2 Offset i.e [ 0x20440C38 ] remove the 0x20
--  Alternatively call Resolve Offset and input everything as RAW PS2 format
function GetPS2Address(offset)
    local base = GetEEMem()          --  EEmem Address
    local result = base + offset
    return result
end

--  Gets pointer address by reading 4bytes from input
-- returns result + eemem
function GetPS2AddrFromPointer(Pointer)
    local base = GetEEMem()          --  EEmem Address
    local value = readInteger(Pointer)    --  EEmem Offset
    local result = base + value
    return result
end

-- Get address by navigating pointer chain
-- input Base Address must be in shorthand RAW PS2 Format, this gets resolved
function GetPS2AddrFromPointerChain(BaseAddress, Offsets)
    local base = GetPS2AddrFromPointer(GetPS2Address(BaseAddress))
    for k,v in pairs(Offsets) do
        base = GetPS2AddrFromPointer(base + v)
    end
    return base
end

-- Attach Cheat Engine to PCSX2 Process
AttachProcess(PCSX2_VER)

-- Get PCSX2 Module
local dwGameBase = getAddress(PCSX2_VER)

-- Get EEMem
local EEmem = getAddress(PCSX2_EEMEM)
local EEModule = GetEEMem()

-- Get GameState Pointer
local GameStateBase = GetPS2AddrFromPointer(GetPS2Address(GameStatePointer))
for k,v in pairs(GameState) do
    registerSymbol(tostring(k), GameStateBase + v)
end
registerSymbol("GameState", GameStateBase)

local WorldStateBase = GetPS2AddrFromPointer(GetPS2Address(WorldStatePointer))
for k,v in pairs(WorldState) do
    registerSymbol(tostring(k), WorldStateBase + v)
end
registerSymbol("WorldState", WorldStateBase)
registerSymbol("dwGameBase", dwGameBase, true)
registerSymbol("EEmem", EEmem, true)
registerSymbol("PS2Mem", EEModule, true)


TOOLS - Cheat Table
- Attach to process (+optional attach on load)
- Show / Hide Address Panel
- PCSX2 Module Base
- EEmem Base
   

Code:
<?xml version="1.0" encoding="utf-8"?>
<CheatTable>
  <CheatEntries>
    <CheatEntry>
      <ID>387240</ID>
      <Description>"[PCSX2x64]"</Description>
      <Options moHideChildren="1"/>
      <LastState Value="" Activated="1" RealAddress="00000000"/>
      <Color>FF51FF</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>386836</ID>
          <Description>"PCSX2 moduleBase"</Description>
          <LastState Value="00905A4D" RealAddress="7FF71C720000"/>
          <ShowAsHex>1</ShowAsHex>
          <ShowAsSigned>0</ShowAsSigned>
          <VariableType>4 Bytes</VariableType>
          <Address>pcsx2x64.exe</Address>
        </CheatEntry>
        <CheatEntry>
          <ID>386837</ID>
          <Description>"EEMainMemory"</Description>
          <ShowAsHex>1</ShowAsHex>
          <ShowAsSigned>0</ShowAsSigned>
          <VariableType>4 Bytes</VariableType>
          <Address>PCSX2x64.EEmem</Address>
          <Offsets>
            <Offset>0</Offset>
          </Offsets>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>386480</ID>
      <Description>"DEBUG"</Description>
      <Options moHideChildren="1"/>
      <LastState Value="" Activated="1" RealAddress="00000000"/>
      <Color>00FFFF</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>386609</ID>
          <Description>"SHOW ADDRESS PANEL"</Description>
          <LastState/>
          <Color>00FFFF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
MainForm.Panel5.visible = true
[DISABLE]
{$lua}
MainForm.Panel5.visible = false
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>356</ID>
          <Description>"ADD NEW ADDRESS"</Description>
          <LastState/>
          <Color>00FFFF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>{$lua}
AddressList.createMemoryRecord()
[ENABLE]
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>386610</ID>
          <Description>"LUA ENGINE"</Description>
          <LastState/>
          <Color>00FFFF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>{$lua}
print('')
[ENABLE]
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>386547</ID>
          <Description>"DARK MODE"</Description>
          <LastState/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>{$lua}
[ENABLE]
GetAddressList().Control[0].BackgroundColor=0x545454
--getMainForm().color=0x545454
[DISABLE]
GetAddressList().Control[0].BackgroundColor=0xFFFFFF
--getMainForm().color=0xf0f0f0
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>386684</ID>
          <Description>"ATTACH PCSX2 [1.6.0]"</Description>
          <LastState/>
          <Color>4080FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>{$lua}
[ENABLE]
-- Attach to Process --
if not openProcess('pcsx2.exe')
then sleep(250)
  if getOpenedProcessID()==0
  then getAutoAttachList().add('pcsx2.exe') sleep(250)
end
end

--NOT USED
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>387225</ID>
          <Description>"ATTACH PCSX2dis [1.5]"</Description>
          <LastState/>
          <Color>4080FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>{$lua}
[ENABLE]
-- Attach to Process --
if not openProcess('pcsx2dis.exe')
then sleep(250)
  if getOpenedProcessID()==0
  then getAutoAttachList().add('pcsx2dis.exe') sleep(250)
end
end

--NOT USED
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>386726</ID>
          <Description>"ATTACH PCSX2x64 [v1.7]"</Description>
          <LastState/>
          <Color>4080FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>{$lua}
[ENABLE]
-- Attach to Process --
if not openProcess('pcsx2x64.exe')
then sleep(250)
  if getOpenedProcessID()==0
  then getAutoAttachList().add('pcsx2x64.exe') sleep(250)
end
end

--NOT USED
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>387235</ID>
          <Description>"ATTACH PCSX2x64-avx2 [v1.7]"</Description>
          <LastState/>
          <Color>4080FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>{$lua}
[ENABLE]
-- Attach to Process --
if not openProcess('pcsx2x64-avx2.exe')
then sleep(250)
  if getOpenedProcessID()==0
  then getAutoAttachList().add('pcsx2x64-avx2.exe') sleep(250)
end
end

--NOT USED
[DISABLE]
</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
  </CheatEntries>
</CheatTable>
Reply

Sponsored links

#2
Hi
I really don't understand your solution. I can't find the EE Main memory on the logs. I tried to put what you show and change the pointer to my old address (the address that I used when cheat engine works normally at PCSX2 1.5- versions) but is not working... could you explain step by step how to still use the cheat tables?
Reply
#3
(03-09-2022, 02:47 AM)dragonhex Wrote: Hi
I really don't understand your solution. I can't find the EE Main memory on the logs. I tried to put what you show and change the pointer to my old address (the address that I used when cheat engine works normally at PCSX2 1.5- versions) but is not working... could you explain step by step how to still use the cheat tables?

Make sure you are using a PCSX2 v1.7 Build dated later than February 24th 2022.

Next go to Debug > Show Program Log
Then in the program log Select "Sources" > Dev/Verbose

In CheatEngine make sure you are entering in the process name correctly
Reply
#4
You can even make it more simply from PCSX2x64.EEmem to EEmem
Reply
#5
Ok now I get it, is just copy my old address without the first 2, thanks for replied.


Attached Files Thumbnail(s)
   
Reply
#6
(04-25-2022, 01:51 AM)dragonhex Wrote: Ok so I fixed myself searching the values again and I noticed that the address is the same but with 7FF7F instead of 2 at the start of the address, thanks for replied anyways

I have very long and detailed .CT tables for certain PS2 games with hotkeys. Is there a way to change all the 2s to 7FF7Fs in a .CT table if I import my old .CT tables into PCSX2 1.7+? Perhaps I can use the offset function and increase or decrease all addresses by 7FF7D (7FF7F-00002), cut then paste all the address and save into a new .CT file. If you don't cut and paste after applying the offset, it won't save the new address. I haven't used 1.7+ yet, but with the new texture swapping functionality implemented recently I've been meaning to test out the new PCSX2s for that and I need to be able to use my old .CT tables.
Reply
#7
(04-25-2022, 10:20 AM)planetps2 Wrote: I have very long and detailed .CT tables for certain PS2 games with hotkeys. Is there a way to change all the 2s to 7FF7Fs in a .CT table if I import my old .CT tables into PCSX2 1.7+? Perhaps I can use the offset function and increase or decrease all addresses by 7FF7D (7FF7F-00002), cut then paste all the address and save into a new .CT file. If you don't cut and paste after applying the offset, it won't save the new address. I haven't used 1.7+ yet, but with the new texture swapping functionality implemented recently I've been meaning to test out the new PCSX2s for that and I need to be able to use my old .CT tables.

Well I have tables with a lot of cheats and what I did was use sublime text, compare the old cheat sintaxis with the new one, do a replace all and fix some sintaxis mistakes
Reply
#8
(04-25-2022, 01:51 AM)dragonhex Wrote: Ok now I get it, is just copy my old address without the first 2, thanks for replied.

In your screenshot, you have 7FF79 then the old address (minus the 2) instead of 7FF7F.

So is it 7FF79 instead of 7FF7F, and if so, what does the '9" represent?
Reply
#9
(04-26-2022, 01:44 PM)planetps2 Wrote: In your screenshot, you have 7FF79 then the old address (minus the 2) instead of 7FF7F.

So is it 7FF79 instead of 7FF7F, and if so, what does the '9" represent?

No, the 7FF79 at the start of the address is because this change every time the PC restart, now is 7FF82, but this doesn't matter if you mark the Pointer checkbox and write the EEMem below of the address should work. The textblock above the EEmem is where you have to put the address of your old cheat but only the last seven characters.
Reply
#10
(04-27-2022, 02:51 AM)dragonhex Wrote: No, the 7FF79 at the start of the address is because this change every time the PC restart, now is 7FF82, but this doesn't matter if you mark the Pointer checkbox and write the EEMem below of the address should work. The textblock above the EEmem is where you have to put the address of your old cheat but only the last seven characters.

Got it, so there's no longer static addresses anymore, even of new addresses that you find from searching in PCSX2 using 1.7+. Any code that you find now must be converted to a pointer with EEMem+ instead of 2.

In earlier versions, there was a specific range to search in cheat engine find codes in PS2 games. It was 20000000-22000000 and most of the useful codes in games with PCSX2 running were found between 20000000-21000000. Now I'm wondering what I should put as the range to my searches on 1.7+. It has to be all numbers right?

Would it be something like 7FF000000000-800000000000 instead of the usual 20000000-22000000? That's a much wider range than before if the XXs in 7FFXX0000000 changing every time so that's why I'm asking. What should my range be for searching codes in PCSX2 in 1.7?

As far as the codes themself, is it possible to list the new codes as "PCSX2+" or something instead of "7FFXX"? I just want to know if there's a better way to list the new codes for 1.7+ rather than turning every code into a pointer.
Reply




Users browsing this thread: 3 Guest(s)