Guide:Writing pnach files
Modding Guide | |
---|---|
Game(s) | Sly Cooper and the Thievius Raccoonus Sly 2: Band of Thieves Sly 3: Honor Among Thieves |
This guide contains documentation on how to write patch lines in pnach format.
Format[edit | edit source]
Pnach format takes inspiration from RAW PS2 cheat codes. A RAW PS2 cheat code is composed of 2 valid hexadecimal numbers (0-9, A-F), without the prefix "0x" and always composed of 8 digits:
XXXXXXXX YYYYYYYY
To convert a RAW PS2 cheat code to a patch line to be used in a pnach file, one must add "patch=1,EE," before the first number and ",extended," before the second number:
patch=1,EE,XXXXXXXX,extended,YYYYYYYY
For example, a RAW PS2 cheat code could be:
00E98100 00000064
Converted to pnach-format:
patch=1,EE,00E98100,extended,00000064
This patch line will constantly write the 8-bit value 0x64 to the address 0xE98100.
Do note that loading a save-state will force PCSX2 to parse the .pnach contents.
Pnach format supports single-line ("//") comments. This means that prefixing a patch line with "//" it will be ignored.
So, we can say that a pnach file is a sequence of patch lines.
Below you can find the documentation of the code types available with their respective syntax.
Constant write[edit | edit source]
8-bit constant write[edit | edit source]
Writes the 8-bit value @v to the address @a.0aaaaaaa 000000vv
16-bit constant write[edit | edit source]
Writes the 16-bit value @v to the address @a.1aaaaaaa 0000vvvv
32-bit constant write[edit | edit source]
Writes the 32-bit value @v to the address @a.2aaaaaaa vvvvvvvv
Increment / Decrement[edit | edit source]
Increment/decrement the current value at address @a by value @v.
8-bit increment[edit | edit source]
300000vv 0aaaaaaa
8-bit decrement[edit | edit source]
301000vv 0aaaaaaa
16-bit increment[edit | edit source]
3020vvvv 0aaaaaaa
16-bit decrement[edit | edit source]
3030vvvv 0aaaaaaa
32-bit increment[edit | edit source]
30400000 0aaaaaaa vvvvvvvv 00000000
32-bit decrement[edit | edit source]
30500000 0aaaaaaa vvvvvvvv 00000000
Constant serial write[edit | edit source]
8-bit constant serial write[edit | edit source]
Starting with address @a, this code writes the 8-bit value @v to @n addresses.
In each cycle, the address is incremented by @s * 2 and the value is incremented by @i.
8aaaaaaa nnnnssss 000000vv 000000ii
16-bit constant serial write[edit | edit source]
Starting with address @a, this code writes the 16-bit value @v to @n addresses.
In each cycle, the address is incremented by @s * 2 and the value is incremented by @i.
8aaaaaaa nnnnssss 1000vvvv 0000iiii
32-bit constant serial write[edit | edit source]
Starting with address @a, this code writes the 32-bit value @v to @n addresses.
In each cycle, the address is incremented by @s * 4 and the value is incremented by @i.
4aaaaaaa nnnnssss vvvvvvvv iiiiiiii
Copy bytes[edit | edit source]
Copies a block of @n bytes from source address @s to destination address @d.5sssssss nnnnnnnn 0ddddddd 00000000
Pointer write[edit | edit source]
This code reads a pointer address @a, follows it @n pointers deep, and writes the @v value to the calculated address.
NOTE: Execution of this code type will stop if a NULL pointer is encountered to prevent a crash.
Single dereference (n <= 1)[edit | edit source]
Loads the 32-bit base address from address @a, adds offset @p_0 to it, and constantly writes the value @v to the calculated address.
Multiple dereferences (n > 1)[edit | edit source]
Loads the 32-bit base address from address @a, adds offset @p_0 to it to get an initial pointer address P_0. Dereference P_0 and add @p_1 to the result to get the next pointer address P_1. This is done @n times until the final address P_n is found, at which point the value @v is written to the calculated address.
8-bit pointer write[edit | edit source]
6aaaaaaa 000000vv 0000nnnn p_0 p_1 p_2 ........ ........ p_(n-1) p_n
16-bit pointer write[edit | edit source]
6aaaaaaa 0000vvvv 0001nnnn p_0 p_1 p_2 ........ ........ p_(n-1) p_n
32-bit pointer write[edit | edit source]
6aaaaaaa vvvvvvvv 0002nnnn p_0 p_1 p_2 ........ ........ p_(n-1) p_n
Bitwise operations[edit | edit source]
Performs a bitwise logical operation between the value @v and the value stored at address @a. Store the result at address @a.
8-bit OR[edit | edit source]
7aaaaaaa 000000vv
16-bit OR[edit | edit source]
7aaaaaaa 0010vvvv
8-bit AND[edit | edit source]
7aaaaaaa 002000vv
16-bit AND[edit | edit source]
7aaaaaaa 0030vvvv
8-bit XOR[edit | edit source]
7aaaaaaa 004000vv
16-bit XOR[edit | edit source]
7aaaaaaa 0050vvvv
Conditionals[edit | edit source]
C-Type[edit | edit source]
32-bit execute all following codes if equal to[edit | edit source]
All following codes will be executed only if 32-bit value at address @a is equal to the value @v.Caaaaaaa vvvvvvvv
D-Type (NOT RECOMMENDED)[edit | edit source]
Multi-line "if"[edit | edit source]
Compares value at address @a to value @v, and executes next @n lines only if the test condition @t is true. Values for @t are:
- 0 equal
- 1 not equal
- 2 less than
- 3 greater than
- 4 NAND
- 5 AND
- 6 NOR
- 7 OR
8-bit test[edit | edit source]
Daaaaaaa nnt100vv
16-bit test[edit | edit source]
Daaaaaaa nnt0vvvv
E-Type (RECOMMENDED)[edit | edit source]
Multi-line "if"[edit | edit source]
Compares value at address @a to value @v, and executes next @n lines only if the test condition @t is true. Values for @t are:
- 0 equal
- 1 not equal
- 2 less than
- 3 greater than
- 4 NAND
- 5 AND
- 6 NOR
- 7 OR
8-bit test[edit | edit source]
E1nn00vv taaaaaaa
16-bit test[edit | edit source]
E0nnvvvv taaaaaaaIt is possible to simulate the && (and) logical operator by having multiple E-Type codes one after the other. For example, the code below checks if the value at address 0x003E1110 is equal to 3 AND the value at address 0x0067381C is not equal to 0xFF. If both conditions are met, write the 32-bit value 0x12345678 to the address 0x003D4AB0:
E0020003 003E1110 E10100FF 1067381C 203D4AB0 12345678
Notes and clarifications[edit | edit source]
The true format of a patch line is:patch=<place>,<cpu>,XXXXXXXX,<data>,YYYYYYYY
place[edit | edit source]
The "place" field indicates how/when/where the patch line should be applied. If "place" is not one of the supported values then the patch line is never applied.
PCSX2 currently supports the following values:
- 0 - apply the patch line once on game boot/startup.
- 1 - apply the patch line continuously (technically - on every vsync).
- 2 - effect of 0 and 1 combined, see below.
Note:
While it may seem that a value of 1 does the same as 0, but also later continues to apply the patch on every vsync - it's not. The current (and past) behavior is that these patches are applied at different places at the code, and it's possible, depending on circumstances, that 0 patches will get applied before the first vsync and therefore earlier than 1 patches. There's no "place" value which indicates to apply both once on startup and then also continuously, however such behavior can be achieved by duplicating the line where one has a 0 "place" and the other has a 1 "place".
cpu[edit | edit source]
The "cpu" field indicates which memory the pnach should be targeting. If "cpu" is not one of the supported values then the patch line is never applied.
PCSX2 currently supports the following values:
- EE - Target the EE memory. EE stands for "Emotion Engine", it is the PS2 CPU's name.
- IOP - Target the IOP memory. IOP stands for Input/Output Processor.
data[edit | edit source]
The "data" field indicates which data type to consider when parsing the patch line.
PCSX2 currently supports the following values:
- If the "cpu" field is "EE":
- byte = 8-bit (1 byte)
- short = 16-bit (2 bytes)
- word = 32-bit (4 bytes)
- double = 64-bit (8 bytes)
- extended = N-bit (the data type is based on the instruction)
- leshort = 16-bit (2 bytes) in little endian
- leword = 32-bit (4 bytes) in little endian
- ledouble = 64-bit (8 bytes) in little endian
- If the "cpu" field is "IOP":
- byte = 8-bit (1 byte)
- short = 16-bit (2 bytes)
- word = 32-bit (4 bytes)
patch=1,EE,20E98100,double,12345678DEADBEEF
Useful links[edit | edit source]
- https://github.com/root670/CheatDevicePS2/wiki/Code-Types
- https://github.com/zzamizz/weed-sheet/wiki/PNACH-Code-Types
- https://github.com/mlafeldt/ps2rd/blob/master/Documentation/code_types.txt
- https://github.com/root670/CheatDevicePS2/blob/master/engine/engine_asm.S
- https://github.com/PCSX2/pcsx2/blob/fdabc82342d82227901c9a709b10f02dfe1801a3/pcsx2/Patch_Memory.cpp