Writing Patches
The patching system allows you to develop and run game patches and cheats, which are text files containing commands that the emulator execute to modify a game as it's running. PCSX2 supports three types of patch files, which are listed below:
| Type | Loaded From | Purpose |
|---|---|---|
| Patch | patches folder and built-in patches.zip file | Quality of life improvements such as widescreen support and no interlacing patches. The patches bundled with releases of PCSX2 are sourced from the pcsx2_patches repository on GitHub. |
| Cheat | cheats folder | Patches intended to alter gameplay, and other miscellaneous user-provided patches. |
| GameDB Patch | Built-in GameIndex.yaml file | Essential compatibility patches. Enabled by default. |
Patch files should be named according to the serial number (product code) of the game being patched, and the hash of the executable file being patched, which is colloquially referred to as its CRC. For example a patch file for the original PAL release of Ratchet & Clank should be named SCES-50916_6A8F18B9.pnach. You can generate a cheat or patch file for the currently running game using the Tools -> Edit Cheats... or Tools -> Edit Patches... menu items within the main window respectively.
Patches can be enabled/disabled from the Patches page of the game properties window.
Cheats can be enabled/disabled from the Cheats page of the game properties window, and will only be applied if the Enable Cheats setting is enabled. This setting can be enabled globally from the Emulation page of the settings window, or on a per-game basis from the Cheats page of the game properties window.
GameDB patches will only be applied if the Enable Compatibility Patches setting is enabled, which it is by default. It can be disabled from the Advanced page of the settings window.
Pnach Files
Patches and cheats both share the same file format, which is called the Pnach format. GameDB patches use a variant of this format that allows for patch commands to be embedded in the afformentioned GameIndex.yaml file.
A .pnach file is shown below as an example:
gametitle=Ratchet & Clank (PAL-M5) (SCES-50916)
[Winter Wonderland]
description=Give the fog a light blue tint.
author=Alice
patch=1,EE,0015F444,byte,9A // red
patch=1,EE,0015F445,byte,EC // green
patch=1,EE,0015F446,byte,F5 // blue
[Cheats\Infinite Health]
description=Don't let Ratchet drop below 8 HP.
author=Bob
patch=1,EE,001415F8,word,00000008
[Cheats\Locked and Loaded]
description=Give Ratchet 1,000,000,000 bolts.
author=Eve
patch=1,EE,0015ED98,word,3B9ACA00
Patches are separated into groups that can be enabled/disabled independently in the UI. Each line beginning and ending with a pair of square brackets starts a new group. For example, the example file above contains three groups: Winter Wonderland, Cheats\Infinite Health and Cheats\Locked and Loaded.
Groups can be organized into a tree. For example, the subgroups in the above example Infinite Health and Locked and Loaded are both children of the Cheats group. This hierarchy will be reflected in the UI.
The patch= lines are what actually modify the game's memory. They are described in detail below.
The description= and author= lines specify text that will be shown in the UI. An end-of-line comment can be created using two consecutive forward slashes.
Prior to v1.7.4546, patch files were not split into groups and so all patch commands were permanently enabled. Modern versions of PCSX2 still support files in this legacy format.
Patches
This command writes the specified value at the specified address in memory, and is probably the command that you will use most frequently. It offers multiple options for when it should be applied, different data types, and extended PS2rd compatible codes that allow for advanced features such as patches that are applied conditionally based on an existing value in memory.
Syntax
Patch commands are written in the following format:
patch=<place>,<cpu>,<address>,<type>,<data>
Each of the parameters that make up the command are described below:
| Parameter | Description |
|---|---|
<place> | The point in time when the patch should be applied. Possible values are:
Older versions of PCSX2 had bugs that altered how this parameter was interpreted. For more information, see the Errata section below. |
<cpu> | The processor corresponding to the address space that should be accessed. Possible values are:
|
<address> | The address in memory where |
<type> | The data type of
|
<data> | The data that should be written into memory at |
PS2rd Codes
PCSX2 has partial support for PS2rd codes. If the <type> parameter of a patch command is set to extended, the most signficant nibble (leftmost hexadecimal digit) of the <address> field will be interpreted as a type code used to perform an action according to the table below:
| Address Parameter(s) | Data Parameter(s) | Description | Pseudocode |
|---|---|---|---|
0aaaaaaa | 000000vv | Write the value
| |
1aaaaaaa | 0000vvvv | ||
2aaaaaaa | vvvvvvvv | ||
300000vv | 0aaaaaaa | Increment or decrement the value in memory at address
| |
301000vv | 0aaaaaaa | ||
3020vvvv | 0aaaaaaa | ||
3030vvvv | 0aaaaaaa | ||
30400000vvvvvvvv | 0aaaaaaa00000000 | ||
30500000vvvvvvvv | 0aaaaaaa00000000 | ||
|
| Set | |
|
| Copy | |
|
| Follow a chain of
| |
|
| Overwrite the value stored in memory at address
| |
|
| Not supported. | |
|
| Not supported. | |
|
| Read a value from address
The sizes of the value read from memory and the value
Do not mix conditional codes and patch commands that are not of type | |
|
|
In the case where multiple address and data parameters are present for a given row in the table above, multiple patch commands must be written on consecutive lines. Lower case letters are used to denote variables, while upper case letters and numbers are used to denote literals. The maximum valid value for any of the addresses in the above table is 1ffffff. If parameter values are provided that do not match one of the patterns in the above table, the behaviour is undefined.
The pseudocode in the above table makes use of the following functions:
Read(address, size)which readssizebits from memory ataddressand returns the result.Write(address, size, value)which writessizebits fromvalueto memory ataddress.SkipPatchCommands(n)which skips (prevents the execution of) the nextnpatch commands.Max(x, y)returnsxifxis greater thany, otherwise it returnsy.
Examples
| Pnach Code | Description | Example Use Case |
|---|---|---|
| Write the 32-bit value 0x12345678 into EE memory at address 0x100000 every frame in little-endian order. | Replacing an instruction in memory. |
| Write the 32-bit value 0x78563412 into EE memory at address 0x100000 every frame in big-endian order. This is equivalent to the last example. | You want the order the bytes are written in the pnach file to match the order in which they appear in a hex editor. |
| Write the null-terminated ASCII string "Hello World!" into EE memory at address 0x100000 every frame. | Writing a string into memory all at once. |
| Add 2 to the 32-bit value at address 0x100000 in EE memory every frame. | Rapidly increasing the amount of in-game currency the player has. |
| Follows a chain of pointers starting at 0x100000 and writes the value 0x12345678 into EE memory. In the following example the value will end up being written at 0x10003c: | Patch data that moves around in memory (e.g. data allocated on the heap). |
| Write the 16-bit value 0x1234 at addresses 0x100010 and 0x100020 if the 16-bit value at address 0x100000 is equal to 0xABCD. Write the same value at address 10100030 unconditionally. | Conditionally applying patches depending on which level is currently loaded. |
Dynamic Patches
Some games load code at runtime, so patching at a fixed address using the patch command may not always be viable. In these cases, as long as you are strictly patching code rather than data, you can use the dpatch command instead. This command allows the patching system to determine the address to patch dynamically by scanning for patterns of instructions. If the recompiler is enabled the patch will only be applied when the instruction at offset 0 (see below) is being recompiled. This means that you should ensure the instruction at offset 0 is executed before the instructions you wish to patch are executed. If the recompiler is disabled, dpatch commands will not be run at all.
Be careful when choosing instructions to match on. If the instruction contains an address (or part of an address) stored as an immediate operand, it may prevent the dpatch command from working when the code is loaded at a different address.
Syntax
Dynamic patch commands are written in the following format:
dpatch=<type>,<pattern count>,<replacement count>,<pattern 1>,...,<pattern N>,<replacement 1>,...,<replacement N>
Each of the parameters that make up the command are described below:
| Parameter | Description |
|---|---|
<type> | Currently must be set to |
<pattern count> | The number of instructions to match. |
<replacement count> | The number of instructions to replace. |
<pattern> | An offset and value pair in the following format: |
<replacement> | An offset and value pair in the following format: |
Example
| Pnach Code | Description | Example Use Case |
|---|---|---|
| Replace all | Patch sequences of instructions that appear at multiple different addresses in memory. |
Widescreen Patches
Patches that add support for widescreen are written in the following format:
[Widescreen 16:9]
gsaspectratio=16:9
patch=1,EE,00100000,word,12345678
The group name must be equal to Widescreen 16:9 for widescreen patches to be automatically applied when the global Apply Widescreen Patches setting is enabled.
Possible values for gsaspectratio:
StretchAuto 4:3/3:24:316:910:7
No-Interlacing Patches
Patches that disable interlacing are written in the following format:
[No-Interlacing]
gsinterlacemode=1
patch=1,EE,00100000,word,12345678
The group name must be equal to No-Interlacing for no interlacing patches to be automatically applied by the global Apply No-Interlacing Patches setting is enabled.
Possible values for gsinterlacemode are:
0: Automatic1: Off2: WeaveTFF3: WeaveBFF4: BobTFF5: BobBFF6: BlendTFF7: BlendBFF8: AdaptiveTFF9: AdaptiveBFF
Errata
Some older versions of PCSX2 are affected by the following issues:
| Affected Versions | Description |
|---|---|
| v2.3.96 to v2.5.384 | Patches with a |
| v1.7.4587 to v2.3.95 | Patches with a |