I recomend that you read the intire guide before trying anything. If you have any questions read over the guide one more time before PM-ing me or posting a reply, most likely I said something that will clear it up for you in this guide.
Before reading this guide I am expecting that you know:
- Exact Value Searching
- Unknown Value Searching
- Text Searching
- Single Level DMA
- How to write a basic subroutine such as this:
Code:
Lui t0 $XXXX
Lui t1 $XXXX
Addiu t1 t1 $XXXX
Sw t1 $XXXX(t0)
Jr ra
Some of those are not NEEDED to know for this tutorial but they will help.
First of all you need to know what a joker is: A joker is a code that does something when you press a button. Now when learning this
it might take you a few tries, it took me like two months :P but hopefuly this guide will help you!
Basic Information:
Spoiler
Bits:
8-Bits: 0xYY
16-Bits: 0xYYYY
32-Bits: 0xYYYYYYYY
Bits are used to messure the size of a value, here are some examples:
8-Bits: 0x2B
16-Bits: 0xB770
32-Bits: 0xAB780220
============================================
Real Addressing:
In the PSP, memory addresses don't start at 0 like most people would think (That use computers a lot, computers start counting at 0
and not 1 like we actually count by) memory addresses start at 08800000. NitePR and NitePR mods add 08800000 to the addresses before
executing the line, if we use a memory address lower than 08800000 in are MIPS subroutines (NitePR and NitePR mods don't go through
are subroutines and add 08800000 to are codes) then we will freeze because there is no such address. So some times you will see this
line:
Lui t0 $0880
This is just loading 08800000 into t0, then we can use another command like lw or sw to get or put a value to/from a memory address.
This might be a little confusing right now, but just think this: Addresses on the PSP start at 08800000 and not 0
============================================
Loading vs Storing:
Loading: The Proccess of moving a value into a register
Storing: The proccess of moving a value from a register and storing it to the value of a memory address's value
============================================
Registers:
Registers are like boxes that we can use to hold a value for us. There are around 60 or so registers mainly used in PSP coding, each
type of register will hold a value differently.
You will be learning some MIPS commands:
Lui
Addi
Bne
Beq
Nop
Lw
Sw
Jr
J
You can learn them here:
Spoiler
Lui - Load Upper Immediate
Loads a 16-Bit immediate value into the upper half of a register:
Lui t0 $172B
t0 = 0x172B0000
Addi - Add Immediate
Adds the contents of one register to a 16-Bit immediate value and puts the result into another register:
Addi t0 zero $9900
This is saying: t0 = zero + 0x00009900
t0 = 0x00009900
Bne - Branch on Not Equal
Checks the contents of two registers, if they are not equal then we will go to another address:
Addi t0 zero $9
Addi t1 zero $4
Bne t0 t1 $08801200
Nop
This would branch us to the address 0x08801200 because 9 doesn't equal 4. Always nop the line after a branch.
Beq - Branch on Equal
Checks the contents of two registers, if they are equal then we will go to another address:
Addi t0 zero $9
Addi t1 zero $4
Beq t0 t1 $08801200
Nop
This would not branch us to the address 0x08801200 because 9 doesn't equal 4. Always nop the line after a branch.
Nop - No Opperation
This command does nothing
Lw - Load Word
Loads a full 32-Bit value from a memory address's value and puts it into a register:
Lui t0 $0880
Lw t0 $1000(t0)
t0 = the value at memory address {(t0) + 0x00001000} so t0 = the value at address 0x08801000
If this code was on: 0x00001000 0x12345678 then t0 would = 0x12345678
Sw - Store Word
Stores a 32-Bit value from the contents of a register to the value of a memory address
Lui t0 $1212
Addi t0 t0 $3434
// t0 now holds the value 0x12123434
Lui t1 $0880
Sw t0 $1000(t0)
The value at address 0x00001000 would not equal 0x12123434
Jr - Jump Register
When a line is read with the jr command in it we will goto the memory address held in the register used:
Lui t0 $0880
Addi t0 t0 $1000
Jr t0
We would goto memory address 0x08801000
J - Jump
When a line is read with the j command in it we will goto the specified memory address:
J $08801000
We would goto memory addreess 0x08801000
You will also need to know some basic registers, think of registers as a box that can hold a value for you, here is the list:
zero
t0
t1
t2
t3
t4
t5
t6
t7
t8
t9
ra
Now the zero register will always hold the value 0, this can not be changed. The temporary registers (t0 - t9) will hold a value that
we want them to, until we put a value into them there value is 0. The return address register (ra) is going to hold a memory address,
this memory address is the address below are hook, which calls are subroutine, I will be going over this later.
So all a joker really is is this:
- Get current value from controller address
- Load a button value into a register
- Check if they equal, if not go to the end of the subroutine, if they do continue on here:
- Activate a code, or turn a code off, or what ever you want to do really
- End the subroutine
Doesn't seem so hard right? Well it's not really. Now if this is your first jokering tutorial you might not know what a controller
address is, well a controller address is a memory address in games that functions use to see what button you are pressing. In most
games there will be one controller address for all buttons, but in some games such as the Star Wars Battlefront series there are a
memory address for each button. Now let's say that you are using a game with only one controller address, it's value can be a few
different things, and each value represents a button. In most games with one controller address the button values are these:
Select button = 0x00000001
Start button = 0x00000008
Up D-Pad button = 0x00000010
Right D-Pad button = 0x00000020
Down D-Pad button = 0x00000040
Left D-Pad button = 0x00000080
Left trigger = 0x00000100
Right trigger = 0x00000200
Triangle button = 0x00001000
Circle button = 0x00002000
Cross button = 0x00004000
Square button = 0x00008000
Now how do you find your controller address? Simple:
Games with one controller address and the normal button values:
Spoiler
- Set pause game to true
- Go into the game, press a button, continue to press that button and open your cheat device
- Do an exact value search for the button value for the button you where pressing
- Once the search is done exit your cheat device and change to another button, then search again
Keep doing this until you get an address for the button you are pressing.
Games with one controller address but not normal button values:
Spoiler
- Set pause game to true
- Click "Find Unknown Value 32-Bit" of what ever it is in your cheat device
- Once it is done "setting" the 32-Bit search exit your cheat device and hold down a button then while holding the button open your
cheat device
- Search "2 = Greater"
- Now exit your cheat device and let go of all buttons, open your cheat device and do an exact value search for 0x00000000
Keep doing this until you find an address that has a value for each button, copy the address to the decoder and then look at the value
after pressing a button to find the value for that button.
Games with a controller address for each button:
Spoiler
- Do the "Games with one controller address but not normal button values:" method but only use one button at a time.
You will need to find one address for each button.
Now in some games if you set the value to 0x200 or what ever the value is for the R button you might not get the result of normally
pressing the R button. This doesn't mean that that address is not your controller address. All a controller address has to do is have a value change when you stop/start pressing a button.
Now we are going to start writing are subroutine, earlyer I said:
- Get current value from controller address
- Load a button value into a register
- Check if they equal, if not go to the end of the subroutine, if they do continue on here:
- Activate a code, or turn a code off, or what ever you want to do really
- End the subroutine
Well here is ONE way of doing that in MIPS:
Lui t0 $XXXX // Upper controller address in true addressing
Lw t0 $XXXX(t0) // Lowe controller address
// t0 now holds the current value in the controller address
Addi t1 zero $XXXX // Button value that you want to use to turn your code on
// t1 Now holds are button value
Bne t0 t1 ${Address of the "JR RA" line}
Nop
// This is saying: if we are not pressing the button jump to the jr ra line.
// All you have to do is copy the address that the jr ra is on and paste it after the $
// I leave this at 0 before until I finish my subroutine
// Now we are going to make a code activate
Lui t2 $XXXX // Upper code address in true addressing
Lui t3 $XXXX // Upper code value
Addi t3 t3 $XXXX // Lower code value
Sw t3 $XXXX(t2) // Lower code address
// Now are code will activate
Jr ra
// This is going to goto the address in the ra register, which is right after our subroutine call (aka our hook)
// Just think of this as ending the subroutine
Make sure to check the MIPS explinations that I posted above. Here is an example for Medal of Honor Heroes (ULUS-10141)
Code:
#Exit Game Joker
;TheEliteOne aka -LeetGamer-
;Press Left to exit the game.
0x00339D78 0x0A2A21AC
0x002886B0 0x3C0808d4
0x002886B4 0x850842B0
0x002886B8 0x34090080
0x002886BC 0x15280003
0x002886C4 0x0E324Add
0x002886CC 0x03E00008
That is a code to exit to the home menu, it is a good example of a joker.
So in this tutorial we have gone over how to make a "joker" and that joker will turn on one code when we press a button. Now we can add as many codes in there as we want, example:
Spoiler
Lui t0 $XXXX // Upper controller address in true addressing
Lw t0 $XXXX(t0) // Lowe controller address
// t0 now holds the current value in the controller address
Addi t1 zero $XXXX // Button value that you want to use to turn your code on
// t1 Now holds are button value
Bne t0 t1 ${Address of the "JR RA" line}
Nop
// This is saying: if we are not pressing the button jump to the jr ra line.
// All you have to do is copy the address that the jr ra is on and paste it after the $
// I leave this at 0 before until I finish my subroutine
// Now we are going to make a code activate
Lui t2 $XXXX // Upper code address in true addressing
Lui t3 $XXXX // Upper code value
Addi t3 t3 $XXXX // Lower code value
Sw t3 $XXXX(t2) // Lower code address
Lui t2 $XXXX // Upper code address in true addressing
Lui t3 $XXXX // Upper code value
Addi t3 t3 $XXXX // Lower code value
Sw t3 $XXXX(t2) // Lower code address
Lui t2 $XXXX // Upper code address in true addressing
Lui t3 $XXXX // Upper code value
Addi t3 t3 $XXXX // Lower code value
Sw t3 $XXXX(t2) // Lower code address
Lui t2 $XXXX // Upper code address in true addressing
Lui t3 $XXXX // Upper code value
Addi t3 t3 $XXXX // Lower code value
Sw t3 $XXXX(t2) // Lower code address
// Now are code will activate
Jr ra
// This is going to goto the address in the ra register, which is right after our subroutine call (aka our hook)
// Just think of this as ending the subroutine
If you want an example of another type of joker besides a simple one button turn code on type reply to this thread and I will let you know how.
Subroutine Calls and Our Hook:
Spoiler
This is not NEEDED to know, but it is VERY useful to know if you are wanting to learn more about MIPS and subroutines.
A subroutine call is basically calling a mini-computer on your phone, this mini-computer is going to do what ever we codded into are subroutine. So we call it and it does what we asked it to do when we wrote the MIPS for the subroutine.
A subroutine call is also known as a hook.
A hook is a Jump command, usually J and Jal. A hook needs a specific address to work right, there are a lot of hooks in every game. They have to be "active" in the game. Let's say you are in the menu and there was a J in the game to call the shooting function, well since you are in the menu you wouldn't be able to sue that hook because you couldn't shoot. If you had a hook that called the shooting function and you used it on your subroutine then your subroutine would only activate when you shot. Most hooks are calls to functions that you don't even know exist. I'm not really going into it that much more, but if you just add your subroutine without a hook then it won't work because (Most the game you are writing it in a nop cave) games don't read nop caves, they don't do anything with them really (Most the time) so why would your subroutine activate? It wouldn't, so you need to have a part of the game that the game is actually using to call it and then it will be used. Now the jr ra will jump to the address after your hook (To be specific it's two addresses down) and this will allow the game to use are subroutine and continue on with other things, if we didn't return to are hook in, let's say a shooting function, we might just shoot and not be able to move until we stopped shooting. Kinda hard to explain but I hope you get the idea. All a hook really is is something to tell the game to use your subroutine.
Well that is it for this tutorial, if you need any help please PM me or reply to this thread.
[Today 08:09 PM] _L96AW_RUSTY_: pwned!
[Today 08:08 PM] whatwentwrong: yes sir.
[Today 08:04 PM] HDC: How about you shut the fuck up
*HDC has just PWNED the Shitbox*
Bookmarks