Guide:Writing pnach files: Difference between revisions

Added navbox
(Tweaked headers)
(Added navbox)
 
(8 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 ==
 
=== 8-bitFormat constant write ===
<pre>
0aaaaaaa 000000vv
</pre>
 
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:
Constantly writes an 8-bit value @v to the address @a.
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.
=== 16-bit constant write ===
<pre>
1aaaaaaa 0000vvvv
</pre>
 
So, we can say that a pnach file is a sequence of patch lines.
Constantly writes a 16-bit value @v to the address @a.
 
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>
 
== Increment / Decrement ==
Constantly writes a 32-bit value @v to the address @a.
Increment/decrement the current value at address @a by value @v.
 
 
== Increment / Decrement ==
=== 8-bit increment ===
<pre>
Line 59 ⟶ 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.
 
In each cycle, the address is incremented by @s or @s * 2 and the value is incremented by @i.
 
==== 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
 
==== Conditionals8-bit test ====
=== 32-bit do all following codes if equal to ===
<pre>
E1nn00vv taaaaaaa
C-aaaaaaa vvvvvvvv
</pre>
 
All following codes will be executed only if 32-bit value at address @a is equal to the value @v.
=== Do multi-lines if conditional ===
 
==== 16-bit test ====
<pre>
E0nnvvvv taaaaaaa
D-aaaaaaa 0000vvvv
</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>
==== 8-bit test ====
patch=<place>,<cpu>,XXXXXXXX,<data>,YYYYYYYY
<pre>
D-aaaaaaa 000000vv
</pre>
 
=== place ===
Compares value at address @a to value @v, and executes next 1 code lines if the value is equal
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.
=== Do multi-lines if conditional ===
* 1 - apply the patch line continuously (technically - on every vsync).
* 2 - effect of 0 and 1 combined, see below.
 
Note:
==== 16-bit test ====
 
<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".
E-0nnvvvv taaaaaaa
</pre>
 
==== 8-bitcpu test ====
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.
<pre>
 
E-1nn00vv taaaaaaa
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 ===
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)
 
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}}