Skip to content

Commit

Permalink
Rendering apis (#6)
Browse files Browse the repository at this point in the history
* include rendering classes

- GSDevices null - DX12
- enums for devices
- adjusted example to obtain instance pointers { device, renderer, thread }

* restructure

PCSX2 Package
Moved all PCSX2 logic to its own package which will contain Classes, Structs, Methods and enums.

GamePackage
Game packages have been moved to their own contained subfolder in the sdk directory. This was done to maintain some level of neatness and exposure as the SDK grows in size

* Update README.md

* dx11 present hook template

* update engine class

Engine
- include dx11 hook template

Readme
- included examples

* readme

* static memory class

adjusted the entirety of the memory class for static access.
Constructor method will populate both EEMemory and PS2BaseAddress.
Being that these 2 values will always be the same for the lifetime of the module , there is no need to obtain it consistently.

Tools class  was also adjusted to be a static class

all pointers for accessing members have been removed due to increased confusion

* Update dllmain.cpp
  • Loading branch information
xCENTx committed Aug 31, 2023
1 parent 6f3c129 commit 70dcf7d
Show file tree
Hide file tree
Showing 22 changed files with 710 additions and 294 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ release/
x86/
x64/

# exclude external libraries
*.rcnet


# exclude personal settings
*.sln
*.vcxproj.filters
*.vcxproj.user
*.vcxproj.user
7 changes: 3 additions & 4 deletions PCSX2-FrameWork.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,12 @@
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../pch.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="SDK\SOCOM1\SOCOM1_package.cpp">
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../pch.h</PrecompiledHeaderFile>
<ClCompile Include="SDK\pcsx2_package.cpp">
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../pch.h</PrecompiledHeaderFile>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="example.hpp" />
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="SDK.h" />
Expand Down
99 changes: 89 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,100 @@
# PCSX2 Menu Trainer Development Kit
## CODE EXAMPLE
PCSX2 Menu Trainer Development Kit is a C++ library designed to simplify the process of creating cheats for the PCSX2 emulator.
It aims to bridge the gap between modern cheat development practices and the classic era of cheat codes.
This framework provides tools to port older codes to a more modern approach, using additional libraries such as dear imgui and minhook.

| ![image](https://github.com/NightFyre/PCSX2-CheatFrameWork/assets/80198020/7417d7e7-603c-465a-807f-62abf88179eb) | ![image](https://user-images.githubusercontent.com/80198020/201475737-21591eb0-8858-4575-8ee9-5d9d2e07d1dc.png) | ![image](https://user-images.githubusercontent.com/80198020/200977619-e22fe7a5-b914-4906-9e3c-50f929ea3ebf.png) |
| :---: | :---: | :---: |

## GENERAL USAGE
1. include the SDK header as well as any required packages.
*NOTE: Engine_Package.h is a required package and needs to be manually included.*
- `SDK.h` // Including the SDK header will provide access to all the most necessary features.
- `Engine_Package.cpp` // Core Package and must be included for basic usage
- `PCSX2_Package.cpp` // Contains PCSX2 specific members and functions. Like the rendering API's for instance

2. Initialize the SDK
- `PlayStation2::InitSDK();`

3. Do Stuff
https://github.com/NightFyre/PCSX2-CheatFrameWork/blob/1cdaa7f5a22868f86a9a7beeb7a637c6f58a8f8e/dllmain.cpp#L8-L44

## CODE EXAMPLES

- Get Physical Address
```cpp
// - Example Pnach: Save Anywhere by Codejunkies ( Kingdom Hearts (NTSC-UC) )
// - patch=1,EE,204865E0,extended,00114288
// - Raw Address -> 204865E0

// Extract offset from raw address (remove "0x20")
unsigned int offset = 0x4865E0;

// Get Physical Address
auto addr = PlayStation2::Memory::GetPS2Address(offset);
```

- Read Memory
```cpp
// Read Memory
// - Example Offset: Tidus Health - FFX
// - 0x10DF34C

// Get Offset Physical Address
auto addr = PlayStation2::Memory::GetPS2Address(0x10DF34C);

// Read Memory
auto result = PlayStation2::Memory::PS2Read<int>(addr);
```

- Write Memory
```cpp
// Write Memory
// - Example Pnach: Infinite Health by Codejunkies ( Star Wars Battlefront )
// - patch=1,EE,20519060,extended,00000001
// - Raw Address -> 20519060
// - Patch -> 00000001

// Get Physical Address
auto addr = PlayStation2::Memory::GetPS2Address(0x519060);

// Write Memory
PlayStation2::Memory::PS2Write<int>(addr, 1);
```

## ADVANCED TECHNIQUES
- Access Class Members via GamePackages
```cpp
/// Access SealObject & Modify Weapon Ammo
/// SOCOM 1 -> Access SealObject & Modify Weapon Ammo
{
// Create an instance of the Offsets Class
SOCOM1::Offsets offsets; // Initializing the class will auto resolve any of our offsets placed in the header
SOCOM1::Offsets offsets; // Initializing the class will auto resolve all offsets placed in the class constructor
auto base = (SOCOM1::CPlayer*)offsets.SEALPointer; // Get SEALObject Class
if (base->isValid()) // Check if our player object is valid, generally the value will be NULL if not in a game
base.PrimaryMag1 = 1337; // Set Ammo Count in MAG1
if (base->isValid()) // Check if player object is valid, generally the value will be NULL if not in a game
base.PrimaryMag1 = 1337; // Set Ammo Count in MAG1
}
```
| ![image](https://user-images.githubusercontent.com/80198020/200977503-e4737e4e-9d2d-4b2e-9554-3b8484872e38.png) | ![image](https://user-images.githubusercontent.com/80198020/201475737-21591eb0-8858-4575-8ee9-5d9d2e07d1dc.png) | ![image](https://user-images.githubusercontent.com/80198020/200977619-e22fe7a5-b914-4906-9e3c-50f929ea3ebf.png) |
| :---: | :---: | :---: |

- Hook Rendering API
```cpp
/// PCSX2 -> Hook DirectX11 Present
PlayStation2::GSDevice* device = *PlayStation2::CGlobals::g_gs_device; // Obtains the current render api device instance
auto d3d11 = reinterpret_cast<PlayStation2::GSDevice11*>(device); // Cast D3D11 Rendering Device
pSwapChain = d3d11->GetSwapChain(); // Obtain SwapChain Pointer
if (pSwapChain)
PlayStation2::hkVFunction(pSwapChain, 8, oIDXGISwapChainPresent, hkPresent); // Hook present
```
## References & Credits
- [Accessing PCSX2 Memory](https://nightfyre.github.io/PCSX2_Trainer/)
- [Dear ImGui](https://github.com/ocornut/imgui)
- [Minhook Hooking Library](https://github.com/TsudaKageyu/minhook)
- [PCSX2](https://github.com/PCSX2/pcsx2)
- [GameHacking.org](https://gamehacking.org/system/ps2)
- [Sly Cooper Modding Community](https://discord.com/invite/2GSXcEzPJA)
- [SOCOM Modding Community](https://discord.com/invite/PCJGrwMdUS)
- [A General Guide for Making Cheats & Trainers for PCSX2](https://www.unknowncheats.me/forum/general-programming-and-reversing/569991-pcsx2-guide-cheats-trainers.html)
## License
This framework is distributed under the MIT License.
## Disclaimer
1. *This framework is intended for educational and single-player use.*
2. *Use cheats responsibly and respect the terms of use of the games you are modifying.*
14 changes: 11 additions & 3 deletions SDK.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,16 @@
#include <sstream>
#include <algorithm>

// RENDERING APIS
#include <d3d11.h>
#include <d3d12.h>
#include <dxgi1_4.h>

// Include SDK Files
#include "SDK/engine_package.h"
#include "SDK/engine_package.h" // Core PS2 Helper Classes, Structs & Functions
#include "SDK/pcsx2_package.h" // Core PCSX2 Classes , Structs & Functions

// Custom Game Includes
#include "SDK/SOCOM1/SOCOM1_package.h"
// Custom Game Packages
// - review readme and examples for better understanding with including a game package.
// #include "SDK/GamePackage/SOCOM1/SOCOM1_package.h"
// #include "SDK/GamePackage/SlyCooper1/SlyCooper_Package.h"
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ namespace PlayStation2
public:
bool IsValid();
bool IsAlive();
class CZSealBody* PlayerPhysicsPtr();
class CZSealObject* PlayerPhysicsPtr();
std::string GetPlayerName();
std::string GetTeamName();
std::string GetWeaponName(unsigned int Weapon);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ namespace PlayStation2
///---------------------------------------------------------------------------------------------------
// [CPLAYER]
// Returns a Pointer to CPlayerPhysics Class
CPlayerPhysics* CZSealBody::PlayerPhysicsPtr()
CZSealObject* CZSealBody::PlayerPhysicsPtr()
{
return (CPlayerPhysics*)((unsigned int)this->CPlayerMovement + g_PS2Mem->BasePS2MemorySpace);
return (CZSealObject*)((unsigned int)this->CPlayerMovement + g_PS2Mem->BasePS2MemorySpace);
}

///---------------------------------------------------------------------------------------------------
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
142 changes: 78 additions & 64 deletions SDK/engine_classes.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,67 +9,56 @@
#pragma pack(push, 0x01)
namespace PlayStation2
{
class PS2
{
public:
// Class Initialize
PS2()
{
HWND g_chWnd = GetConsoleWindow();
if (g_chWnd == NULL)
{
AllocConsole(); // Allocate console for output
freopen_s(&output_stream, "CONOUT$", "w", stdout); // Establish stream for output to console
SetConsoleTitleA("PCSX2 FrameWork by NightFyre"); // Set console title
g_chWnd = GetConsoleWindow(); // Store WindowHandle to console
}
g_cHandle = GetStdHandle(STD_OUTPUT_HANDLE); // Store handle to console
ShowWindow(GetConsoleWindow(), SW_SHOW); // Show console window
printf("[+] PCSX2-FrameWork::Initialized\n\n"); // Print text to our newly created window
}
class Engine
{
public: // INSTANCE METHODS
void CreateConsole(const char* title, bool bShow = true); // creates a console instance for debug output
void DestroyConsole(); // destroys the created console instance
bool isConsolePresent(); //
void D3D11HookPresent(); //
void D3D11UnHookPresent(); //

// Cleanup
~PS2()
{
if (output_stream == NULL)
return;
// D3D Present Hook Template
typedef HRESULT(APIENTRY* IDXGISwapChainPresent)(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags);
IDXGISwapChainPresent fnc_oIDXGISwapChainPresent = NULL;
IDXGISwapChain* m_pSwapChain = nullptr;
static HRESULT __stdcall hkPresent(IDXGISwapChain* pSwapChain, UINT sync, UINT flags);

fclose(output_stream);
DestroyWindow(g_chWnd);
FreeConsole();
}

private: // Nothing should ever need access to these things
FILE* output_stream; // Console Text Output Stream
HANDLE g_cHandle; // Handle to Console
HWND g_chWnd{}; // Window Handle to Console
HANDLE _pipe; // Handle to Pipe
private:
FILE* p_fin_stream; // Console Text Input Stream
FILE* p_fout_stream; // Console Text Output Stream
FILE* p_ferr_stream; // Console Text Error Stream
HANDLE p_console_handle; // Handle to Console
HWND p_wndw_handle; // Window Handle to Console
HANDLE p_pipe_handle; // Handle to Pipe
bool p_bConsole{ 0 }; // flag for console creation
bool p_bShowWindow{ 0 }; // flag for displaying console window
};
inline std::unique_ptr<PS2> g_PS2;
inline std::unique_ptr<Engine> g_Engine;

class PS2Memory
class Memory
{
public:
class PS2Tools* Tools; //
ProcessInfo Process; // Process Information Struct
uintptr_t dwGameBase; // Process Module Base
uintptr_t dwEEMem; // EEMem Pointer
uintptr_t BasePS2MemorySpace; // EEMem Base Address
public: // MEMBERS
static uintptr_t dwGameBase; // Process Module Base
static uintptr_t dwEEMem; // EEMem Pointer
static uintptr_t BasePS2MemorySpace; // EEMem Base Address
static ProcessInfo Process; // Process Information Struct

public: // METHODS
static bool ObtainProcessInfo(ProcessInfo& pInfo);
static uintptr_t GetPS2Address(unsigned int RAW_PS2_OFFSET);
static uintptr_t DereferencePtr(unsigned int RAW_PS2_OFFSET);
static uintptr_t ResolvePtrChain(unsigned int RAW_PS2_OFFSET, std::vector<unsigned int> offsets = {});
static bool BytePatch(uintptr_t Address, BYTE* bytes, unsigned int size);
static bool NopBytes(uintptr_t Address, unsigned int size);

public:
bool isNullPtr();
uintptr_t GetAddr(unsigned int RAW_PS2_OFFSET);
uintptr_t GetClassPtr(unsigned int RAW_PS2_OFFSET);
uintptr_t ResolvePtrChain(unsigned int RAW_PS2_OFFSET, std::vector<unsigned int> offsets = {});
bool BytePatch(uintptr_t Address, BYTE* bytes, unsigned int size);
bool Nop(uintptr_t Address, unsigned int size);

///---------------------------------------------------------------------------------------------------
// [MEMORY]
// Takes Full Address
// Make sure to resolve any offsets prior to running this function
// NOTE: only reads last 4bytes
template<typename T> inline T PS2Read(uintptr_t Address)
template<typename T>
static inline T PS2Read(uintptr_t Address)
{
/// USING FRAMERATE AS AN EXAMPLE
//0x7FF6B048CF60 0000001E0000001E // 8 Bytes
Expand All @@ -82,13 +71,13 @@ namespace PlayStation2
return A;
}


///---------------------------------------------------------------------------------------------------
// [MEMORY]
// Takes Full Address
// Make sure to resolve any offsets prior to running this function
// NOTE: only writes last 4bytes
template<typename T> inline void PS2Write(uintptr_t Address, T Patch)
template<typename T>
static inline void PS2Write(uintptr_t Address, T Patch)
{
/// USING FRAMERATE AS AN EXAMPLE
//0x7FF6B048CF60 0000001E0000001E // 8 Bytes
Expand All @@ -97,23 +86,48 @@ namespace PlayStation2
*(T*)Address = Patch;
}


public:
PS2Memory()
{
Process.Initialize();
dwGameBase = (uintptr_t)Process.m_ModuleBase;
dwEEMem = (uintptr_t)GetProcAddress((HMODULE)Process.m_ModuleHandle, "EEmem");
BasePS2MemorySpace = *(uintptr_t*)dwEEMem;
}
~PS2Memory() {}
Memory();
~Memory();
};
inline std::unique_ptr<PS2Memory> g_PS2Mem;
inline uintptr_t Memory::dwGameBase{ 0 };
inline uintptr_t Memory::dwEEMem{ 0 };
inline uintptr_t Memory::BasePS2MemorySpace{ 0 };
inline ProcessInfo Memory::Process{ 0 };


class PS2Tools
class Tools
{
public:
static float GetDistanceTo3DObject(Vector3 POS, Vector3 POS2);
};

class CGlobals
{
public:
float GetDistanceTo3DObject(Vector3 POS, Vector3 POS2);

/*
__int64 GSUpdateDisplayWindow() -> g_gs_renderer
.text:000000014015095F mov rcx, cs:g_gs_renderer
AOB: 48 8B 0D 32 42 F8 03
*/
static class GSRenderer** g_gs_renderer;

/*
__int64 GSUpdateDisplayWindow() -> g_gs_device
.text:00000001401508C5 mov rax, cs:g_gs_device
AOB: 48 8B 05 D4 41 F8 03
*/
static class GSDevice** g_gs_device;

/*
__int64 __fastcall OpenGSDevice(char a1, unsigned int a2) -> g_emu_thread
.text:000000014035C32F mov rcx, cs:g_emu_thread
AOB: 48 8B 0D A2 48 9D 0D
*/
static class EmuThread** g_emu_thread;

};

}
#pragma pack(pop)

0 comments on commit 70dcf7d

Please sign in to comment.