First of all, don't forget that for codes we should use hexadecimal count system,
it means we should count like 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10, 11, 12...
In PSP an address takes seven digits
Addresses and values for PSP and for ppsspp are the same when you make a code
but addresses are different for searching, the difference is 08800000
for example if in PSP an address is 0407A18 then in ppsspp this address is 08C07A18 (0407A18 + 08800000 = 08C07A18)
Basics
Usually we use two kinds of lines to make codes:
"constant" - when you write to memory
"condition" - when you read memory
Let's use these words as terms
For example
Constant is 0x20407A08 0x00000217 means "on address 0407A08 value is 217"
Condition is 0xE0XX0217 0x00407A08 means "if value on 0407A08 is 217"
This "XX" in the middle of the first part means how many next lines will work if this condition is "true"
For example
0xE0010217 0x00407A18
0xXXXXXXXX 0xXXXXXXXX
Or
0xE0020217 0x00407A18
0xXXXXXXXX 0xXXXXXXXX
0xXXXXXXXX 0xXXXXXXXX
Or
0xE0050217 0x00407A18
0xXXXXXXXX 0xXXXXXXXX
0xXXXXXXXX 0xXXXXXXXX
0xXXXXXXXX 0xXXXXXXXX
0xXXXXXXXX 0xXXXXXXXX
0xXXXXXXXX 0xXXXXXXXX
You can combine them like this:
0xE0020217 0x00407A18
0xE0010512 0x00408348
0xXXXXXXXX 0xXXXXXXXX
But don't use the same address two times:
0xE01D0217 0x00407A18
0xXXXXXXXX 0xXXXXXXXX
0xXXXXXXXX 0xXXXXXXXX
0xE0010512 0x00407A18
0xXXXXXXXX 0xXXXXXXXX
It makes no sense!
I often write "1D" because it's the max amount of lines in one cheat code (for PSP)
But i do it only if i sure that this condition must work for all code lines and it will not conflict with other conditions
There are 8bit, 16bit and 32bit addresses.
32bit addresses contain 8 digits in value and end with 0, 4, 8 or C
16bit addresses contain 4 digits in value and end with 0, 2, 4, 6, 8, A, C or E
8bit addresses contain 2 digits in value and end with any digit.
Another important thing is the digit that you use in beginning of a constant line,
it regulates how many digits in the value will work
0x2 means all eight digits will work
0x1 means four digits will work
0x0 means two digits will work
!You can use 0x2 only for 32bit addresses!
!You can use 0x1 only with 32bit and 16bit addresses!
For example 0407A18 is 32bit address, so if you write:
0x20407A18 0x12345678 - you write to memory "12345678"
0x10407A18 0x12345678 - you write to memory only "5678", the rest part will be ignored
0x00407A18 0x12345678 - you write to memory only "78", all the rest will be ignored
You can write one 32bit address as two 16bit addresses
0x10407A18 0x00005678
0x10407A1A 0x00001234
Or you can write it as four 8bit addresses
0x00407A18 0x00000078
0x00407A19 0x00000056
0x00407A1A 0x00000034
0x00407A1B 0x00000012
And the same thing for conditions, 0xE0 means 16bit condition, 0xE1 means 8bit condition
0xE0XX5678 0x00407A18
0xE0XX1234 0x00407A1A
Is the same to
0xE1XX0078 0x00407A18
0xE1XX0056 0x00407A19
0xE1XX0034 0x00407A1A
0xE1XX0012 0x00407A1B
Getting some experience
Each code usually starts with the "condition of character"
Address which shows number of character is 04078B4 (08C078B4 in ppsspp), so the code line must be
0xE0XX00YY 0x004078B4 - YY is number of character
To get value for YY in PSP:
Open CWCheat / "Cheat searcher" / "Changes finder"
Type 004078B4
To get value for YY in ppsspp:
Open "Debug" / "Memory View" (or press Ctrl+M)
Type in the "Goto" 08C078B4 and press Enter
After this choose your character as P1 and see the value, for example number of Yoshimitsu is 04
To get some experience let's change a hit rank
Address which regulates hit rank of P1's moves is 0407A08
General values are:
512 - High
217 - Mid
10F - Low
So, if you want Yoshimitsu to have all moves as Mid, you should make such code
_C0 Hit Rank, test1
_L 0xE0010004 0x004078B4 - if Yoshi
_L 0x20407A08 0x00000217 - then hit rank is Mid
Or you can change only specific hit rank
_C0 Hit Rank, test2
_L 0xE0020004 0x004078B4 - if Yoshi
_L 0xE0010217 0x00407A08 - if hit rank is Mid
_L 0x20407A08 0x0000010F - then hit rank is Low
This code will change for Yoshimitsu all Mid moves to Low, but High moves will work as usual
If you want to change hit rank only for a specific move you should add "condition of a move"
We use 0407A18 to set a condition of an ordinal move number
It's like a move identification which shows which move is going
To get a value from this address we should repeat all steps like we did with number of characters
but now we need to get four digits
In PSP:
Open CWCheat / "Cheat searcher" / "Changes finder"
Type 00407A18
Press Square button to set 16bit (because we need four digits)
If a character does not perform a move you see the value is "8001"
In ppsspp:
Open "Debug" / "Memory View" (or press Ctrl+M)
Type in the "Goto" 08C07A18 and press Enter
If a character does not perform a move you see the value is "01 80"
It's how the emulator shows values, to use it in a code you have to turn it backwards
So in real the value is "8001"
Let's try to change rank for Yoshimitsu f+3
We need to get a value before a move hits an opponent
In PSP
Open CWCheat / "Settings"
Set the "Controller check delay" to 0, it allows to open CWCheat immediately
In ppsspp:
Press F8 to pause the game
While f+3 you see the value is 01DE, so now we can make such code
_C0 Hit Rank, test3
_L 0xE0020004 0x004078B4 - if Yoshi
_L 0xE00101DE 0x00407A18 - if during f+3
_L 0x20407A08 0x00000217 - then hit rank is Mid
This code will change hit rank only for Yoshimitsu f+3 but all the rest moves will work as usual
Modify moves
To modify moves we use two groups of addresses
Both groups show the same values, the difference is only in the time
The first group shows values during whole move (from the first to the last frame)
The second group - only from the moment when you press button(s) to the moment when this move starts
Addresses of the first group:
0407A18 - ordinal move number
0407964 - pointer to the current move
Addresses of second group:
0407D1C - ordinal move number
0407D24 - pointer to move
The main address which regulates which move P1 performs is 0407D24 (08C07D24 in ppsspp)
But since the second group shows values very fast we have to use a "double-address" from the first group, it's 0407964
Let's try to modify a Jin's move, for example force him to perform EWHF
Choose Jin vs Paul (it's important) and do the move
Now we need to get eight digits
In PSP:
Open CWCheat / "Cheat searcher" / "Changes finder"
Type 00407964
Press Square button to set 32bit
When you get back to the game you see the value is "0870B274"
In ppsspp:
Open "Debug" / "Memory View" (or press Ctrl+M)
Type in the "Goto" 08C07964 and press Enter
You see the value is "74 B2 70 08", when you turn it backwards you get "0870B274"
Let's make a simple code with it
_C0 Modify move, test1
_L 0xE0010009 0x004078B4 - if Jin (number of Jin is 09)
_L 0x20407D24 0x0870B274 - performs EWHF
You see Jin performs EWHF all the time, we cannot control him anymore and he even does not react on opponent's attacks
To make it work properly we need to add "condition of move" as a limiter, for example ordinal move number
We can use both addresses which show ordinal move number, as from the first group as from the second
But since 0407D24 is from the second group let's use move number address from the second group too, it's 0407D1C
And the same like we did with 0407D24 we have to use one address in the code but take values from another
Do a move which you want to change to EWHF, for example d/f+2, it will like a trigger
In PSP:
Open CWCheat / "Cheat searcher" / "Changes finder"
Type 00407A18
In ppsspp:
Open "Debug" / "Memory View" (or press Ctrl+M)
Type in the "Goto" 08C07A18 and press Enter
You see that ordinal move number of d/f+2 is 024B, so now we already can make such code
_C0 Modify move, test2
_L 0xE0020009 0x004078B4 - if Jin
_L 0xE001024B 0x00407D1C - if d/f+2 starts
_L 0x20407D24 0x0870B274 - performs EWHF
Now Jin will perform EWHF when you press d/f+2, but this code is not stable yet
Disable these codes and Choose Jin vs Alisa (it's important)
Do EWHF and take look at the value on 0407964, you see it's not 0870B274 anymore, now it's 087B6E74
Tekken 6 has a feature, all move pointers have two variants
It happens because P1 and P2 locate their move bases in two places
Who has a bigger number that locate move base in the first place, another - in the second place
Paul has number 0 (very first), Alisa has number 29 (the last)
So if you choose your character vs Paul that it will have the first variant of pointers, if vs Alisa - the second variant
To make codes work stable we should consider it
Address which shows which variant of pointer P1 has is 04078E0
If it's the first variant then value is 086A8800, the second variant - 08754400
We can use it for recognition
_C0 Modify move, test3
_L 0xE0050009 0x004078B4 - if Jin
_L 0xE004024B 0x00407D1C - if d/f+2 starts
_L 0xE001086A 0x004078E2 - if first variant
_L 0x20407D24 0x0870B274 - performs EWHF vs Paul
_L 0xE0010875 0x004078E2 - if second variant
_L 0x20407D24 0x087B6E74 - performs EWHF vs Alisa
Now this code works stable
You can also make it with using 0407A18 but since 0407A18 and 0407D24 are in different time groups EWHF will start only when d/f+2 will completely end
To fix it we have to use an address which regulates when following move must start during the current one, it's 0407D10
And code will look like this
_C0 Modify move, test3a
_L 0xE0060009 0x004078B4 - if Jin
_L 0xE005024B 0x00407A18 - if during d/f+2
_L 0x20407D10 0x00000000 - then immediately
_L 0xE001086A 0x004078E2 - if first variant
_L 0x20407D24 0x0870B274 - performs EWHF vs Paul
_L 0xE0010875 0x004078E2 - if second variant
_L 0x20407D24 0x087B6E74 - performs EWHF vs Alisa
You can experiment with value for 0407D10 and set any delay what you want
d/f+2 hits an opponent on 15th frame (15 in dec = 0F in hex)
So if you change value for 0407D10 to 0F then d/f+2 will hit an opponent two times, as original d/f+2 and as EWHF
_C0 Modify move, test3b
_L 0xE0060009 0x004078B4 - if Jin
_L 0xE005024B 0x00407A18 - if during d/f+2
_L 0x20407D10 0x0000000F - then on 15th frame (in dec)
_L 0xE001086A 0x004078E2 - if first variant
_L 0x20407D24 0x0870B274 - performs EWHF vs Paul
_L 0xE0010875 0x004078E2 - if second variant
_L 0x20407D24 0x087B6E74 - performs EWHF vs Alisa
And by the same way we can make a custom string
Let's take Jin 3,1 now, ordinal move number (on 0407A18) is 1E0
We can continue it for example with WS+1,2 (so in result we will have 3,1,2)
For this we need to add a condition of button press, the 8bit address which shows it is 0407D3C (08C07D3C in ppsspp)
1 - Square
2 - Triangle
4 - Cross
8 - Circle
We will do it with Triangle button
And also we need to limit the time when a user can press this button
Address which shows current frame of current move is 0407940 (08C07940 in ppsspp)
3,1 hits an opponent on 14th frame (in hex)
But if we add such condition 0xE0XX0014 0x00407940 we will have a justframe input 3,1:2
To fix it we should use another option in a condition line
0xEYXXVVVV 0xZAAAAAAA - instead of Z use:
0 - if VVVV is equal to value on address AAAAAAA
1 - if VVVV is not equal to value on address AAAAAAA
2 - if VVVV is less than value on address AAAAAAA
3 - if VVVV is greater than value on address AAAAAAA
User must have time for pressing a button from 1st to the 14th frame, so the condition line must be 0xE0XX0014 0x20407940
And in a result the code will look like this
_C0 Modify move, test4
_L 0xE0080009 0x004078B4 - if Jin
_L 0xE00701E0 0x00407A18 - if during 3,1
_L 0xE0060014 0x20407940 - if this move is less 14 frames (in hex)
_L 0xE1050002 0x00407D3C - if press Triangle button
_L 0x20407D10 0x00000014 - then on 14th frame (in hex)
_L 0xE001086A 0x004078E2 - if first variant
_L 0x20407D24 0x08708D54 - performs WS+1,2 vs Paul
_L 0xE0010875 0x004078E2 - if second variant
_L 0x20407D24 0x087B4954 - performs WS+1,2 vs Alisa
We can continue this string further but since we added 3,1,2 in a custom way we face a problem. Value on 0407A18 is 0000 now, we cannot use only this address to identify our move. We have to use other move features while P1 performs it, for example pointer on 0407964. Though move pointers are different vs Paul and vs Alisa, the last two digits are always the same. We settled on 3,1,2 which has move pointers 08708D54 (vs Paul) and 087B4954 (vs Alisa). You see the last two digits are 54 in both cases, we can use it as 8bit condition for 0407964
Let's continue 3,1,2 with f+4
_C0 Modify move, test5
_L 0xE0090009 0x004078B4 - if Jin
_L 0xE0080000 0x00407A18 - if during a custom move
_L 0xE1080054 0x00407964 - if move pointer ends with "54"
_L 0xE0060016 0x20407940 - if this move is less 16 frames (in hex)
_L 0xE1050008 0x00407D3C - if press Circle button
_L 0x20407D10 0x00000016 - then on 16th frame (in hex)
_L 0xE001086A 0x004078E2 - if first variant
_L 0x20407D24 0x087098AC - performs f+4 vs Paul
_L 0xE0010875 0x004078E2 - if second variant
_L 0x20407D24 0x087B54AC - performs f+4 vs Alisa
What is a pointer
A pointer is a special kind of value. In this case it does not write anything to memory directly. The value becomes a "link" which follows to another memory area. Let's start with a simple example, take a look at the value on address 0407F98.
In PSP:
Open CWCheat / "Cheat searcher" / "Disassembler" and scroll to 0407F98.
You see, the value is 08C07860, this is a link.
To get the area which it links to, you must decrease 08800000 (08C07860 - 08800000 = 00407860) and scroll to this address.
In ppsspp:
Open "Debug" / "Memory View" (or press Ctrl+M)
(0407F98 + 08800000 = 08C07F98) Type in the "Goto" 08C07F98 and press Enter
You see, the value is 08C07860, this is a link.
To get the area which it links to, type it in the "Goto" also.
Let's try to change hit rank using this pointer
There are special code lines we must use for this:
_L 0x6AAAAAAA 0xVVVVVVVV
_L 0x000Y000T 0xSSSSSSSS
These lines must be always together. Never separate them! Especially when you pick a number for the middle of the first part of a Condition line.
AAAAAAA - is the address which has pointer value (in our example it's 0407F98).
VVVVVVVV - is the value you want to be written in result (in our example it's 217).
Y - is datatype of value, 0 means 8bit, 1 means 16bit, 2 means 32bit (our value 217 has three digits, so we must use 1 or 2).
T - is number of "steps" in this pointer (we have only one here) (and btw. ppsspp supports only one "step").
SSSSSSSS - is an offset, i.e. it's a distance from the link address (0407860) to the address which we want (0407A08), so 0407A08 - 0407860 = 1A8
Thus in result the code will look like this
_C0 Hit Rank, test4
_L 0x60407F98 0x00000217
_L 0x00020001 0x000001A8
This is absolutely the same to _L 0x20407A08 0x00000217.
In messages and posts we often describe pointer's steps like "0407F98=>1A8". Just to say it faster.
It means - take a value that you see at 0407F98 (for example 08C07860) and increase it by 1A8.
Structure of a move
You might be already understood that values which we use for 0407964/68 and for 0407D24 are pointers. They point to structure of a move. If we recreate this structure somewhere in an empty area of the game we can use it as a custom move. In Tk6 one move takes 0x58 bytes, it's the same for all characters. There is an empty area in Tk6 starting from 0884000, so if you wanna build a custom move there then it must look like this:
_C0 Building custom move
_L 0x20884000 0x08B98190 // technical pointer (not in use in Tk6)
_L 0x20884004 0x08B98190 // technical pointer (not in use in Tk6)
_L 0x20884008 0x08F51FC8 // pointer to animation (list of all P0 animations)
_L 0x2088400C 0x00000842 // body state for opponent's attacks (842 means body stands, no block)
_L 0x20884010 0x00000217 // hit rank (217 means mid)
_L 0x20884014 0x08E41530 // pointer to recovery/strings
_L 0x20884018 0x00008001 // visual recovery (8001 means default stance)
_L 0x2088401C 0x00000000 // technical id (not necessary)
_L 0x20884020 0x08E413F8 // pointer to reactions/damage
_L 0x20884024 0x0000004A // length of move (74 frames in DEC)
_L 0x20884028 0x00000000 // midair state "from" (not necessary)
_L 0x2088402C 0x00000000 // midair state "to" (not necessary)
_L 0x20884030 0x00000000 // frame of ground fall (not necessary)
_L 0x20884034 0x00000000 // pointer to base hit/block sounds (not necessary)
_L 0x20884038 0x00000000 // pointer to audio/visual effects (not necessary)
_L 0x2088403C 0x00000000
_L 0x20884040 0x00000000
_L 0x20884044 0x08000000 // extra properties of body
_L 0x20884048 0x0000000D // attacking limb (list of all limbs)
_L 0x2088404C 0x00000023 // the frame of attack "from"
_L 0x20884050 0x00000024 // the frame of attack "to"
_L 0x20884054 0x00000000 // extra properties, like movement of body in the air, displacement of colliders (rare using).
(red values are important, you can't set zeros for them)
So, all these values together are one move. When i say "move" i also mean a stance, a throw, a reaction, a cutscene, etc. They all are moves. To apply this move you must increase the first address by 08800000 (0884000 + 08800000 = 09084000) and add conditions as before.
_C0 JIN u/f+1+2 custom move
_L 0xE0020009 0x004078B4 // if Jin
_L 0xE00102FC 0x00407D1C // if u/f+1+2
_L 0x20407D24 0x09084000 // custom move
For custom moves you don't have to get values vs Paul and vs Alisa but if you use "recovery/string" pointer or "reactions/damage" pointer from a character then you have to.