Guide:Writing pnach files: Difference between revisions

Added navbox
(Added formatting)
(Added navbox)
 
(9 intermediate revisions by 2 users not shown)
Line 1:
{{Infobox guide
This guide contains documentation on how to write patches in pnach files.
| sly1 = y
| sly2 = y
| sly3 = y
}}
 
This guide contains documentation on how to write patch lines in pnach format.
== Constant writes ==0
=== 8-bit constant write ===
<pre>
0aaaaaaa 000000vv
</pre>
 
== Format ==
Constantly writes an 8-bit value @v to the address @a.
 
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.
=== 16-bit constant write ===
<pre>
1aaaaaaa 0000vvvv
</pre>
 
Pnach format supports single-line ("//") comments. This means that prefixing a patch line with "//" it will be ignored.
Constantly writes a 16-bit value @v to the address @a.
 
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.
 
{{Note for Bentley|The PNACH documentation below is all in RAW PS2 cheat format. To write a pnach file, you have to convert it to pnach format like above (formatted like `patch=1,EE,XXXXXXXX,extended,XXXXXXXX`).}}
 
== Constant write ==
 
=== 8-bit constant write ===
Writes the 8-bit value @v to the address @a.<pre>
0aaaaaaa 000000vv
</pre>
=== 16-bit constant write ===
Writes the 16-bit value @v to the address @a.<pre>
1aaaaaaa 0000vvvv
</pre>
=== 32-bit constant write ===
Writes the 32-bit value @v to the address @a.<pre>
<pre>
2aaaaaaa vvvvvvvv
</pre>
 
Constantly writes a 32-bit value @v to the address @a.
 
 
== Increment / Decrement ==
Increment/decrement the current value at address @a by value @v.
 
=== 8-bit increment ===
<pre>
Line 58 ⟶ 78:
vvvvvvvv 00000000
</pre>
Increments/decrements the value at address @a by the value @v.
 
== Constant serial write ==
 
=== 328-bit constant serial write ===
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.
<pre>
4-aaaaaaa8aaaaaaa nnnnssss
000000vv 000000ii
vvvvvvvv iiiiiiii
</pre>
 
=== 16-bit constant serial write ===
Starting with address @a, this code writes the 32-bit value @v to @n addresses.
Starting with address @a, this code writes the 16-bit value @v to @n addresses.
 
In each cycle, the address is incremented by @s * 42 and the value is incremented by @i.
<pre>
8aaaaaaa nnnnssss
1000vvvv 0000iiii
</pre>
 
=== 32-bit constant serial write ===
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.
=== Copy bytes ===
<pre>
4aaaaaaa nnnnssss
5-sssssss nnnnnnnn
vvvvvvvv iiiiiiii
</pre>
 
== Copy bytes ==
Copies a block of @n bytes from source address @s to destination address @d.<pre>
5sssssss nnnnnnnn
0ddddddd 00000000
</pre>
 
== Pointer write ==
Copies a block of @n bytes from source address @s to destination address @d.
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) ====
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) ====
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.
 
== Pointer write ==
=== 8-bit pointer write ===
<pre>
6-aaaaaaa6aaaaaaa 000000vv
0000nnnn iiiiiiii p_0
p_1 p_2
pppppppp pppppppp # 1st. extra pointer line, required if
........ ........ @n > 1
p_(n-1) p_n
pppppppp pppppppp # N-th. extra pointer line, required if
@n > ((N << 1) - 1)
</pre>
 
=== 16-bit pointer write ===
<pre>
6-aaaaaaa6aaaaaaa 0000vvvv
0001nnnn iiiiiiii p_0
p_1 p_2
pppppppp pppppppp
........ ........
p_(n-1) p_n
pppppppp pppppppp
</pre>
 
=== 32-bit pointer write ===
<pre>
6-aaaaaaa6aaaaaaa vvvvvvvv
0002nnnn iiiiiiii p_0
p_1 p_2
pppppppp pppppppp
........ ........
p_(n-1) p_n
pppppppp pppppppp
</pre>
 
== Bitwise operations ==
This code reads a pointer address @a and follows it @n pointers deep. This is how it does it:
Performs a bitwise logical operation between the value @v and the value stored at address @a. Store the result at address @a.
 
# Loads the 32-bit pointer base from address @a
# Add offset @i to it to get either:
# If @n is 1, the final address. Skip to step 5.
# If @n > 1, a new pointer location. Continue to step 3.
# Load the 32-bit pointer address from the address computed at the previous step and add offset @p to it.
# Keep doing this until all (@n - 1) offsets @p have been processed
Constantly write the value @v to the final address.
 
 
== Bitwise operations ==
=== 8-bit OR ===
<pre>
7-aaaaaaa7aaaaaaa 000000vv
</pre>
 
=== 16-bit OR ===
<pre>
7-aaaaaaa7aaaaaaa 0010vvvv
</pre>
 
=== 8-bit AND ===
<pre>
7-aaaaaaa7aaaaaaa 002000vv
</pre>
 
=== 16-bit AND ===
<pre>
7-aaaaaaa7aaaaaaa 0030vvvv
</pre>
 
=== 8-bit XOR ===
<pre>
7-aaaaaaa7aaaaaaa 004000vv
</pre>
 
=== 16-bit XOR ===
<pre>
7-aaaaaaa7aaaaaaa 0050vvvv
</pre>
 
== Conditionals ==
Performs a bitwise logical operation between the value @v and the value stored at address @a.
 
=== C-Type ===
 
==== 32-bit execute all following codes if equal to ====
All following codes will be executed only if 32-bit value at address @a is equal to the value @v.<pre>
Caaaaaaa vvvvvvvv
</pre>
 
=== D-Type (NOT RECOMMENDED) ===
== 8-bit / 16-bit constant serial write ==
 
=== 8-bit write ===
==== Multi-line "if" ====
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 ====
<pre>
Daaaaaaa nnt100vv
8-aaaaaaa nnnnssss
000000vv 000000ii
</pre>
 
==== 16-bit writetest ====
<pre>
Daaaaaaa nnt0vvvv
8-aaaaaaa nnnnssss
1000vvvv 0000iiii
</pre>
 
=== E-Type (RECOMMENDED) ===
Starting with address @a, this code type will write the value @v to @n addresses.
 
==== Multi-line "if" ====
In each cycle, the address is incremented by @s or @s * 2 and the value is incremented by @i.
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 ====
<pre>
E1nn00vv taaaaaaa
</pre>
 
==== Conditionals16-bit test ====
=== 32-bit do all following codes if equal to ===
<pre>
E0nnvvvv taaaaaaa
C-aaaaaaa vvvvvvvv
</pre>It 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:<pre>
E0020003 003E1110
E10100FF 1067381C
203D4AB0 12345678
</pre>
==Notes and clarifications==
The true format of a patch line is:<pre>
patch=<place>,<cpu>,XXXXXXXX,<data>,YYYYYYYY
</pre>
 
=== place ===
All following codes will be executed only if 32-bit value at address @a is equal to the value @v.
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:
=== Do multi-lines if conditional ===
=== 16-bit test ===
<pre>
D-aaaaaaa 0000vvvv
</pre>
 
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".
=== 8-bit test ===
<pre>
D-aaaaaaa 000000vv
</pre>
 
=== cpu ===
Compares value at address @a to value @v, and executes next 1 code lines if the value is equal
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.
=== Do multi-lines if conditional ===
* IOP - Target the IOP memory. IOP stands for Input/Output Processor.
=== 16-bit test ===
 
<pre>
=== data ===
E-0nnvvvv taaaaaaa
The "data" field indicates which data type to consider when parsing the patch line.
</pre>
 
PCSX2 currently supports the following values:
=== 8-bit test ===
 
<pre>
# If the "cpu" field is "EE":
E-1nn00vv taaaaaaa
#* 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)
 
While it is recommended to use the "extended" value, one might find the "double" data type useful to write 8 bytes in a single line (which would require 2 32-bit writes instructions):<pre>
patch=1,EE,20E98100,double,12345678DEADBEEF
</pre>
==Useful links==
 
* https://github.com/root670/CheatDevicePS2/wiki/Code-Types
Compares value at address @a to value @v, and executes next @n code llines only if the test condition @t is true. Values for @t are:
* https://github.com/zzamizz/weed-sheet/wiki/PNACH-Code-Types
* 0 equal
* https://github.com/mlafeldt/ps2rd/blob/master/Documentation/code_types.txt
* 1 not equal
* https://github.com/root670/CheatDevicePS2/blob/master/engine/engine_asm.S
* 2 less than
* https://github.com/PCSX2/pcsx2/blob/fdabc82342d82227901c9a709b10f02dfe1801a3/pcsx2/Patch_Memory.cpp
* 3 greater than
* 4 NAND
* 5 AND
* 6 NOR
* 7 OR
 
{{WikiSEO helper
| keywords = pnach,patch,pcsx2,codes,cheats,cheat codes
}}
 
{{Navbox guides}}