____ ______ ______ THE ______ ______ ____
/ \ | ___| | | _____ | ___| |_ _| / \
| |__| | |__ | |__| | \ | |__ | | | |__|
\ \ | __| | | | | | | __| | | \ \
_\ \ | | | |__ | / | | | | _\ \
| | | | |___ | | | | | \ | |___ | | | | |
\____/ |______| |______| |___|__\ |______| |__| \____/
Of Professional Gameshark(tm) Hacking
_____ 0001110101001110010110100011
..~` a`~~.. 110100000100001000100000101000001
..~` }100000111000110001110001100011111110
-----` /\/\/\/10100011100110000111001100001110011000
`. \\\ | 00010001001111110010011111100100111111100
; \/\/\100100111001100001110011000011101100010
.` ___/01000111000110001110001100011100110010
; ..~~~~```` 11011000100100100101010100100110101001
.` ..``
; ..``
; .`
.-` .`
.-` ,` "The most elaborate, in-depth hacking guide
/ .. . for Game Cheat Devices, ANYWHERE!"
|.-`` `. \
`.|
[Originally By: Kong K Rool* and Macrox]
with additions by [Tolos, DGenerateKane,
HyperHacker, Viper187, and Kenobi]
-----------------------------------------------
Table Of Contents
-----------------------------------------------
Section 1 : Foreword
I This Version
II What's New
III Coming Soon
IV Dedication
V Preface
VI Acknowledgments
Section 2 : Hacking
VII Introduction
VIII Hacking Basics - Theory
IX. How-to Guide - Getting Started
| Constantly writes the value specified by YY to address XXXXXX. This and its 16-Bit counterpart below are the most used code types on N64. You'll probably be making most of your new codes with them. | GS/XP64 | ||
| Constantly writes the 16-Bit value specified by YYYY to address XXXXXX. | GS/XP64 | ||
| Constantly writes the value specified by YY to the uncached address XXXXXX. | GS/XP64 | ||
| Constantly writes the 16-Bit value specified by YYYY to the uncached address XXXXXX. | GS/XP64 | ||
| Writes the value YY to address XXXXXX ONLY when the GS Button is pressed. | GS/XP64 | ||
| 16bit version of the above. Writes the value YYYY to address XXXXXX ONLY when the GS Button is pressed. | GS/XP64 | ||
| Execute the following code (ZZZZZZZZ ZZZZ) ONLY when the value stored in address XXXXXX is equal to YY. | GS/XP64 | ||
ZZZZZZZZ ZZZZ | |||
| Same as above, only it reads a 16bit value. GS Pro 3.0+ ONLY! | GS/XP64 | ||
ZZZZZZZZ ZZZZ | |||
| Execute the following code (ZZZZZZZZ ZZZZ) ONLY when the value stored in address XXXXXX is NOT equal to YY. | GS 3.0+ | ||
ZZZZZZZZ ZZZZ | |||
| Same as above, only it reads a 16bit value. | GS 3.0+ | ||
ZZZZZZZZ ZZZZ | |||
| Keeps the game from using the expansion pack if it is present. Also used on some older non-expansion pack games to increase compatibility with the code generator. | GS Pro 3.2+ | ||
| Disabled the expansion pack (if present) using a secondary method. | GS Pro 3.2+ | ||
| Disabled the expansion pack (if present) using a 3rd method. | GS Pro 3.2+ | ||
| Tells the GameShark where the value "3C0880" is in the RAM. This type of code does not write a value to the given address. It sets the entry point which the GS will use to start the game. Games which require that code have a specific protection chip which will set the entry point upon booting the N64. | GS 1.08+ | ||
| Tells the GameShark what address is causing malfunction with it, and writes the supplied value to that address. Writes the value YY to the address XXXXXX once on boot. F0\F1 codes write to RAM before starting the game. This way, the codes take effect before the code handler is executed. | GS Pro 3.0+ / XP64 | ||
| 16-Bit version of the above. | GS Pro 3.0+ / XP64 | ||
| Sets the location in RAM where active codes are stored. Usually only used on games that utilize the expansion pack. | GS Pro 3.3+ | ||
| The same as an F1 enabler on GS Pro. | XP64 | ||
| The exact use of this code type is unknown as of now. | XP64 | ||
| Patch codes, aka Serial Repeaters, are used to make a code string shorter. EG, You have five codes put together to give you "all weapons." Use the patch to shorten it to two codes. XX is the number of addresses to write; YY is the amount (offset) to add to each address; ZZ is the amount to add to each value. | GS Pro 3.3+ | ||
TTTTTTTT VVVV | |||
GameShark | |||
| Constantly writes the value specified by YY to address XXXXXX. This and its 16-bit counterpart below are the most used code types on PSX. You'll probably be making most of your new codes with them. | GS x.x | ||
| Constantly writes the value specified by YY to address XXXXXX. This and its 16-bit counterpart below are the most used code types on PSX. You'll probably be making most of your new codes with them. | GS x.x | ||
| When the value for the given address is equal to the supplied value, activate the following code. | GS 2.2+ | ||
| When the value for the given address is different to the supplied value, activate the following code. | GS 2.2+ | ||
| When the value for the given address is less than the supplied value, activate the following code. | GS 2.2+ | ||
| When the value for the given address is greater than the supplied value, activate the following code. | GS 2.2+ | ||
| When the value for the given address is equal to the supplied value, activate the following code. | GS x.x | ||
| When the value for the given address is different to the supplied value, activate the following code. | GS 2.2+ | ||
| When the value for the given address is less than the supplied value, activate the following code. | GS 2.2+ | ||
| When the value for the given address is greater than the supplied value, activate the following code. | GS 2.2+ | ||
| Same as D0 except not RAM dependent. More easily used as a button activator. | GS 2.41+ | ||
| When buttons pressed equal YYYY then activate all codes. | GS 2.41+ | ||
| When buttons pressed equal YYYY then de-activate all codes. | GS 2.41+ | ||
| Add value(16-bit) code. Use with D/E activators. Example - (adds value "1007" to address "001221" when address "110012" equals value "5") D0110012 0005 10001221 1007 | GS 2.2+ | ||
| Subtract value(16-bit) code. Use only with D/E activators. Example - (subtracts value "102" from address "001221" when address "110012" equals value "6") D0110012 0006 11001221 0102 | GS 2.2+ | ||
| Add value(8-bit) code. Use with D/E activators. Example - (adds value "7" to address "001221" when address "110012" equals value "5") D0110012 0005 20001221 0007 | GS 2.2+ | ||
| Subtract value(8-bit) code. Use only with D/E activators. Example - (subtracts value "2" from address "001221" when address "110012" equals value "6") D0110012 0006 21001221 0002 | GS 2.2+ | ||
| Patch codes, aka Serial Repeaters, are used to make a code string shorter. EG, You have five codes put together to give you "all weapons." Use the patch to shorten it to two codes. XX is the number of addresses to write; YY is the amount (offset) to add to each address; ZZ is the amount to add to each value. | GS 2.41+ | ||
TTTTTTTT VVVV | |||
| Works like the D0/E0 code type, but affects ALL codes. Use as an (M) Must Be On if the game won't load with codes turned on. | GS 2.2+ | ||
| Works like the D0/E0 code type, but affects ALL codes. This is like a timer. A value of around 4000 or 5000 will usually give you a good 20-30 second delay before codes are activated. Use as an (M) Must Be On if the game won't load with codes turned on. | GS 2.41+ | ||
| Copy's YYYY bytes from location XXXXXX to location ZZZZZZ. Example use would be: C2040450 0008 80040680 0000 That would copy 8 bytes from 40450 to 40680. | GS 2.41+ | ||
80ZZZZZZ 0000 |
|||
Xplorer/Xploder -- see explorer FAQ for more info | |||
| Writes value YY to address XXXXXX. | Xplorer | ||
| Writes value YYYY to address XXXXXX. | Xplorer | ||
| Delays CPU by X per cycle. Best used with activator. | Xplorer | ||
| Writes any number of bytes ZZ to address XXXXXX. YYYY is the number of bytes to write. | Xplorer | ||
ZZZZ ZZZZ ZZZZ ZZZZ ZZ.. .... | |||
| CPU breaks at address AAAAAAAA; YYYY is number of bytes used (XX's); FFFFFFFF is the break point mask; CCCC is the type of break point, which can be E180 (instruction gotton by CPU but not yet implemented), EE80 (data to be read or written), E680 (data to be read), EA80 (data to be wrtten) or EF80 (instruction). | Xplorer | ||
AAAA AAAA CCCC FFFF FFFF XXXX XXXX XXXX XXXX | |||
| If address XXXXXX is equal to value YYYY execute following code. | Xplorer | ||
| If address XXXXXX is not equal to value YYYY execute following code. | Xplorer | ||
| nn is the number of repetitions (plus one); AAAA is the size of the address step; BBBB is the increase in the data value per step; XXXXXX is the initial address; YYYY is the inital value. | Xplorer | ||
10XX XXXX YYYY | |||
| Same as 7-code, but only functions from 0010 0000 to 01FF FFFF. | Xplorer | ||
| Same as 7-code. but only functions from 0000 0000 to 000F FFFF. | Xplorer | ||
| Automatically activates other selected codes if address XXXXXX is equal to YYYY. | Xplorer | ||
| 32-bit constant write to XXXXXX address (0000YYYY) | Xplorer | ||
| Note that all the code types below are in RAW form. RAW codes must be encrypted to work on the Gameshark� for Playstation 2. | ||
This command will constantly write the value specified by dd to the address specified by aaaaaaa. | ||
This command will constantly write the value specified by dddd to the address specified by aaaaaaa. | ||
This command will constantly write the value specified by dddddddd to the address specified by aaaaaaa. | ||
| Increment/Decrement Commands | ||
This command adds the value specified by nn to the value stored at the address aaaaaaaa. | ||
This command subtracts the value specified by nn to the value stored at the address aaaaaaaa. | ||
This command adds the value specified by nnnn to the value stored at the address aaaaaaaa. | ||
This command subtracts the value specified by nnnn to the value stored at the address aaaaaaaa. | ||
This command adds the value specified by nnnnnnnn to the value stored at the address aaaaaaaa. | ||
nnnnnnnn 00000000 | ||
This command subtracts the value specified by nnnnnnnn to the value stored at the address aaaaaaaa. | ||
nnnnnnnn 00000000 | ||
| Test Commands | ||
Only when the value at the address specified by aaaaaaa is equal to the value specified by dddd will the next line of code be executed. | ||
Only when the value at the address specified by aaaaaaa is not equal to the value specified by dddd will the next line of code be executed. | ||
Only when the value at the address specified by aaaaaaa is less than the value specified by dddd will the next line of code be executed. | ||
Only when the value at the address specified by aaaaaaa is greater than the value specified by dddd will the next line of code be executed. | ||
Only when the value at the address specified by aaaaaaa is equal to the value specified by dddd will the next nnn lines of code be executed. Otherwise, they will be skipped. | ||
Only when the value at the address specified by aaaaaaa is not equal to the value specified by dddd will the next nnn lines of code be executed. Otherwise, they will be skipped. | ||
Only when the value at the address specified by aaaaaaa is less than the value specified by dddd will the next nnn lines of code be executed. Otherwise, they will be skipped. | ||
Only when the value at the address specified by aaaaaaa is greater than the value specified by dddd will the next nnn lines of code be executed. Otherwise, they will be skipped. | ||
| Miscellaneous Commands | ||
a = Address to copy from b = Address to copy to n = Number of bytes to copy | ||
bbbbbbbb 00000000 | ||
Starting with the address specified by aaaaaaa, this code will write to xxxx addresses. The next address is determined by incrementing the current address by (yyyy * 4). The value specified by dddddddd is written to each calculated address. Also known as a "Patch Code." | ||
dddddddd 00000000 | ||
| Untested Commands | ||
| 3000nnnn dddddddd aaaaaaaax(n-1) | 32-bit Multiple Address Write? | |
| 8aaaaaaa bbbbbbbb cccccccc 00000000 | Master Command | |
| Aaaaaaaa dddddddd | 32-bit Write Once? | |
| B0000000 nnnnnnnn | Timer Command | |
| Caaaaaaa dddddddd | 32-bit Equal? | |
| Faaaaaaa bbbbbbbb | Master Command | |
| DEADFACE xxxxxxxx | "DEADFACE" Master Command - changes encryption seeds | |
| The following are what decrypted or raw code types look like. Xploder and Codebreaker use this format. Gameshark uses an encrypted format for the first line of the code (the address) while all use the second line as is (offset or quantifier). Dreamcast has 32 bit codes. These codes will require 8 digits for the offset and 8 digits for the quantifier, 2^32= FFFFFFFF in hex. Example, XXYYYYYY ZZZZZZZZ. Note: It is not unusual for manufacturers of cheating devices to encrypt their codes. Fire International (Blaze USA) has encrypted codes in both its N64 and Game Boy Xploder/Xplorer, while Interact has employed encryption in its DC Shark, GameBoy Advance Shark, and Playstation 2 Shark. If the code begins with a '0', then it is in decrypted format. As in any encryption there always is a crack to defeat it. Codebreaker and Xploder both have the built in ability to accept DC gameshark codes in decipher them. It is left to the reader to explore the decryption further. | ||
Code Value | Description | |
00xxxxxx 000000vv | Write 8bit (byte) value "vv" to memory address 8cxxxxxx. That is, 8 bit constant write. | |
01xxxxxx 0000vvvv | Write 16bit (2byte) value "vvvv" to memory address 8cxxxxxx. That is, 16 bit constant write. | |
02xxxxxx vvvvvvvv | Write 32bit (4byte) value "vvvvvvvv" to memory address 8cxxxxxx. That is, 32 bit constant write. | |
0300nnnn aaaaaaaa | Group write code. nn specifies how many 32 bit values follow. aaaaaaaa is the addrsss to write to. The values following this code are written to address aaaaaaaa. E.g: 03000004 8c012000 11111111 22222222 33333333 44444444 The effect is as follows: With a count of 00000004 codes, to address 8c012000: 8c012000 = 11111111 8c012004 = 22222222 8c012008 = 33333333 8c01200c = 44444444 | |
030100vv aaaaaaaa | Increment code. Add the 8bit value vv to the value at address aaaaaaaa | |
030200vv aaaaaaaa | Decrement code. Subtract the 8bit value vv from the value at address aaaaaaaa | |
0303vvvv aaaaaaaa | Increment code. Add the 16bit value vvvv to the value at address aaaaaaaa | |
0304vvvv aaaaaaaa | Decrement code. Subtract the 16bit value vvvv from the value at address aaaaaaaa | |
03050000 aaaaaaaa vvvvvvvv | Increment code. Add the 32bit value vvvvvvvv to the value at address aaaaaaaa Note that this code is 3 lines long and so will require an 0exxxxxx condition (not a 0dxxxxxx) if you're using it with a condition code. | |
03060000 aaaaaaaa vvvvvvvv | Decrement code. Subtract the 32bit value vvvvvvvv from the value at address aaaaaaaa Note that this code is 3 lines long and so will require an 0exxxxxx condition (not a 0dxxxxxx) if you're using it with a condition code. | |
04xxxxxx rrrrssss vvvvvvvv | Repeat/Filler code. Writes to address 8Cxxxxxx. Writes the 32bit value vvvvvvvv. Repeats this rrrr time, each time increasing the address by ssss (actually ssss x 4). That is, 32-Bit Constant Serial Write E.g: 04007a30 00030001 12345678 Effect: 8c007a30 = 12345678 8c007a34 = 12345678 8c007a38 = 12345678 | |
05xxxxxx dddddddd nnnnnnnn | Copy bytes code. Copy nnnnnnnn bytes from the address 8cxxxxxx to the address dddddddd. That is, constant copy bytes | |
071000XX | Change Decryption Type | |
0b0xxxxx |
Delay putting on codes for xxxxx cycles. Default 1000 (0x3e7) | |
0cxxxxxx vvvvvvvv | If the value at address 8Cxxxxxx is equal to vvvvvvvv, execute ALL codes; otherwise no codes are executed. Useful for waiting until game has loaded. | |
0dxxxxxx 0000vvvv |
If the value at address 8Cxxxxxx is equal to vvvv, execute the following code. Can be used with code types 00, 01 and 02 only. To use this type of control with other codes use an 0e code. | |
0dxxxxxx 0001vvvv |
If the value at address 8Cxxxxxx is different to vvvv, execute the following code. Can be used with code types 00, 01 and 02 only. To use this type of control with other codes use an 0e code. | |
0dxxxxxx 0002vvvv | If the value at address 8Cxxxxxx is less than vvvv (unsigned), execute the following code. Can be used with code types 00, 01 and 02 only. To use this type of control with other codes use an 0e code. | |
0dxxxxxx 0003vvvv |
If the value at address 8Cxxxxxx is greater than vvvv (unsigned), execute the following code. Can be used with code types 00, 01 and 02 only. To use this type of control with other codes use an 0e code. | |
0ennvvvv 00aaaaaa |
If the value at address 8caaaaaa is equal to vvvv, execute the following nnnn lines of codes. E.g: 0e04abcd 00012000 02300040 ffffffff 02300050 eeeeeeee if address 8c012000==abcd, execute the 04 lines of codes following. The 4 lines of codes being two "02xxxxxx" codes "02300040=ffffffff" and "02300050=eeeeeeee". | |
0ennvvvv 01aaaaaa |
If the value at address 8caaaaaa is different to vvvv, execute the following nnnn lines of codes. | |
0ennvvvv 02aaaaaa |
If the value at address 8caaaaaa is less than vvvv (unsigned), execute the following nnnn lines of codes. | |
0ennvvvv 03aaaaaa |
If the value at address 8caaaaaa is greater than vvvv (unsigned), execute the following nnnn lines of codes. | |
0F-XXXXXX 0000YYYY | 16-Bit Write Once Immediately. (Activator code) | |
| Just what it implies. Continuously writes YYYY value to XXXXXXX address. | ||
| Continuous write of YY value to address XXXXXXX. | ||
| Writes YYYY value to XXXXXXX address once on boot up. Same as F0/F1 on N64 | ||
|
Activates the code on the line directly beneath it ONLY when XXXXXXX address is YYYY value. | ||
| Enable Code | ||
| The most common GS code prefix for Gameboy is "01". This means the code resides in the first bank of the address line. Codebreaker users will find that 00 and 01 are equally used code types. The "00" simply means the code resides in the zero bank and "01" as above, the first bank. There are no known other code types for gameboy as there are for N64, Playstation and Dreamcast. Z is the data bank; XXXX is the address; YY is the value. | ||
- by Parasyte (Additions by DGenerateKane) | ||
| Note that all the code types below are in RAW form. RAW codes must be encrypted to work on the Gameshark for Gameboy Advance. | ||
| Continuously writes the value xx to the RAM address aaaaaaa. | ||
| Continuously writes the 16-Bit value xxxx to the RAM address aaaaaaa. Address must be aligned to 2 (must end with one of the following digits - 0,2,4,6,8,A,C,E). | ||
| Continuously writes the 32-Bit value xxxxxxxx to the RAM address aaaaaaa. Address must be aligned to 4 (must end with one of the following digits - 0,4,8,C). | ||
| Writes data to the following "count" (cccc) addresses. (xxxxxxxx value is also concidered an address, not really a problem, just a very stupid bug -- thanks Datel!!) Many addresses can follow. Example: 30000004 01010101 03001FF0 03001FF4 03001FF8 00000000 (write 01010101 to 3 addresses - 01010101, 03001FF0, 03001FF4, and 03001FF8. '00000000' is used for padding, to ensure the last code encrypts correctly) | ||
| This type allows GSA to intercept ROM reads and returns the value xxxx. The address is shifted to the right by 1 (divided by 2). You can either manually shift the address left by 1, or multiply by 2 to get the real address. GSAcrypt (Win32 version) has an option to automatically shift the address for you. Note: V1\V2 hardware can only have up to 1 user-defined rom patch max. V3 can have up to 4. some enable code types can shorten the amount of user-defined rom patches available. | ||
| Similar to first ROM patch code, except patch is enabled before the game starts, instead of waiting for the code handler to enable the patch. (address >> 1) | ||
| 16-bit ROM Patch ? (address >> 1) | ||
| 8-Bit RAM write only when the GS Button is pressed. | ||
| 16-Bit RAM write only when the GS Button is pressed. | ||
| Slow down on GS Button. This type will put the GBA into a loop for "xxxx" number of times, each time the code handler is run. This slows the game down. | ||
| Activate the code on the next line ONLY when the value of address 'aaaaaaa' is Equal To xxxx. | ||
| 16-Bit activate the multi lines if-true. If the value at address is equal to xxxx, execute following 'zz' lines. | ||
| Used to insert the GS code handler routine where it will be executed at least 20 times per second. Without this code, GSA can not write to RAM. xxxx: 0001 - Executes code handler without backing up the $lr register. Must turn GSA off before loading game. 0002 - Executes code handler and backs up the $lr register. Must turn GSA off before loading game. 0003 - Replaces a 32-bit pointer used for long-branches. Must turn GSA off before loading game. 0101 - Executes code handler without backing up the $lr register. 0102 - Executes code handler and backs up the $lr register. 0103 - Replaces a 32-bit pointer used for long-branches. | ||
| Used by GSA only for auto-detecting the inserted game. | ||
| "Deadface" is used to change the encryption seeds. It's original intent was probably to re- encrypt codes if someone figured out the normal encryption. (Very similiar to the CBA's '9' code type.) | ||
- by Parasyte (Additions by DGenerateKane) | ||
| Note that all the code types below are in RAW form. RAW codes must be encrypted to work on the Codebreaker for Gameboy Advance. | ||
| xxxx is the CRC value (the "Game ID" converted to hex) Flags ("yyyy"): 0008 - CRC Exists (CRC is used to autodetect the inserted game) 0002 - Disable Interupts | ||
| 'y' is the CBA Code Handler Store Address (0-7) [address = ((d << 0x16) + 0x08000100)] 1000 - 32-bit Long-Branch Type (Thumb) 2000 - 32-bit Long-Branch Type (ARM) 3000 - 8-bit(?) Long-Branch Type (Thumb) 4000 - 8-bit(?) Long-Branch Type (ARM) 0020 - Unknown (Odd Effect) | ||
| Continuosly writes the 8-Bit value specified by 'yy' to address aaaaaaa. | ||
| This is one of those two-line codes. The "yyyy" set is the data to store at the address (aaaaaaa), with xxxxxxxx being the number of addresses to store to, and iiii being the value to increment the addresses by. The codetype is usually use to fill memory with a certain value. | ||
xxxxxxxx iiii | ||
| Performs the AND function on the address provided with the value provided. I'm not going to explain what AND does, so if you'd like to know I suggest you see the instruction manual for a graphing calculator. This is another advanced code type you'll probably never need to use. | ||
| If the value at the specified RAM address (aaaaaaa) is equal to yyyy value, active the code on the next line. | ||
| Continuosly writes yyyy values to the specified RAM address (aaaaaaa). | ||
(When 1st Code Only!) | Works like the DEADFACE on GSA. Changes the encryption seeds used for the rest of the codes. | |
| Basicly the opposite of an 'If Equal To' Activator. Activates the code on the next line if address xxxxxxx is NOT equal to yyyy | ||
| No Description available at this time. | ||
| AR V3 Codes Types | |
| About the Code Types Numbers | |
Let's take for exemple : Type E3 3.0.3.1.x : 00XXXXXX : (00000130 -> C7000130) ZZZZZZZZ : Write the Word ZZZZZZZZ to the address $4XXXXXX 3.0.3.1.x : 1st number = 3 = Data size (0 to 3) 2nd number = 0 = Code Type (0 to 7) 3rd number = 3 = Cude subtype (0 to 3) 4th number = 1 = Special bit (0 to 1) 5th number : x = Unused bit (0 to 3) 3.0.3.1.0 gives these (bit speaking) = 11.000.11.1.00 reverse it : 00.1.11.000.11 = 0011100011 = E3 = The code type. I choose to take this numbering to make it that the Ram 8bits write (Type 0), Ram 16bits write Type 1 andRam 32bits write (Type 2) have the same type number than for AR/GS V1/2. Moreover, If I didn't "reverse" the numbers, we've gotten almost only even code type number, which, IMHO, sounds really strange... | |
| 1) Normal RAM Write Codes | |
|
Type 00 0.0.0.x.x |
(02024EA4 -> 00224EA4) Fill area (XXXXXXXX) to (XXXXXXXX+YYYYYY) with Byte ZZ. |
|
XXXXXXXX YYYYYYZZ | |
|
Type 01 1.0.0.x.x |
(02024EA4 -> 02224EA4) Fill area (XXXXXXXX) to (XXXXXXXX+YYYY*2) with Halfword ZZZZ. |
|
XXXXXXXX YYYYZZZZ | |
|
Type 02 2.0.0.x.x |
(02024EA4 -> 04224EA4) Write the Word ZZZZZZZZ to address XXXXXXXX. |
|
XXXXXXXX ZZZZZZZZ | |
| 2) Pointer RAM Write Codes | |
|
Type 20 0.0.1.x.x |
(02024EA4 -> 40224EA4) Writes Byte ZZ to ([the address kept in XXXXXXXX]+[YYYYYY]). |
|
XXXXXXXX YYYYYYZZ | |
|
Type 21 1.0.1.x.x |
(02024EA4 -> 4224EA4) Writes Halfword ZZZZ ([the address kept in XXXXXXXX]+[YYYY*2]). |
|
XXXXXXXX YYYYZZZZ | |
|
Type 22 2.0.1.x.x |
(02024EA4 -> 4424EA4) Writes the Word ZZZZZZZZ to [the address kept in XXXXXXXX]. |
|
XXXXXXXX ZZZZZZZZ | |
| 3) Add Codes | |
|
Type 40 0.0.2.x.x |
(02024EA4 -> 80224EA4) Add the Byte ZZ to the Byte stored in XXXXXXXX. |
|
XXXXXXXX 000000ZZ | |
|
Type 41 1.0.2.x.x |
(02024EA4 -> 82224EA4) Add the Halfword ZZZZ to the Halfword stored in XXXXXXXX. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 42 2.0.2.x.x |
(02024EA4 -> 84224EA4) Add the Word ZZZZ to the Halfword stored in XXXXXXXX. |
|
XXXXXXXX ZZZZZZZZ | |
| 4) Write to $4000000 (IO Registers!) | |
|
Type 63 3.0.3.0.x |
(00000130 -> C6000130) Write the Halfword ZZZZ to the address $4XXXXXX |
|
00XXXXXX 0000ZZZZ | |
|
Type E3 3.0.3.1.x |
(00000130 -> C7000130) Write the Word ZZZZZZZZ to the address $4XXXXXX |
|
00XXXXXX ZZZZZZZZ | |
| 5) If Equal Code (= Joker Code) | |
|
Type 04 0.1.0.x.x |
(02024EA4 -> 08224EA4) If Byte at XXXXXXXX = ZZ then execute next code. |
|
XXXXXXXX 000000ZZ | |
|
Type 24 0.1.1.x.x |
(02024EA4 -> 48224EA4) If Byte at XXXXXXXX = ZZ then execute next 2 codes. |
|
XXXXXXXX 000000ZZ | |
|
Type 44 0.1.2.x.x |
(02024EA4 -> 88224EA4) If Byte at XXXXXXXX = ZZ execute all the codes below this one in the same row (else execute none of the codes below). |
|
XXXXXXXX 000000ZZ | |
|
Type 64 0.1.3.x.x |
(02024EA4 -> C8224EA4) While Byte at XXXXXXXX <> ZZ turn off all codes. |
|
XXXXXXXX 000000ZZ | |
|
Type 05 1.1.0.x.x |
(02024EA4 -> 0A224EA4) If Halfword at XXXXXXXX = ZZZZ then execute next code. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 05 1.1.0.x.x |
(02024EA4 -> 0A224EA4) If Halfword at XXXXXXXX = ZZZZ then execute next code. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 25 1.1.1.x.x |
(02024EA4 -> 4A224EA4) If Halfword at XXXXXXXX = ZZZZ then execute next 2 codes. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 45 1.1.2.x.x |
(02024EA4 -> 8A224EA4) If Halfword at XXXXXXXX = ZZZZ execute all the codes below this one in the same row (else execute none of the codes below). |
|
XXXXXXXX 0000ZZZZ | |
|
Type 65 1.1.3.x.x |
(02024EA4 -> CA224EA4) While Halfword at XXXXXXXX <> ZZZZ turn off all codes. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 06 2.1.0.x.x |
(02024EA4 -> 0C224EA4) If Word at XXXXXXXX = ZZZZZZZZ then execute next code. |
|
XXXXXXXX ZZZZZZZZ | |
|
Type 26 2.1.1.x.x |
(02024EA4 -> 4C224EA4) If Word at XXXXXXXX = ZZZZZZZZ then execute next 2 codes. |
|
XXXXXXXX ZZZZZZZZ | |
|
Type 46 2.1.2.x.x |
(02024EA4 -> 8C224EA4) If Word at XXXXXXXX = ZZZZZZZZ execute all the codes below this one in the same row (else execute none of the codes below). |
|
XXXXXXXX ZZZZZZZZ | |
|
Type 66 2.1.3.x.x |
(02024EA4 -> CC224EA4) While Word at XXXXXXXX <> ZZZZZZZZ turn off all codes. |
|
XXXXXXXX ZZZZZZZZ | |
| 6) If Different Code | |
|
Type 08 0.2.0.x.x |
(02024EA4 -> 10224EA4) If Byte at XXXXXXXX <> ZZ then execute next code. |
|
XXXXXXXX 000000ZZ | |
|
Type 28 0.2.1.x.x |
(02024EA4 -> 50224EA4) If Byte at XXXXXXXX <> ZZ then execute next 2 codes. |
|
XXXXXXXX 000000ZZ | |
|
Type 48 0.2.2.x.x |
(02024EA4 -> 90224EA4) If Byte at XXXXXXXX <> ZZ execute all the codes below this one in the same row (else execute none of the codes below). |
|
XXXXXXXX 000000ZZ | |
|
Type 68 0.2.3.x.x |
(02024EA4 -> D0224EA4) While Byte at XXXXXXXX = ZZ turn off all codes. |
|
XXXXXXXX 000000ZZ | |
|
Type 09 1.2.0.x.x |
(02024EA4 -> 12224EA4) If Halfword at XXXXXXXX <> ZZZZ then execute next code. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 29 1.2.1.x.x |
(02024EA4 -> 52224EA4) If Halfword at XXXXXXXX <> ZZZZ then execute next 2 codes. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 49 1.2.2.x.x |
(02024EA4 -> 92224EA4) If Halfword at XXXXXXXX <> ZZZZ disable all the codes below this one. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 69 1.2.3.x.x |
(02024EA4 -> D2224EA4) While Halfword at XXXXXXXX = ZZZZ turn off all codes. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 0A 2.2.0.x.x |
(02024EA4 -> 14224EA4) If Word at XXXXXXXX <> ZZZZZZZZ then execute next code. |
|
XXXXXXXX ZZZZZZZZ | |
|
Type 2A 2.2.1.x.x |
(02024EA4 -> 54224EA4) If Word at XXXXXXXX <> ZZZZZZZZ then execute next 2 codes. |
|
XXXXXXXX ZZZZZZZZ | |
|
Type 4A 2.2.2.x.x |
(02024EA4 -> 94224EA4) If Word at XXXXXXXX <> ZZZZZZZZ disable all the codes below this one. |
|
XXXXXXXX ZZZZZZZZ | |
|
Type 6A 2.2.3.x.x |
(02024EA4 -> D4224EA4) While Word at XXXXXXXX = ZZZZZZZZ turn off all codes. |
|
XXXXXXXX ZZZZZZZZ | |
| 7) [If Byte at address XXXXXXXX is lower than ZZ] (signed) Code | |
| Signed means : For bytes : values go from -128 to +127. For Halfword : values go from -32768/+32767. For Words : values go from -2147483648 to 2147483647. For exemple, for the Byte comparison, 7F (127) will be > to FF (-1). | |
|
Type 0C 0.3.0.x.x |
(02024EA4 -> 18224EA4 or 28224EA4) If ZZ > Byte at XXXXXXXX then execute next code. |
|
XXXXXXXX 000000ZZ | |
|
Type 2C 0.3.1.x.x |
(02024EA4 -> 58224EA4 or 68224EA4) If ZZ > Byte at XXXXXXXX then execute next 2 codes. |
|
XXXXXXXX 000000ZZ | |
|
Type 4C 0.3.2.x.x |
(02024EA4 -> 98224EA4 or A8224EA4) If ZZ > Byte at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
|
XXXXXXXX 000000ZZ | |
|
Type 6C 0.3.3.x.x |
(02024EA4 -> D8224EA4 or E8224EA4) While ZZ <= Byte at XXXXXXXX turn off all codes. |
|
XXXXXXXX 000000ZZ | |
|
Type 0D 1.3.0.x.x |
(02024EA4 -> 1A224EA4 or 2A224EA4) If ZZZZ > Halfword at XXXXXXXX then execute next line. |
| XXXXXXXX 0000ZZZZ | |
|
Type 2D 1.3.1.x.x |
(02024EA4 -> 5A224EA4) If ZZZZ > Halfword at XXXXXXXX then execute next 2 lines. |
| XXXXXXXX 0000ZZZZ | |
|
Type 4D 1.3.2.x.x |
(02024EA4 -> 9A224EA4) If ZZZZ > Halfword at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
| XXXXXXXX 0000ZZZZ | |
|
Type 6D 1.3.3.x.x |
(02024EA4 -> DA224EA4) While ZZZZ <= Halfword at XXXXXXXX turn off all codes. |
| XXXXXXXX 0000ZZZZ | |
|
Type 0E 2.3.0.x.x |
(02024EA4 -> 1C224EA4) If ZZZZZZZZ > Word at XXXXXXXX then execute next line. |
| XXXXXXXX ZZZZZZZZ | |
|
Type 2E 2.3.1.x.x |
(02024EA4 -> 5C224EA4) If ZZZZZZZZ > Word at XXXXXXXX then execute next 2 lines. |
| XXXXXXXX ZZZZZZZZ | |
|
Type 4E 2.3.2.x.x |
(02024EA4 -> 9C224EA4) If ZZZZZZZZ > HWord at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
| XXXXXXXX ZZZZZZZZ | |
|
Type 6E 2.3.3.x.x |
(02024EA4 -> DC224EA4) While ZZZZZZZZ <= Word at XXXXXXXX turn off all codes. |
| XXXXXXXX ZZZZZZZZ | |
| 8) [If Byte at address XXXXXXXX is higher than ZZ] (signed) Code | |
| Signed means : For bytes : values go from -128 to +127. For Halfword : values go from -32768/+32767. For Words : values go from -2147483648 to 2147483647. For exemple, for the Byte comparison, 7F (127) will be > to FF (-1). | |
|
Type 10 0.4.0.x.x , 0.6.0.x.x |
(02024EA4 -> 20224EA4 or 30224EA4) If ZZ < Byte at XXXXXXXX then execute next code. |
|
XXXXXXXX 000000ZZ | |
|
Type 30 0.4.1.x.x |
(02024EA4 -> 60224EA4 or 70224EA4) If ZZ < Byte at XXXXXXXX then execute next 2 codes. |
|
XXXXXXXX 000000ZZ | |
|
Type 50 0.4.2.x.x , 0.6.2.x.x |
(02024EA4 -> A0224EA4 or B0224EA4) If ZZ < Byte at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
|
XXXXXXXX 000000ZZ | |
|
Type 70 0.4.3.x.x |
(02024EA4 -> E0224EA4 or F0224EA4) While ZZ => Byte at XXXXXXXX turn off all codes. |
|
XXXXXXXX 000000ZZ | |
|
Type 11 1.4.0.x.x, 1.6.0.x.x |
(02024EA4 -> 22224EA4 or 32224EA4) If ZZZZ < Halfword at XXXXXXXX then execute next line. |
| XXXXXXXX 0000ZZZZ | |
| Type 31 1.4.1.x.x |
(02024EA4 -> 62224EA4) If ZZZZ < Halfword at XXXXXXXX then execute next 2 lines. |
| XXXXXXXX 0000ZZZZ | |
| Type 51 1.4.2.x.x, 1.6.2.x.x |
(02024EA4 -> A2224EA4 or B2224EA4) If ZZZZ < Halfword at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
| XXXXXXXX 0000ZZZZ | |
| Type 71 1.4.3.x.x | (02024EA4 -> E2224EA4) While ZZZZ => Halfword at XXXXXXXX turn off all codes. |
| XXXXXXXX 0000ZZZZ | |
| Type 12 2.4.0.x.x, 2.6.0.x.x | (02024EA4 -> 24224EA4 or 34224EA4) If ZZZZ < Halfword at XXXXXXXX then execute next line. |
| XXXXXXXX 0000ZZZZ | |
| Type 32 2.4.1.x.x | (02024EA4 -> 64224EA4) If ZZZZ < Halfword at XXXXXXXX then execute next 2 lines. |
| XXXXXXXX 0000ZZZZ | |
| Type 52 2.4.2.x.x,2.6.2.x.x | (02024EA4 -> A4224EA4 or B4224EA4) If ZZZZ < Halfword at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
| XXXXXXXX 0000ZZZZ | |
| Type 72 2.4.3.x.x | (02024EA4 -> E4224EA4) While ZZZZ => Halfword at XXXXXXXX turn off all codes. |
| XXXXXXXX 0000ZZZZ | |
| 9) [If Value at adress XXXXXXXX is lower than...] (unsigned) Code | |
| Unsigned means : For bytes : values go from 0 to +255. For Halfword : values go from 0 to +65535. For Words : values go from 0 to 4294967295. For exemple, for the Byte comparison, 7F (127) will be < to FF (255). | |
| Type 14 0.5.0.x.x | (02024EA4 -> 28224EA4) If ZZZZZZZZ > Byte at XXXXXXXX then execute next line. |
| XXXXXXXX ZZZZZZZZ | |
| Type 34 0.5.1.x.x | (02024EA4 -> 68224EA4) If ZZZZZZZZ > Byte at XXXXXXXX then execute next 2 lines. |
| XXXXXXXX ZZZZZZZZ | |
| Type 54 0.5.2.x.x | (02024EA4 -> A8224EA4) If ZZZZZZZZ > Byte at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
| XXXXXXXX ZZZZZZZZ | |
| Type 74 0.5.3.x.x | (02024EA4 -> E8224EA4) While ZZ <= Byte at XXXXXXXX turn off all codes. |
| XXXXXXXX ZZZZZZZZ | |
| Type 15 1.5.0.x.x | (02024EA4 -> 2A224EA4) If ZZZZZZZZ > Halfword at XXXXXXXX then execute next line. |
| XXXXXXXX ZZZZZZZZ | |
| Type 35 1.5.1.x.x | (02024EA4 -> 6A224EA4) If ZZZZZZZZ > Halfword at XXXXXXXX then execute next 2 lines. |
| XXXXXXXX ZZZZZZZZ | |
| Type 55 1.5.2.x.x | (02024EA4 -> AA224EA4) If ZZZZZZZZ > Halfword at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
| XXXXXXXX ZZZZZZZZ | |
| Type 75 1.5.3.x.x | (02024EA4 -> EA224EA4) While ZZZZZZZZ <= Halfword at XXXXXXXX turn off all codes. |
| XXXXXXXX ZZZZZZZZ | |
| Type 16 2.5.0.x.x | (02024EA4 -> 2C224EA4) If ZZZZZZZZ > Word at XXXXXXXX then execute next line. |
| XXXXXXXX ZZZZZZZZ | |
| Type 36 2.5.1.x.x | (02024EA4 -> 6C224EA4) If ZZZZZZZZ > Word at XXXXXXXX then execute next 2 lines. |
| XXXXXXXX ZZZZZZZZ | |
| Type 56 2.5.2.x.x | (02024EA4 -> AC224EA4) If ZZZZZZZZ > Word at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
| XXXXXXXX ZZZZZZZZ | |
| Type 76 2.5.3.x.x | (02024EA4 -> EC224EA4) While ZZZZZZZZ <= Word at XXXXXXXX turn off all codes. |
| XXXXXXXX ZZZZZZZZ | |
| 10) [If Value at adress XXXXXXXX is higher than...] (unsigned) Code | |
| Unsigned means For bytes : values go from 0 to +255. For Halfword : values go from 0 to +65535. For Words : values go from 0 to 4294967295. For exemple, for the Byte comparison, 7F (127) will be < to FF (255). | |
| Type 18 0.6.0.x.x | (02024EA4 -> 30224EA4) If ZZZZZZZZ < Byte at XXXXXXXX then execute next line.. |
| XXXXXXXX ZZZZZZZZ | |
| Type 38 0.6.1.x.x | (02024EA4 -> 70224EA4) If ZZZZZZZZ < Byte at XXXXXXXX then execute next 2 lines. |
| XXXXXXXX ZZZZZZZZ | |
| Type 58 0.6.2.x.x | (02024EA4 -> B0224EA4) If ZZZZZZZZ < Byte at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
| XXXXXXXX ZZZZZZZZ | |
| Type 78 0.6.3.x.x | (02024EA4 -> F0224EA4) While ZZZZZZZZ => Byte at XXXXXXXX turn off all codes. |
| XXXXXXXX ZZZZZZZZ | |
| Type 19 1.6.0.x.x | (02024EA4 -> 32224EA4) If ZZZZZZZZ < Halfword at XXXXXXXX then execute next line. |
| XXXXXXXX ZZZZZZZZ | |
| Type 39 1.6.1.x.x | (02024EA4 -> 72224EA4) If ZZZZZZZZ < Halfword at XXXXXXXX then execute next 2 lines. |
| XXXXXXXX ZZZZZZZZ | |
| Type 59 1.6.2.x.x | (02024EA4 -> B2224EA4) If ZZZZZZZZ < Halfword at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
| XXXXXXXX ZZZZZZZZ | |
| Type 79 1.6.3.x.x | (02024EA4 -> F2224EA4) While ZZZZZZZZ => Halfword at XXXXXXXX turn off all codes. |
| XXXXXXXX ZZZZZZZZ | |
| Type 1A 2.6.0.x.x | (02024EA4 -> 34224EA4) If ZZZZZZZZ < Halfword at XXXXXXXX then execute next line. |
| XXXXXXXX ZZZZZZZZ | |
| Type 3A 2.6.1.x.x | (02024EA4 -> 74224EA4) If ZZZZZZZZ < Halfword at XXXXXXXX then execute next 2 lines. |
| XXXXXXXX ZZZZZZZZ | |
| Type 5A 2.6.2.x.x | (02024EA4 -> B4224EA4) If ZZZZZZZZ < Halfword at XXXXXXXX then execute all following codes in the same row (else execute none of the codes below). |
| XXXXXXXX ZZZZZZZZ | |
| Type 7A 2.6.3.x.x | (02024EA4 -> F4224EA4) While ZZZZZZZZ => Halfword at XXXXXXXX turn off all codes. |
| XXXXXXXX ZZZZZZZZ | |
| 11) If AND Code | |
|
Type 1C 0.7.0.x.x |
(02024EA4 -> 38224EA4) If ZZ AND Byte at XXXXXXXX <> 0 (= True) then execute next code. |
|
XXXXXXXX 000000ZZ | |
|
Type 3C 0.7.1.x.x |
(02024EA4 -> 78224EA4) If ZZ AND Byte at XXXXXXXX <> 0 (= True) then execute next 2 codes. |
|
XXXXXXXX 000000ZZ | |
|
Type 5C 0.7.2.x.x |
(02024EA4 -> B8224EA4) If ZZ AND Byte at XXXXXXXX <> 0 (= True) then execute all following codes in the same row (else execute none of the codes below). |
|
XXXXXXXX 000000ZZ | |
|
Type 7C 0.7.3.x.x |
(02024EA4 -> F8224EA4) While ZZ AND Byte at XXXXXXXX = 0 (= False) then turn off all codes. |
|
XXXXXXXX 000000ZZ | |
|
Type 1D 1.7.0.x.x |
(02024EA4 -> 3A224EA4) If ZZZZ AND Halfword at XXXXXXXX <> 0 (= True) then execute next code. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 3D 1.7.1.x.x |
(02024EA4 -> 7A224EA4) If ZZZZ AND Halfword at XXXXXXXX <> 0 (= True) then execute next 2 codes. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 5D 1.7.2.x.x |
(02024EA4 -> BA224EA4) If ZZZZ AND Halfword at XXXXXXXX <> 0 (= True) then execute all following codes in the same row (else execute none of the codes below). |
|
XXXXXXXX 0000ZZZZ | |
|
Type 7D 1.7.3.x.x |
(02024EA4 -> FA224EA4) While ZZZZ AND Halfword at XXXXXXXX = 0 (= False) then turn off all codes. |
|
XXXXXXXX 0000ZZZZ | |
|
Type 1E 2.7.0.x.x |
(02024EA4 -> 3C224EA4) If ZZZZZZZZ AND Word at XXXXXXXX <> 0 (= True) then execute next code. |
|
XXXXXXXX ZZZZZZZZ | |
|
Type 3E 2.7.1.x.x |
(02024EA4 -> 7C224EA4) If ZZZZZZZZ AND Word at XXXXXXXX <> 0 (= True) then execute next 2 codes. |
|
XXXXXXXX ZZZZZZZZ | |
|
Type 5E 2.7.2.x.x |
(02024EA4 -> BC224EA4) If ZZZZZZZZ AND Word at XXXXXXXX <> 0 (= True) then execute all following codes in the same row (else execute none of the codes below). |
|
XXXXXXXX ZZZZZZZZ | |
|
Type 7E 2.7.3.x.x |
(02024EA4 -> FC224EA4) While ZZZZZZZZ AND Word at XXXXXXXX = 0 (= False) then turn off all codes. |
|
XXXXXXXX ZZZZZZZZ | |
| 12) "Always..." Codes | |
| For the "Always..." codes: -XXXXXXXX can be any authorised address BUT 00000000 (use 02000000 if you don't know what to choose). -ZZZZZZZZ can be anything. -The "y" in the code data must be in the [1-7] range (which means not 0). | |
| Type 07 3.y.0.x.x | (02024EA4 -> 0E224EA4) Always skip next line. |
| XXXXXXXX ZZZZZZZZ | |
| Type 27 3.y.1.x.x | (02024EA4 -> 4E24EA4) Always skip next 2 lines. |
| XXXXXXXX ZZZZZZZZ | |
| Type 47 3.y.2.x.x | (02024EA4 -> 8E224EA4) Always Stops executing all the codes below. |
| XXXXXXXX ZZZZZZZZ | |
| Type 67 3.y.3.x.x | (02024EA4 -> CE224EA4) Always turn off all codes. |
| XXXXXXXX ZZZZZZZZ | |
| 13) 1 Line Special Codes (= starting with "00000000") | |
|
Type z00 0.0.0.0.0 | End of the code list (even if you put values in the 2nd line). |
| 00000000 | |
|
Type z04 x.1.0.x.x | AR Slowdown : loops the AR XX times |
| 0800XX00 | |
| 14) 2 Lines Special Codes (= starting with '00000000' and padded (if needed) with "00000000") | |
| Note: You have to add the 0es manually, after clicking the "create" button. | |
|
Type z08 0.2.0.x.x |
(02024EA4 -> 10224EA4) Writes Byte ZZ to address XXXXXXXX when AR button is pushed. |
|
XXXXXXXX 000000ZZ | |
|
Type z09 1.2.0.x.x |
(02024EA4 -> 12224EA4) Writes Halfword ZZZZ to address XXXXXXXX. |
|
XXXXXXXX 0000ZZZZ | |
|
Type z0A 2.2.0.x.x |
(02024EA4 -> 14224EA4) Writes Word ZZZZZZZZ to address XXXXXXXX. |
|
XXXXXXXX ZZZZZZZZ | |
|
Type z0C 0.3.0.x.x |
(02024EA4 -> 18224EA4) Patches ROM address (XXXXXXXX << 1) with Halfword ZZZZ. |
|
XXXXXXXX 0000ZZZZ | |
|
Type z0D 1.3.0.x.x |
(02024EA4 -> 1A224EA4) Patches ROM address (XXXXXXXX << 1) with Halfword ZZZZ. Does not work on V1/2 upgraded to V3. Only for a real V3 Hardware? |
|
XXXXXXXX 0000ZZZZ | |
|
Type z0E 2.3.0.x.x |
(02024EA4 -> 1C224EA4) Patches ROM address (XXXXXXXX << 1) with Halfword ZZZZ. Does not work on V1/2 upgraded to V3. Only for a real V3 Hardware? |
|
XXXXXXXX 0000ZZZZ | |
|
Type z0F 3.3.0.x.x |
(02024EA4 -> 1E224EA4) Patches ROM address (XXXXXXXX << 1) with Halfword ZZZZ. Does not work on V1/2 upgraded to V3. Only for a real V3 Hardware? |
|
XXXXXXXX 0000ZZZZ | |
|
Type z20 x.0.1.x.x |
(00000000 -> 40000000) (SP = 0) (means : stops the "then execute all following codes in the same row" and stops the "else execute none of the codes below)". |
|
00000000 00000000 | |
|
Type z30 x.4.1.x.x |
(00000000 -> 60000000) (If SP <> 2 -> SP = 1) (means : start to execute all codes until end of codes or SP = 0). (bypass the number of codes to executes set by the master code). |
|
00000000 00000000 | |
|
Type z40 0.0.2.x.x |
(02024EA4 -> 80224EA4) Writes Byte YY at address XXXXXXXX. Then makes YY = YY + Z1, XXXXXXXX = XXXXXXXX + Z3Z3, Z2 = Z2 - 1, and repeats until Z2 < 0. |
|
XXXXXXXX 000000YY Z1Z2Z3Z3 | |
|
Type z41 1.0.2.x.x |
(02024EA4 -> 82224EA4) Writes Halfword YYYY at address XXXXXXXX. Then makes YYYY = YYYY + Z1, XXXXXXXX = XXXXXXXX + Z3Z3*2, |
|
XXXXXXXX 0000YYYY Z1Z2Z3Z3 | |
|
Type z42 2.0.2.x.x |
(02024EA4 -> 84224EA4) Writes Word YYYYYYYY at address XXXXXXXX. Then makes YYYYYYYY = YYYYYYYY + Z1, XXXXXXXX = XXXXXXXX + Z3Z3*4, Z2 = Z2 - 1, and repeats until Z2<0. |
|
XXXXXXXX YYYYYYYY Z1Z2Z3Z3 | |
| WARNING: There is a BUG on the REAL AR (v2 upgraded to v3, and maybe on real v3) with the 32Bits Increment Slide code. You HAVE to add a code (best choice is 80000000 00000000 : add 0 to value at address 0) right after it, else the AR will erase the 2 last 8 digits lines of the 32 Bits Inc. Slide code when you enter it !!! | |
| 15) Special Codes | |
|
-Master Code- Type 62 2.0.3.x.x |
(address to patch -> address to patch AND $1FFFFFE) Master Code settings. |
|
XXXXXXXX 0000YYYY | |
|
-ID Code- Type 62 2.0.3.x.x |
word at address 080000AC Must always be 001DC0DE |
|
XXXXXXXX 001DC0DE | |
| -DEADFACE- |
Must always be DEADFACE New Encryption seed. |
|
DEADFACE 0000XXXX | |
| Final Notes | |
SP = 0 : normal (execute n codes before giving back the hand to the game). SP = 1 : execute all codes until SP <>1 (or end of codes). SP = 2 : don't execute anymore codes. Each time the GSA starts to execute codes (= each time "it has the hand"), SP = 0. The 'execute all the codes below this one in the same row' makes SP = 1. The '(else execute none of the codes below)' makes SP = 2. The 'turn off all codes' makes an infinite loop (that can't be broken, unless the condition becomes True). | |
| Encryption | Decryption |
| A0A1A2A3 D0D1 | a0a1a2a3 d0d1 |
|
A0 = (a0 XOR $06) on PSX A0 = (a0 XOR $68) on N64 A1 = (a1 XOR $81) - $2B A2 = (a2 XOR $82) - $2B A3 = (a3 XOR $83) - $2B D0 = (d0 XOR $84) - $2B D1 = (d1 XOR $85) - $2B Alternate: A0 = (a0 XOR $06) on PSX A0 = (a0 XOR $68) on N64 A1 = (a1 XOR $01) - $AB A2 = (a2 XOR $02) - $AB A3 = (a3 XOR $03) - $AB D0 = (d0 XOR $04) - $AB D1 = (d1 XOR $05) - $AB |
a0 = (A0 XOR $06) on PSX a0 = (A0 XOR $68) on N64 a1 = (A1 + $2B) XOR $81 a2 = (A2 + $2B) XOR $82 a3 = (A3 + $2B) XOR $83 d0 = (D0 + $2B) XOR $84 d1 = (D1 + $2B) XOR $85 Alternate: a0 = (A0 XOR $06) on PSX a0 = (A0 XOR $68) on N64 a1 = (A1 + $AB) XOR $01 a2 = (A2 + $AB) XOR $02 a3 = (A3 + $AB) XOR $03 d0 = (D0 + $AB) XOR $04 d1 = (D1 + $AB) XOR $05 |
| Newer PSX 7K Encryption (PSX Only) | |
| A0A1A2A3 D0D1 | |
|
A0 = (a0 XOR $07) A1 = (a1 - (a2 AND $73)) + ((a3 XOR $90) - $F5) - d0 - d1 A2 = (a2 - (a3 AND $73)) + ((d0 XOR $90) - $16) - d1 A3 = (a3 - (d0 AND $73)) + ((d1 XOR $90) - $5A) D0 = (d0 - (d1 AND $73)) + $35 D1 = (d1 + $35) | |
| Newer PSX 7K Decryption (PSX Only) | |
| a0a1a2a3 d0d1 | |
|
d1 = (D1 - $35) d0 = (D0 + (D1 AND $73)) - $35 a3 = (A3 + (D0 AND $73)) - ((D1 XOR $90) - $5A) a2 = (A2 + (A3 AND $73)) - ((D0 XOR $90) - $16) + D1 a1 = (A1 + (A2 AND $73)) - ((A3 XOR $90) - $F5) + D0 + D1 a0 = (A0 XOR $07) | |
Now the part we need to look at in this case is 0004AC68 - 0004AC78. I'll
explain what each opcode does...| lui | $v1,802F | |
| lw | $v1,CE20($v1) | |
| lhu | $v0,0656($v1) | |
| addiu | $v0,$v0,FFE0 | |
| sh | $v0,0656($v1) |
| lui $v1,802F | LUI - Load Upper Immediate: This puts the hex value (immediate) into the left (upper) half of the reg specified. Meaning $v1 now equals 802F0000. |
| lw $v1,CE20($v1) | LW - Load Word: This loads the word (32-bit) value of the reg in () + the hex offset into the reg on the left. The hex offset is signed though; the means if the offset is higher than 7FFF, the upper 16 bits are made FFFF. So, CE20 is actually FFFFCE20. The 32-bit value at 802ECE20 is "800EFBC0", so $v1 is 800EFBC0 now. Anyone familar with pointers? This is what they're for. hehe |
| lhu $v0,0656($v1) | LHU - Load Halfword Unsigned: This loads the halfword (16-bit) value from $v1 + 0656 hex (signed offset) into $v0. Now $v0 is the amount of Ice you currently have. |
| addiu $v0,$v0,FFE0 | ADDIU - Add Immediate Unsigned Word: This adds the 2nd reg listed + the hex value and puts that value into the 1st reg, so $v0 = $v0 + FFE0. Now you're gonna say, "how does that decrease my ice?" Well, let's say your Ice, $v0, is 00000080. Now add FFE0 to it and you get 00010060. |
| sh $v0,0656($v1) | Store Halfword: Same as when you loaded this halfword value 2 opcodes above. Now you're just storing it. So how does it decrease your ice? It's only storing the halfword value in $v0 to the RAM. That means it's only storing the 16 bits (4 digits) on the right, so it's storing 0060. Now your ice was decreased by 20 (hex). |
Ok, we can see the a few values changed. The code would be:
8004AC75 0002
8104AC76 00FF
8004AC7B 0054
That's your code. You changed the ASM so it makes your health 00FF everytime
you use ice, and your ice never goes down because the asm that was decreasing
it is changed to refill your health instead. We can shorten this code to 2
lines if we want to.
8104AC74 2400
8004AC7B 0054
The first line kills that ADDIU opcode and the 2nd makes it store the value of
$v0 to your health instead of ice, so basicly, it copies the amount of ice
you have into your health.
Hacking Some Various Types Of Codes Using ASM
I showed above you how to make Infinite Ammo, Health, etc and Modify you ammo
consumption & such all in pretty much the same way there. Now I'll show you how to
hack some other types of ASM codes. I'll try to start out with easier codes and
progress to more advanced stuff. Always remember, "there's more than one way to
skin a cat." The examples I'm showing you are never the only way of doing
something, and they're by no means the only types of things you can do. The
only limits in ASM hacking are the hacker's mind.
Infinite Ammo For All Guns
There are times when the method I stated above won't affect all your guns.
Duke Nukem 64 is an example of this. Each gun has its own routine that
decrements your ammo when you shoot. Think the only way to do it is a code for
each gun? Nah. Let's make 1 code do it all.
Set a BPR on the ammo for whatever gun you have currently equipped (Pistol in
my case - 802A5A00). The game should halt immediately.
Breakpoint/PC Address: 8006F8E0.
Opcode: LH $A2,59FE($A2)
What it does:
Loads Halfword value $A2 from $A2 + 59FE. $A2 is 802A0002.
(802A0002 + 59FE = 802A5A00) In this case, the reg that's holding the address
we're going to need to write to is overwritten by the load opcode. This isn't
a problem; it's actually useful in this case. That initial address in $A2
changes depending on what gun you have equipped so it can read the ammo you
have for whatever gun is equipped. It's actually using this to display your
ammo on the screen. Do we care? No, so let's change it and get Infinite Ammo
for all weapons. :)
Since it's a Load Halfword (LH), we want it to Store Halfward (SH) instead.
Sounds good, right? But what do we store? If you can find a reg that always has
a useful value in it (like something between 0001 and FFFF) you can use it;
otherwise you'd have to go through setting the value yourself. For now, we'll
do this the easy way. Remember $K1 is always 0AAA? Well, we'll store it and
always have AAA (2730) bullets for all guns.
Our new Opcode is: SH $K1,59FE($A2)
When you enter that into Niew, you'll notice only 1 16-Bit address changed,
8106F8E0. The value is now A4DB. There's your code :)
Modify Initial Stats When Starting A New Game
This type of code is reminiscent of the Game Genie� era. "Start With X
Lives" was something that was seen for pretty much every game, but we've never
seen that kinda thing on N64, have we? Well, we can now. I'll use Mario 64 as
an example this time.
At the title screen/menu, set a BPW on Mario's lives (8033B21D). Now Start a
new game. The break will occur at 8025500C, but this stores $zero to the
address, so NOP it and try again. Now you'll get the right one.
Breakpoint/PC Address: 8025501C
Opcode: SB $T2,00AD($T3)
What It Does:
Stores Byte value $T2 to the address $t3 + 00AD.
Now we gotta make it store what we want to there. Start looking at the opcodes
that come before it and find what sets $t2. Luckily, this one is actually the
opcode right before it. 80255018: ADDIU $t2,$zero,0005. This is pretty simple.
Just change the 0005 to whatever you want, so your code would be 8125501A ????.
Lets say, for the sake of argument, that you found a Load instead of an Add
opcode there. You'd have 2 options.
1. Change the op to ADDIU $T2,$zero,????
2. Go to the address the Load op is loading $T2 from and change it there.
"But what if there's no load? I wanna modify something that you start with
0 of, and the opcode just stores $zero." This can be a bit trickier. You can
use $K1 and have AAA of that item if you want -- the easy way out. Or you can
find a place before the Store opcode to put an 'ADDIU $K1,$zero,????'. If you
can replace an exiting op without it causing any problems, or find an empty
space (NOP) somewhere there, you're in good shape. Otherwise, you'd need to
Jump out of that routine to an empty area, set the reg, then Jump back. This
may sound a bit complicated, but it's really quite easy once you get the
hang of it. See Routines & Jumps for more details.
All Scores/Damage Counts For x Player/Team
This is easiest on sports type games (i.e. Gretzky Hocky '98); however
it is possible to make player 2/CPU beat themself on a fighting game and is
rather fun to watch. You simply set s BPW on the score, for example. Then
it'll break when the game adds to your score. On Gretzky Hockey (Pal),
you'll get the shots first, since it's watching that too (because the BPW
covers more than 16-Bits). NOP that and get actually score to get it to break
again. This will be the score asm. Gretzky's is at 8005ABCC.
opcode: SH $T8,3440($A2)
What you need to is look through the opcodes that come before it and find a
suitable one to replace, preferably the opcode that sets $A2 in the first place
(or a nice NOP to make use of). In this case we find a NOP at 8005ABA0. Now
let's say we want i tto always add to team 1's score. That's 800EA870. Split
that into 2 16-Bit halves, 800E and A870. Now because ASM uses signed values
we need to take in account the value of the 2nd half of the address. If it's
more than 7FFF, which it is, we need to add 1 to the 1st half. So 800E becomes
800F. Now we use 'LUI $A2,800F' in that NOP and change both the LH and the SH
opcodes there to add A870 instead of 3440.
Before:
8005ABA0: NOP
8005ABAC: LH $T7,3440($A2)
8005ABCC SH $T8,3440($A2)
After:
8005ABA0: LUI $A2,800F
8005ABAC: LH $T7,A870($A2)
8005ABCC: SH $T8,A870($A2)
So our code is:
8105ABA0 3C06
8105ABA2 800F
8105ABAE A870
8105ABCE A870
You can do that same thing on fighting games, but P2/CPU won't actually
beat themself up, so it's less entertaining. I've never actually accomplished
this myself, but the way it's done starts out the same way as this, but then
requires tracing through the ASM to find where it determines what player is
actually being hit. This has been done for Mortal Kombat Trilogy if you'd
like an example code to look at on your own.
Invcincibility
Using an Infinite Health code but tired of getting banged around? Here's
your solution. I'll use Turok Dinosaur Hunter as an example on this one. If
you know me, you had to know that'd be coming eventually, considering I hacked
over 30,000 codes for that game. hehe
This starts out the same as most things. BPW on Health address and, get
hit by an enemy, game halts. The address of the breakpoint here is 80071494,
but that's a Branch. The actual opcode that wrote it is the next one down,
80071498. NOPing that will stop your health from being decremented when hit,
but doesn't make you untouchable. To do that, you need to scroll down through
the OPs til you find a 'JR $xx'. Look at 80071654. Bingo! JR $RA
JR is a "Jump Register." This jumps to the address stored in $RA. Now, is there
something loading $RA just before that? Yep, 8007164C. We need a BPX after
that loads to find out what it is. On Nemu, this is easy, I mentioned above.
On GSCC2k2, yo'ull have to set it up...
This is what I recommend for GSCC2k2 users:
80071498: LUI $K1,8000
80071658: SW $K1,0060($K1)
In GS code form:
81071498 3C1B
8107149A 8000
81071658 AF7B
8107165A 0060
What that does is set $K1 to 80000000 (the game won't using $K1 for anything,
remember?) and stores it to 80000060, which you'll set a BPW on. Now why did
I pick those addresses? Well, 80071498 is that opcode that stores helath, we
don't what it does and we don't really care about it, so we can change it. Now
80071658 is the opcode directly after JR $RA. Lucky for us it's a NOP, so it
works out well. Now when you get hit again, it'll break. This time, we know
what the break address is going to be, no suprise there. What we wanna know is
what $RA is at the time. In this case, it's 80060A24. Now when you look at the
ASM here, you'll see that it immediately loads $RA from somewhere else and
does another JR $RA. This is not always the case, but it is this time, so BPX
again. Change 80071658 back to NOP, if you didn't didn't already, and put your
SW $K1,0060($K1) at 80060A30 (the NOP following the new JR $RA). Now this time
we get the breakpoint and $RA is 80061D4C; go there. Look up 2 opcodes and you
should se a JAL (Jump And Link). Yep, 80061D40 is JAL 800609A4. That jumps to
800609A4, which appears to be the start of the routine that causes Turok to
take damage. NOP it and see if you become Invincible. Yep, Turok is now a God.
What you just did was trace some ASM. In some games, you'll have to repeat
those steps and trace back even further.
Modify Jump Height (Mega Jump!)
This one's rather hard to explain. You basicly have to find your own way
of doing this, but I'll give you the general concept here. You have to find
the ASM the writes the Moon Jump address when you first press the jump button.
That's harder than it sounds because there are usually multiple constant
writes on the Moon Jump addy, and one of those could be the one you're looking
for so you can't just NOP them. I've found it possible with Nemu64 to keep
resuming and get my charater to jump between breaks, but this can be a bit
tricky. I don't know if it's XP or what, but sometimes I can move and such on
the game when the Commands window is highlighted instead of the main game
window, and other times I can't. One way I've found to get this to happen is to
load the Mario 64 rom, then immidiately click onto whatever window is behind
Nemu; odds are, you'll be able to press whatever keys you've assigned for the
controller and you'll hear Mario's face getting trashed (The little *doing*
you hear when you click his face). Then you'll know this is working and you can
go ahead and load the game you wanna hack. If you can, get that far, then open
the Registers window (Commands window should already be open) and go to the
"COP 1" tab. Now keep resuming and tryin gto jump, as I said, and everytime
time it breaks look at the reg being stored (F4,F6, etc) and see what the value
is. You're usually looking for the one that's 4xxxxxxxx when being stored to
the jump address. Get that far? Good for you. The hard part is over. Now
there are 2 ways you can change the jump height.
1. You can search for that value in the RAM. This is the easy way out, however
you might need to do it more than once if the game has different types of
jumps (i.e. Banjo has normal jump and backflip).
2. Change the ASM. To change COP1 regs though, you can't just use ADDIU. You
have to set a normal reg (like $k1) to the value you want to use with LUI then
use MTC1 to put it in the COP1 reg that the game is storing. In most cases,
you could also stick with the regular ops and change the SWC1 to an SH/SW. For
example sake, I'll show you the way to do it with COP1:
LUI $K1,???? - Load Upper Immediate will set $K1 to ????0000
MTC1 $K1,Fx - Move To COP1 moves the value in $K1 to Fx (x can be 1-31, in
our case it should be the reg that's being store to the Moon
Jump address.
I know this description is a little rough. Imagine trying to write it up. ;)
If you really want to do this with GSCC2k2, I'd suggest setting up the BPW as
HyperHacker describes for his Anti-Gravity How-To below, but jumping up
instead of falling. This is just a theory on my part, as I don't have a working
shark anymore.
Anti-Gravity Codes (by HyperHacker)
You will need GSCC for this. Knowing some ASM may help but isn't required.
1) Find the character's Y Speed. If there's an L Button To Levitate or Moon
Jump code for the game, chances are it works by setting the character's Y
Speed to a constant value. (Also in some cases making them jump - if there's
more than one line besides the activator, remove some until the code only
works when you're in the air - that's the Y Speed.)
2) Open GSCC, go into the RAM editor and start the game.
3) Go into the breakpoint window, and create a Write BP on the character's Y
Speed. Don't enable the BP yet, but use the Tab key to make sure the Set BP
button will activate when you press Enter.
4) In the game, fall off something. (Don't jump, you have to be moving down.)
While in the air, press Enter on the PC to enable the BP.
5) The game should halt immediately. Clear the message box that appears and
GSCC should go to the BP address. (Check the N64regs.txt file it opens to be
sure, since sometimes it goes to the wrong place. The number beside "PC" is
the BP address.)
6) Write down the 16-bit value at this address. Change it to 2400 and the
gravity should be disabled! (You may still slowly fall, some games do that.)
If not, repeat the process (don't change this value back) until you find it.
7) Make a code out of it!
Note: No gravity may get annoying and make the game hard to play. I suggest
you set it up like my Mario 64 codes, this way:
[Activator]
[Anti-gravity code]
[Activator]
[Enable Gravity code*]
[Activator]
[Y Speed = Positive code**]
[Activator]
[Y Speed = 0 code**]
[Activator]
[Y Speed = Negative code**]
Each activator should be different of course.
*The Enable Gravity code is simple. Take the Anti-gravity code and change
the value back to what it originally was.
**These are codes to set the character's Y Speed to any positive value, 0,
and any negative value, allowing the player to move up and down. Play around
to find a nice speed. Also, some games crash when setting the speed to 0, in
which case I recommend about 3000 for most games (which isn't stopped, but so
super slow you wouldn't notice).
(C) 2003 HyperHacker
Walk Through Walls (General Theory Only)
I haven't done a great deal of looking for WTWs yet, but I thought I'd
share the general concept of how you'd find them with ASM because they've
always been such a hot topic.
Theory 1:
On games where you take damage from hitting walls (i.e. certain racing
games) you could BPW on healh/energy and hit a wall to cause the break. Then
start backtracing the ASM a bit and NOPing the Jumps. I did this with F-Zero X
and was able to pass through the walls, althrough you plummit to your death if
you slow down. lol
Theory 2:
Now what about the typical games, where you just bounce your head off the
walls but nothing happens? This may be a little tricky. The idea here would
most likely be to BPW on your X/Z coordinate and find the ASM that causes you
to move. Then look around for branches that skip it when you hit a wall, or
an opcode that stores your X/Z again when you hit something. I don't imagine
this will be easy, but I know someone will want to try it. :)
Breaking Limits
Ever wanna carry more than 100 bullets, but the game wouldn't let you?
I'll show you why and how to get around it. Let's use Turok Dinosaur Hunter
v1.0 for this one. Get near a clip with something other than the pistol
equipped (to avoid extra breaks). Now set a BPR and BPW on the pistol ammo.
You'll get an immediate break on this one. The ASM that breaks is actually
what tells if you're allowed to equip the pistol or not (this is how I made
the weapons shoot without ammo). NOP that and set the BPs again. Now you can
walk over the clip to cause a break. You'll find yourself at 80057DB4, which
is a Branch; the Load Word is in it's delay slot. Now if you look through
the next few opcodes, you'll see these:
80057DC0: SLTI $at,$t0,00C8
-Set On Less Than Immediate.
-if $t0 is less than 00C8, $at is 1, otherwise $at is 0
80057DC4: BNEL $at,$zero,80057F68
-If $at is Not Equal To $zero, then jump to 80057F68
80057DD8: SLTI $at,$t0,0064
-Set On Less Than Immediate.
-if $t0 is less than 0064, $at is 1, otherwise $at is 0
80057DDC: BNEL $at,$zero,80057F68
-If $at is Not Equal To $zero, then jump to 80057F68
C8 (200) is the maximum pistol ammo when you have a backpack and 64 (100) is
the max without the backpack.
If you look at 80057DB0 and B4 you'll see it loads the word (32-Bit) value from
80128D28 (the backpack's on/off address) and branches accordingly. You can NOP
the Branch there to force the pistol to always have the packpack available, or
force the Branch so the backpack is never avilable to the pistol. Now, we can
do a couple different things with the opcodes I showed you above. You probably
noticed by now that you can change the values on the SLTIs to whatever you want
to mod the maximum pistol ammo with/without backpack. Now how bout killing the
limit entirely? Easy. Just force the branch. We can do this by changing it to a
Jump, but that'll make it a 2 line code to replace each Branch. Instead, we'll
change the branch to BEQ $zero,$zero,80057F68. I use this just like I use Short
NOPs. 1000XXXX is BEQ $zero,$zero,XXXX address. :)
Wait, we're not done yet. That will allow you to pickup ammo no matter how much
you have, but if you try it, you'll see you're still capped at 64/C8. This is
because there's another check where it actually adds the pickup to your total,
so when you have 99 bullets and pickup 10 you still end up with 100. When you
get the next breakpoint (you can NOP the LW here or just resume), you'll get a
useless one at 8009269C. NOP it and go again. Now you'll be at 80057B14. See
anything interesting?
80057B28: SLTI $at,$t6,00C9
80057B2C: BNE $at,$zero,80057D10
80057B30: ADDIU $t9,$zero,00C8
80057B40: ADDIU $t1,$zero,0064
80057B44: SLTI $at,$t0,0065
80057B48: BNE $at,$zero,80057D10
and again you'll see it check for the backpack and Branch accordingly.
With This group, notice the ADDIUs. You can change just these and make it so
when a pickup would bump you over 100/200 bullets, it'll give you like 500
instead. You could change both the SLTI and ADDIUs to change the max ammo
with/without backpack. Lastly, you can break the limits entirely by forcing
the Branches like I showed you.
So from 3 breakpoints, we can make all these codes, and probably more that I
haven't even thought of... like adding bullet pickups to other weapons instead.
Max Bullets Modifier (Without Backpack)
81057B42 ????
81057B46 ????
81057DDA ????
Max Bullets Modifier (With Backpack)
81057B32 ????
81057B2A ????
81057DC2 ????
Pistol Can Shoot Without Ammo
810583F8 1000
Pistol Can Shoot Without Ammo (Alternate)
810583F4 240A
810583F6 0001
Break Max Bullets (Without Backpack)
81057B48 1000
81057DDC 1000
Break Max Bullets (Without Backpack)(Alternate)
81057B44 2501
81057DD8 2521
Break Max Bullets (With Backpack)
81057B2C 1000
81057DC4 1000
Break Max Bullets (With Backpack)(Alternate)
81057B28 25C1
81057DC0 2501
Always Have Backpack For Bullets
81057B20 2400
81057DB4 5400
Always Have Backpack For Bullets (Alternate)
81057B18 240F
81057DB0 2419
Always Have Backpack For Bullets (Alternate 2)
81057B22 0001
81057DB6 0001
Copy Bytes Codes
You might've noticed that PSX and all the newer systems have a code type
called "Copy Bytes." What this does is copy values from one location in RAM to
another. You can use ASM to do this on N64 if you want, since Datel didn't
bother to include the code type in the N64 shark.
First, find an ASM routine to 'hook' into. You'll probably want something
that's always executing, but there may be cases where you want something else.
The easiest way I've found to do a Copy Bytes that's always copying is to find
a routine that reads the button/stick activators for the game. I'll use Super
Mario 64 as our example in this one....
We'll do a BPR on the button activator (00367054). We got 80323B58 as our
break address. Now if we look a few opcodes down, we'll see that we can safely
use $t2, $t3, $t4, and $t5. You could jump from 23B58, but I'm going from
23B54 instead -- just my preference. Now, let's jump to 80400000 so we have
plenty of room to work, and I'll show you how to copy the value of one address
to another.
80323B54: J 80400000 - the Jump (duh)
routine now begins at 8040000
LUI $t2,8020
ADDIU $t3,$t2,7702
ADDIU $t2,$t2,7772
LH $t4,0000($t2)
SH $t4,0000($t3)
J 80323B5C
SW $at,0000($t8)
That loads the 16-Bit value in 80207702 into $t4, then stores it to 80207772.
The Store Word (SW) at the end is just the opcode that the Jump replaced from
80323B54.
Now here is an example routine that copies a lot. This will copy 80207700 -
8020776C (Star & Coin Records for File 1) to 80207770 - 802077DC (Star &
Coin Records on File 2).
80323B54: J 80400000 - the Jump (again)
routine begins at 80400000
LUI $t2,8020
ADDIU $t3,$t2,7770
ADDIU $t2,$t2,7700
ADDU $t5,$zero,$zero
LW $t4,0000($t2)
SW $t4,0000($t3)
ADDIU $t2,$t2,0004
ADDIU $t3,$t3,0004
SLTIU $k1,$t5,006C
BNE $k1,$zero,80400010
ADDIU $t5,$t5,0004
J 80323B5C
SW $at,0000($t8)
Ever used a For Loop in other types of programming? Same concept here. If $t5
is less than 6C $k1 is set to 1. If $k1 is Not Equal To $zero then it jumps
back to the LW opcode and proceeds through again.
Writing Routines, Jumping In And Out, Etc
Ok, I bet you're wondering what you can do when you want to change
something but there's no room to do it within the current routine (no NOPs
or useless ops to change). This is where Jumping comes in. Remember in my
Invincibility code example, I showed you how to make Turok Invincible? Well,
what about if we want to do somethin ga little different? Like make him take
Double or Half Damage? Multiply the damage? Well, first you need to find the
opcode that subtracts from Turok's health when he's hit. We found the the
opcode that actually writes the new helath value (80071498), so it should be
a few opcodes or so before that. Look at 80071490. SUBU $V0,$T6,$V1. This
means "$V0 = $T6 - $V1" so $V1 would be the amount of damage taken. We need
to find a play to jump out of this routine now, so we can manipulate $V1 a
bit. This has to happen after $V1 is loaded, but before it's subtracted from
$T6. Also, You can't have 2 consecutive Jump or Branch opcodes because jumps
and branches all have that Delay Slot and putting another Jump/Branch in there
will crash the game. With that Delay slot you also need to take into account
the opcode you're replacing with a Jump. I'll show you what I mean...
80071478: LW $V1,003C($SP)
8007147C: BEQ $V1,$ZERO,80071538
80071480: NOP
80071484: LH $T6,01DC($T0)
80071488: LUI $A0,8010
8007148C: ADDIU $A0,$A0,9E60
80071490: SUBU $V0,$T6,$V1
80071494: BGEZL $V0,800714A8
80071498: SH $V0,01DC(T0)
Ok, see 80071488 and 8007148C? Those need executed in that order, so if you put
a jump at 80071488 that next opcode that uses $A0 would be in the Delay Slot.
We don't want that. 80071484 looks good here. That loads Turok's current health.
Write that opcode down before you change it because you want it to still get
executed at some point in your routine, so you're not losing anything. Ok, we
picked our address to Jump from. Now where do we jump to? You can jump to any
part of the RAM that the game doesn't use. Most games don't use the following
areas after boot up (so they're free for us to play with):
80000058 - 8000007C
80000090 - 800000C0
and typicly you'll find a good amount of space somwhere in the area between
800002B4 and 800003F0
Also, if you're hacking a game that doesn't require the expansion pack, but
you have it anyway, then you've got plenty of RAM to play with (804-808!).
Ok, in this example, we'll Jump to 80000060. The Opcode we'll use is:
J 80000060
That amounts to
81071484 0800
81071486 0018
as our Jump code.
The routine itself is going to double, multiply, or divide $V1. I'll show you
3 ways of accomplishing this, but there are more.
Double:
ADDU $V1,$V1,$V1 - pretty self explanatory, I think $V1 = $V1 + $V1
Multiply: (This is where it gets a little more interesting)
ADDIU $K1,$ZERO,00?? - We set $K1 to the amount we want to multiply by
MULT $V1,$K1 - Multiply $V1 by $K1. The result is stored in "LO"
MFLO $V1 - Move the result from LO to $V1. LO and HI are used for some special
calculations (like MULTU and DIVU). If used with a DIV opcode, LO is the
division result and HI is the remainder.
Divide:
ADDIU $K1,$ZERO,00?? - We set $K1 to the amount we want to divide by
DIV $V1,$K1 - Divide $V1 by $K1. The result is stored in "LO"
MFLO $V1 - Move the result from LO to $V1.
Let's say you've decided on Dividing by 2 so Turok takes Half Damage. Next, we
need to know where we're Jumping back to. This is normally the address of the
Jump plus 8 (we need to skip the Delay Slot since it'a already done). So...
ADDIU $K1,$ZERO,0002
DIV $V1,$K1
MFLO $V1
J 8007148C
Wait a minute. What comes after the Jump? The Delay slot needs to have a valid
ASM opcode (Like a NOP). Oh, what about that opcode that loads health? :)
ADDIU $K1,$ZERO,0002
DIV $V1,$K1
MFLO $V1
J 8007148C
LH $T6,01DC($T0)
That's more like it. Note that in some cases, you may want that opcode to
execute first (like if you needed the health value for something there), but
for this purpose we don't need to. When you can, I recommend putting the last
opcode of your routine in the Delay Slot. If you wanted that health load first
then you'd do it like this:
LH $T6,01DC($T0)
ADDIU $K1,$ZERO,0002
DIV $V1,$K1
J 8007148C
MFLO $V1
That would work just the same. Only difference here is that the LH is done
first instead of last.
Once you get done typing that into Niew, you'll see your code is:
81071484 0800
81071486 0018
81000060 241B
81000062 0002
81000064 007B
81000066 001A
81000068 0000
8100006A 1812
8100006C 0801
8100006E C523
81000070 850E
81000072 01DC
There you have it. "Turok Takes Half Damage"
Tip: Jump And Link
Once you get used to jumping and jumping back, you may want to do it the
easy way. Jump And Link (JAL) works like J but it stores the return address in
$RA for you. Note that you can't always do this because the game may not
load $RA again before it uses it. If you look down through the opcodes in the
routine you're jumping out of, you should be able to fins a JR $xx at the end.
If this is something other than $RA or it loads $RA from somewhere first, then
you're in good shape. Otherwise you'd have to back up that reg somewhere if
you're going to do it. A quick way to tell if you can do this other than
lookin for the JR $xx is to see if you notice a JAL right in the area. If the
game uses JAL there, then you can pretty well bet it's gonna load $RA before
it uses a JR $RA. So to do the above code the way I like to do them....
81071484 becomes JAL 80000060
and
8100006C becomes JR $RA
The new code would be:
81071484 0C00
81071486 0018
81000060 241B
81000062 0002
81000064 007B
81000066 001A
81000068 0000
8100006A 1812
8100006C 03E0
8100006E 0008
81000070 850E
81000072 01DC
Tip: Using Regs Other Than $K1
If you need more than just 1 free reg to use in a routine, you'll have to
look for ones that aren't in use. The safest thing to do, is use regs that you
you will be set right after your routine. In the Tutok example, you could use
$T6 since it's set at the end of your routine anyway. You could also safely
use $V0, $T7, $AT, and $T8 in this example (look at routine to see why).
Expample Of A Longer ASM Routine
Well, you've seen some of the things you can do here already, but just
for good measure I'm going to show you a couple longer, slightly more advanced
routines that I wrote for WWF No Mercy.
Example 1: Universal P1 Ultra Code.
Ever play a game where the player & CPU codes can become switched because
of how the game is setup? The breakpoint for this was a BPR on P1's
Health/Spirit. The general idea here to to find which wrestler is human
controlled and keep giving that wrestler Special, Full Spirit, Full Health,
Max Health, and Full Health For All Body Parts (so you don't submit).
800FE770: JAL 80400000 -Jump to 80400000 And Link, $RA is now 800FE778
80400000: LB $V0,00E9($A0) -Load's the value of the CPU/Human address
80400004: ANDI $V0,$V0,000F -$V0 = $V0 AND 000F, if this is 0, it's human
80400008: BNEZ $V0,80400038 -Branch On Not Equal, skip to addy if $V0 != 0
8040000C: ADDIU $V0,$ZERO,0004 -$V0 = 0 + 0004
80400010: SB $V0,00EE($A0) -Store Byte $V0 to $A0 + 00EE
80400014: ADDIU $V0,$ZERO,0064 -$V0 = 0 + 0064
80400018: SH $V0,00AE($A0) - Store Halfword $V0 to $A0 + 00AE
8040001C: SH $V0,00AC($A0) - the rest of this is the same way: set, store
80400020: SH $V0,00AA($A0)
80400024: ADDIU $V0,$ZERO,4248
80400028: SH $V0,02C4($A0)
8040002C: SH $V0,02C8($A0)
80400030: SH $V0,02CC($A0)
80400034: SH $V0,02D0($A0)
80400038: SH $V0,02D4($A0)
8040003C: JR RA -Jump Register: Jumps to address stored in $RA
80400040: NOP -We'll use a NOP as a Delay Slot since we don't
always want that SH to execute.
In this example, we used $A0, which the game sets to a different wresters'
pointer each time it goes through. So we load the CPU/Control info for
whichever wrestler the game is looking at and check if that wrestler is
human. If it is, we go through our routine of writing that wrestler's stats.
If not, we Branch (skip) over it and just Jump Back.
Using The COP1 Registers And Instructions
If you've gotten the hang of this stuff and maybe tried finding some more
advanced types of codes, or even stopping timers on some games, you've probably
noticed COP1 instructions. COP1 has its own set of opcodes and registers for
working with floating point values.
How do values get into and out of the floating point registers (FPRs)?
They can either be loaded just like we typicly see, using LWC1, or by
moving values from the main regs.
Loading from RAM:
LUI $V0,8014 -Load Upper Immediate, we already know. $V0 = 80140000 now.
LWC1 F2,5420($V0) -Load Word COP1 works just like LW but puts the value into
an FPR, F2 in this case.
LUI $V1,8014 -Load Upper Immediate. $V1 = 80140000
LDC1 F4,5420($V1) -Load Doubleword COP1. Same as above. Used to load a 64bit
value as a double precision floating point value, I guess.
Moving from the main regs:
MTC1 $V0,F2 -Move To COP1. F2 = $V0
Another example:
LUI $V0,3FAB -Load Upper Immediate. $V0 = 3FAB0000
ORI $V0,22D1 -OR Immediate performs a bitwise logical OR on $V0. If you
haven't used OR before, it sets any bits that aren't set.
Since the lower bits aren't set (3FAB0000), this is
just like adding 22D1 to $V0. If $V0 is 3FAB2200 and you
OR it by 22D1, then it'll be 3FAB22D1, as this only sets
what wasn't already there.
MTC1 $V0,F2 -Move $V0 to FPR 2.
Getting values out of FPRs:
SWC1 F5,5420($V0) -Store Word COP1. The usual method of writing the value to
a RAM location.
MFC1 F5,$V1 -Move From COP1. Moves the value from an FPR reg to a main
reg. Thus, $V1 would now be set to the value in F5.
How do I do math operations with FPRs?
Again, this is the same basic concept as you do normally, it's just more
confusing. COP1 supports both single precision floating points and double
precision floating points. You should have a fair idea of what the 2 mean, if
you've programmed much.
Adding:
ADD.S F1,F4,F8 -Floating Point Add, Single Precision. F1 = F4 + F8.
ADD.D F1,F4,F8 -Floating Point Add, Double Precision. F1 = F4 + F8.
Subtracting:
SUB.S F1,F4,F8 -Floating Point Subtract, Single Precision. F1 = F4 + F8.
SUB.D F1,F4,F8 -Floating Point Subtract, Double Precision. F1 = F4 + F8.
Multiplying:
MUL.S F1,F6,F8 -Floating Point Multiply, Single Precision. F1 = F6 * F8
MUL.D F1,F6,F8 -Floating Point Multiply, Double Precision. F1 = F6 * F8
Dividing:
DIV.S F3,F9,F16 -Floating Point Divide, Single Precision. F3 = F9 / F16
DIV.D F3,F9,F16 -Floating Point Divide, Double Precision. F3 = F9 / F16
I like multiplication and division better in COP1 because it doesn't require
you to use the extra OP to extract the result. There are also some other neat
COP1 OPs like NEG, ROUND, FLOOR, CEIL, etc. This was more of a basic
intro to using COP1.
F) Hack Your Shark!? - by HyperHacker
It's actually possible to hack an N64 Gameshark/AR v3.3. You can use these
codes with any game and hack the GS! Sweetness!
81791DF6 ????
81791E02 ???? Lowest Goto Address (normally 80000400)
81791E06 ????
81791E12 ???? Highest Goto Address (normally 803FFFFF)
81791E32 ????
81791E36 ???? Lowest Scroll To Address (normally 80000400)
81791E3A ????
81791E3E ???? Highest Scroll To Address (normally 803FFFFF)
81791E42 ????
81791E4A ???? Address Returned To When Attempting To Go To Invalid Address
(normally 80000400)
807FFDE7 000? Is Controller Active
817FFDE8 ???? Button Pressed Data
817FFDEA ???? Joystick Data (if you can find any use for these last 3, tell me!)
817E9C98 ????
817E9C9A ???? Cursor X Coord
817E9C9C ????
817E9C9E ???? Cursor Y Coord
817E9CA0 ????
817E9CA2 ???? Cursor Mode
807E9D34 - 807E9D44 Text Searched For
You can use this to turn the Text Search into a string search for almost any
number, but beware - If you enter a number between 41h and 5Ah, it will also
search for numbers 20h higher. This is to allow strings to be found in caps or
lowercase. Also, if you enter a number lower than 20h, it will crash
everything, as these are special control bytes rather than text.
I've also hacked the active code list! Using this along with the codes to goto
any RAM, you can alter active codes on the fly. Plus, if you know N64 ASM, you
can create your own types of codes! The list starts at 807C0000. Basically,
it's just a bunch of ASM that is executed several times per second. The formats
are as follows:
80 Code Type (constant 8-bit write)
Format: 3C1A XXXX 375A YYYY 241B ZZZZ A35B 0000
ASM: lui $k0,XXXX
ori $k0,k0,YYYY
addiu $k1,$zero,ZZZZ
sb $k1,0000($k0)
81 Code Type (constant 16-bit write)
Format: 3C1A XXXX 375A YYYY 241B ZZZZ A75B 0000
ASM: lui $k0,XXXX
ori $k0,$k0,YYYY
addiu $k1,$zero,ZZZZ
sh $k1,0000($k0)
88 Code Type (8-bit write, G$ Button triggered)
Format: 3C1A BE40 375A 0000 875B 0000 0000 000F 337B 0400 1760 0004, then
normal 80 code type format
ASM: lui $k0,BE40
ori $k0,$k0,0000
lh $k1,0000($k0)
sync
andi $k1,$k1,0400
bne $k1,$zero,00000028
Then normal 80 code type ASM
89 Code Type (16-bit write, G$ Button triggered)
Format: 3C1A BE40 375A 0000 875B 0000 0000 000F 337B 0400 1760 0004, then
normal 81 code type format
ASM: lui $k0,BE40
ori $k0,$k0,0000
lh $k1,0000($k0)
sync
andi $k1,$k1,0400
bne $k1,$zero,00000028
Then normal 81 code type ASM
D0 Code Type (8-bit activate if equal)
Format: 3C1A XXXX 375A YYYY 835A 0000 241B ZZZZ 175B 0004, then code to be
activated
ASM: lui $k0,XXXX
ori $k0,$k0,YYYY
lb $k0,0000($k0)
addiu $k1,$zero,ZZZZ
bne $k0,$k1,00000024
Then code to be activated
D1 Code Type (16-bit activate if equal)
Format: 3C1A XXXX 375A YYYY 875A 0000 241B ZZZZ 175B 0004, then code to be activated
ASM: lui $k0,XXXX
ori $k0,$k0,YYYY
lh $k0,0000($k0)
addiu $k1,$zero,ZZZZ
bne $k0,$k1,00000024
D2 Code Type (8-bit activate if not equal)
Format:
ASM:
D3 Code Type (16-bit activate if not equal)
Format:
ASM:
THE LIST MUST END WITH THE FOLLOWING CODE:
3C1A 8000 375A 0120 0340 0008 0000 0020
IF IT DOES NOT, THE GAME WILL FREEZE AS PROCESSING WILL NOT RETURN TO THE GAME
PROGRAM.
G) Hacking Playstation 2 Codes
There are no trainers, code gens, etc publicly available for PS2 as of
right now, and according to CodeMaster doesn't look promissing. This is because
it's so hard to get things like this working on the system. So how are some of
us doing it?
WARNING: Either of these methods could potentially cause damage to your
system if you enter bad codes! This isn't a common occurence, but you have
been warned! The authors are not responsible for any damage you may cause
to your PS2!
Guess & Check
Yeah, the old "Guess & Check" methods are usuable on PS2. This can be
done with encrypted codes, but it's recommended that you play with RAW codes
and encrypt them yourself. The Codebreaker PS2 actually has the ability to
accept RAW codes, I think. This can make things easier. Still, you're left
with a problem: There's too much RAM to play with, and constatly rebooting
with a CD based cheat device is a real pain. The only shortcut I've found if
you're really looking to find a specific effect is to use patch codes to
conver a certain amount of the RAM at a time til you get the desired effect.
Then narrow down the patch a little at a time til you lose the effect and
you'll know where the code is. NOTE: To pretty well eliminate the risk of
messing up your PS2 with a faulty code, stay in the same area of the RAM as the
existing codes for thew game you are hacking.
Using PS2DIS - Courtesy hellion (hellion00.thegfcc.com)
Disclaimer: Very few SLUS files have the proper labels for this kind of code. Don't be disappointed when this strategy doesn't work for most other games. Open the GTA3 SLUS in the DIS. Today, we're going to be looking at a couple of simple variable-setting codes. The first thing we need to do is open the Label Listing (Ctrl+G) and see if we can find anything interesting. Now, there are lots and lots of labels in the GTA3 SLUS, and most of them just aren't helpful at all. It takes a lot of patience to look through them to find the ones that are useful. To save you some time and to facilitate the learning process, I'll go ahead and point out a couple of them for you. Example #1 With the Label Listing open, type Lives in the text box at the top. The selection will automatically move to the first label that starts with what you typed. If you press Enter, the DIS cursor will move to the line of code that has the selected label. You should now have selected the address for "LivesSavedWithAmbulance__6CStats". As you can probably guess from the label, this stores the number of people you have saved in the Paramedic Missions. Now that we have an address (00416EE8), we need to figure out what value we want to use. Remember that this value needs to be in hexadecimal form. Let's say we want to have 1000 people saved. Converting 1000 to hexadecimal gives us 3E8. (Windows Calculator in Scientific Mode converts between decimal and hexadecimal easily) With an address and value in hand, we need to figure out what GameShark command we want to use. Since 3E8 is larger than 8 bits (2 hex digits), we can't use the 8-bit Write. 3E8 is smaller than 16 bits (4 hex digits), so we can use the 16-bit Write. The format for that is 1aaaaaaa 0000dddd, where a is the address and d is the value. Putting it all together, we have: 10416EE8 000003E8 (dropping the first zero from the address to make it 7 digits, and adding a zero to the value to make it 4 digits). Last, you need to encrypt the code. The encryption you use depends on the game you are hacking. GTA3 GameShark codes use the 1456E7A5 encryption, so we will use that as well. Using the converter to encrypt the code gives us: 1000 People Saved Example #2 Open the Label Listing again and type Respray in the text box. It should bring you to the label "RespraysAreFree__8CGarages". Press Enter to go to that address. The name of this variable implies that this is a yes or no question. Are resprays free or not? In programming, this is known as a Boolean variable (stores True or False). True is normally represented by a 1, and False is represented by 0. Taking this into account, it would make sense that if we set this variable to 1, then resprays would be free. So, we take the address (00416F90) and the value (1, 1 converted to hexadecimal is still 1) and figure out what command we need to use. Since 1 is less than 8 bits, we can use the 8-bit Write. The format for that is 0aaaaaaa 000000dd. Filling in the address and value, we have: 00416F90 00000001 (again, dropping the zero off the address and adding a zero to the value to make it two digits). Encrypting with the 1456E7A5 encryption gives us: Free Resprays |
See those "0100"s in the upper-left? The first one is the X coordinate size
(which you just hacked) and the second one is the Y coordinate size. In this
case, the address for the Y coordinate is 03003D30, just two addresses higher
than the X coordinate size.
This is usually the case: the X coordinate and Y coordinate size modifiers are
close like this. So if you find one, you've practically found the other.
Let's do a general recap:
-Start the search process and move somewhere else (or even change the area you
are in, if you're hacking a code for your character). Do an Equal to search.
-Make the object get squished, smashed from the sides, or shrink. Do a
Less than search. (If you can make the object get larger, do a
Greater than search.)
-When it reverts/grows to normal size, do a Greater than search. (Less than
if the object had grown.)
-Move around a bit and/or change other stuff and do an Equal to search. Do NOT
make the object you want to modify get destroyed or go to an area where that
object is not present.
-If you don't have a manageable number of results (less than 20), repeat.
-Look for codes with the value 0100. Check the area of memory around
that/those code address(es) to find the size modifier for the other
coordinate, if it didn't show up in your search.
-Encrypt the code(s) as needed.
Now what if the object you want to hack DOESN'T change shape? Then what?
Known Value Method:
This method is good for hacking size modifiers for objects that do not normally
change shape. For this example, I'll be hacking a size mod for one of the
computer racers, again in Mario Kart: Super Circuit.
-Load the ROM and select a new file.
-Select "Mario GP," any cup, any racer, and any track.
-Now, when the characters are waiting behind the finish line, open the cheat
search menu, and do a 16-bit search for 0100. (I'm assuming you know how to
configure it to your liking, since I'm assuming you followed along in the
previous section of this guide.)
-You'll get a load of results. Check the results for a pair of addresses in
which the second address is two addresses higher than the first
(1st address + 2). There are several, so start testing them out, using the
value C000.
-If a code doesn't work, go back to your results and start checking again. If
any values are NOT 0100 or C000, search for 0100 again to get rid of them.
-Elimination will eventually lead you to 03003ECE, which is the X coordinate
size modifier for the first CPU player. You can check out the memory to get
the code for the Y coordinate, but here, you don't have to. The very next
result is 03003ED0, which just so happens to be two addresses higher than the
X coord code. Now we have the complete code set for CPU 1.
-Encrypt your code(s) as needed.
To recap, all you have to do is just search for 0100 (256 in decimal). As of
now, this is the only value I have seen used for GBA size mods, but I have a
feeling that programmers may use different values in the future.
So that's how to hack size modifiers for your Game Boy Advance games. Be
warned that not all of them will be as easy to hack as they were in Super
Circuit - I just used Super Circuit as an example because it's easy to hack,
and I feel that the best way to learn to hack (aside from example) is to hack
an easy code/game first. Three closing tips:
-Some objects are seemingly "unhackable," so you feel that you may be forced
to give up hacking a code. Don't let this discourage you.
-Some games, such as racing games, may have "patterns" that you can follow.
In Super Circuit, for example, you can add 1A0 to each memory address to get
the address of the next racer's size mod.
C) Finding GameBoy Advance Enabler Codes
- By Parasyte (Used with Permission)
Required Software:
GameBoy Advance ROM to hack (find on your own)
Mappy Virtual Machine - www.bottledlight.com/
GameShark Advance Code Encryption Program
GameBoy Advance Enablers are comprised of two parts, the first part is the
hook routine. It overwrites some assembly in ROM/RAM with a jump to the GSA
code handling routines. This jump must be executed many times per second. So a
good place to hook would be the controller reading routine.
The Second part is an ID Code, it's not needed, but it's good to have if you
like the GSA auto-detecting your game.
Hacking the hook code:
(this method only works on Thumb assembly in ROM)
1) Load up the rom in Mappy, then goto View -> Disassembler
2) Goto File -> Export -> Disassembly
3) Pick a destination txt file to save
4) Near the bottom you see three text boxes, leave the first one blank, type
08000000 into the second, and 200000 into the third
5) Select "Thumb" in the drop down list box
6) Click the Add button
7) Click the OK button, and wait a few seconds to a minute for the disassembly to
complete.
8) Open the new txt file in a text editor, the file will be around 7MB
9) Text search for 04000130
10) You may find more than one place with this info, so be sure to write down
ever address with that text string.
11) Going through all addresses, find two opcodes that might work. They can be
anything BELOW the "04000130", and ABOVE any opcode beginning with a "B". The
two opcodes you choose must be right next to each other, and they cannot have
an "=" sign in any part of the line. Example of USABLE opcodes -
080002D2 add r1, r4, #0
080002D4 add r1, #24
080002DE ldrh r0, [r0]
080002E0 mvn r0, r0
Example of NON-USABLE opcodes -
080002E8 bne #$080002F2
080002EA ldr r0, =$03000540
12) Once you find an address that can be used, put the "F" code type on it, and
use the value 00000101. Encrypt the code, and try it with any known codes, just
to make sure it works. Example: F80002DE 00000101
13) If the game crashes, try using a value of 00000102. If the game still crashes,
you will need to find another area to hook. The easiest method to do this
envolves running the game in an emulator (VisualBoy Advance-SDL) and halting the
game anywhere during execution. You should almost always end up in a piece of
ASM that is executed many, many times. So just use the rules above and find a
new address to use.
Hacking the ID Code:
1) Load the ROM into a hex editor
2) Jump to address 000000AC
3) Copy the 4 bytes at this address, then reverse all bytes. Example: "41424344"
becomes "44434241"
4) Encrypt this as an address with a value of 001DC0DE using the Game Shark Advance
encrypter. Example: 44434241 001DC0DE
5) GameShark Advance should autodetect the game with this code in your(M) code
D) Creating AR V3 Codes Using AR Crypt - by Kenobi
{Special Acknowledgement: This program is based on the original AR Crypt
algorithm by Parasyte.
You will need the AR Crypt program by Kenobi.
Get it here
GS Central is currently the only authorized site to host this program.
As such, neither the program creator or GS Central will not
be held responsible for un-authorized web sites carrying this program.
Authorization to host this ptogram is soley up to the program creator and
that authorization is final and binding.
Check "Expert Mode" in the Main menu, and check "AR V3" in the "Create..." Menu.
You can either choose the "Code Type" in the combobox or you can enter the
"numbers separated by periods" found in this document in the "Data Size",
"Code Type", "Code Subtype", "Special" and "Unused" spinedit boxes.
Then Type in the 1st line of the left memo your RAW codes on ONE LINE with
SPACES between the 32bits numbers.
Press the "Create" Button.
Example
Example
11) 2 Lines Special Codes (= starting with '00000000' and padded (if
needed)
with "00000000").
To add the 0s automatically, check the "pad with 0s" checkox of ARCrypt.
Type z09
1.2.0.x.x
XXXXXXXX : (02024EA4 -> 14224EA4)
0000ZZZZ : Writes Halfword ZZZZ to address XXXXXXXX."
You can either search the "Type z09" code type in the combobox, or you can
do everything manually :
-set "Data Size" to 1, "Code Type" to 2, "Code Subtype" to 0, "Special" to x
(=any value, for exemple 0) and "Unused" to x (=any value, for exemple 0),
and finally check the
"pad with 0s" checkbox.
Type in the left memo your RAW address (for exemple "02024ea4") and your
value
(8 digits, padded with 0es at the start if needed ; for exemple "00001234").
(That gives 02024ea400001234).
Now press the Create button. Ar Crypt will compute the ARV3 Raw (=
unencrypted)
code, will display it on the 2nd line of the left memo, and will encrypt it
in
the right memo.
Left memo : Right memo:
02024ea0 00000001
00000000 12224EA0 A81467EF C2D5BB2A
00000001 00000000 7FD49BC1 DBCF6C10
The good ARV3 Code is :
A81467EF C2D5BB2A
7FD49BC1 DBCF6C10
(One day, AR Crypt will pad the codes with 0es automatically. Until then,
you'll have to do it manually).
WARNING!!!!!!
All addresses obtained by decrypting V3 codes are in V3 RAW Format.
Let's say the decrypted V3 code is : XXXXXXXX YYYYYYYY
"Data Size" = (XXXXXXXX >> $19) AND 3
"Code Type" = (XXXXXXXX >> $1B) AND 7
"Code Subtype" = (XXXXXXXX >> $1E) AND 3
"Unknown 2" = (XXXXXXXX >> $18) AND 1
"Unknown 1" = (XXXXXXXX >> $12) AND 3
"Unknown 1" seems to never be used. It's not even calculated by the AR.
The data is just trashed. But it isn't useless. It might be used to create
codes that will have some kind of signature, so you might know if someone steal
your codes...
Morevover, you an also change the "x" to any allowed value to create even more
"signatures".
For exemple :
0.0.0.x.x will give you 4*2=8 different encryptions for the very same code.
x.1.0.x.x will give you 4*4*2=32 different encryptions for the very same code.
Then, to get the the real RAW address, you need to do :
XXXXXXXX = (XXXXXXXX AND $01FFFFFF)
RAW address = ((XXXXXXXX << 4) AND $0F000000) + (XXXXXXXX AND $0003FFFF)
E) Tutorial: Hacking Non-Standard Master Codes
this is several posts from the gscentral vb - courtesy parasyte
--------------------------------------------------------------------------------
There are a few GBA games out there for which a master code cannot be found by
any of the 'standard' methods, such as using Kenobi's AR Crypt. The two
examples I will cover here are Baulder's Gate: Dark Alliance, and Phantasy
Star (a part of Phantasy Star Collection).
Baulder's Gate is an easy one. Just about anyone with the ROM and VBA-SDL can
hack the master code for it. Not a whole lot of assembly knowledge is required.
You just have to know what to look for.
If you load the game in AR Crypt and attempt to search for a master code,
you'll come up empty handed (be sure to use on the latest version of AR Crypt).
So to make our master code, we'll have to use a process which is a bit more
involved.
Load up the game in VBA-SDL, and get into the gameplay part of the game. (By the
looks of the damn intro, I thought it was an interactive novel, bah! Developers
need to stop forcing lame intros like that upon us gamers.) Once you are in the
game, and ready to go, open the ROM in a hex editor. Run a hex search for
"0047C0460847C046" -- this is the beginning of what I like to call the "Long
Branch Routines." Almost every game will have one, so take notes!
I found the long branch routines at file offset 006A9888. This, of course,
translates to GBA ROM address 086A9888. Knowing this, go back to VBA-SDL and
press F11 to bring up the debug console. In the debug console, type "dt
086A9888" This will disassemble the long branch routines into thumb assembly.
All games that have these long branch routines will look exactly the same, so
you probably won't ever have to disassemble it again. Just notice where all
the 'bx' instructions are:
086a9888 4700 bx r0
086a988a 46c0 mov r8, r8
086a988c 4708 bx r1
086a988e 46c0 mov r8, r8
086a9890 4710 bx r2
086a9892 46c0 mov r8, r8
Etc! You can easily spot the pattern. The bx instructions will rest on a 4-byte
boundary, followed by 'mov r8,r8' which is the official Thumb instruction for
NOP. (No Operation)
Anyway, these bx instructions are what you will use to find a long branch type
master code. Let's start with the first one - 'bx r0.' Set a thumb breakpoint
on that address using the command "bt 086A9888" then use the command "c" to
continue running the game.
What we are looking for is one of these bx instructions which execute many times
per second. After I set the breakpoint on 'bx r0,' I did not get any hits when I
ran the game. So this one will not do! Press F11 again, and delete the
breakpoint using command "bd 0". Now set a thumb breakpoint on the next bx
instruction using command "bt 086A988C" and run the game with the "c" command.
Now here's where it starts to get interesting. Immediately after running the
game, my breakpoint was hit, meaning the 'bx r1' instruction is used. Now what
we want to do is copy down the value of the r1 register as reported by VBA. (We
copy the value of r1, because we set a breakpoint on the 'bx r1' .. see how
that works?) The register used by the bx instruction will always contain an
address at this point. The bx instruction is used to branch\jump to the address
contained in that register.
As of now, the r1 register contains value '03003ef8' which we know is a RAM
address. I just temporarily wrote that into notepad, and now I am going to just
run the game again, and let the breakpoint pause it once more. This time, I get
the same address... I've already written that address down, so I will continue
running the game (at least 20 times, if needed) to see if any other addresses
are run.
About 5 runs later, r1 contains '0869fc05' -- a ROM address. This is a good
start. I'll write this address down and simply continue running the game quite
a few more time, recording every address, until I believe I have written all of
the different addresses into notepad.
And here is my list, so far:
03003ef8
0869fc05
0869e145
02000634
02000514
0869e3d5
0869e0d9
Now that I believe I have all of the addresses which are used here, I will
delete the breakpoint using "bd 0" and run the game. Then I'll move on to
another area... Since I'm in the tavern, I have to go into the cellar.
Once there, I'm going to push F11 and set the breakpoint on the 'bx r1'
instruction again, and repeat the process of writing down addresses. Make
sure you keep your list of addresses clearly seperate.
Now I've got this for my second list:
0869e3d5
0869d5a1
0869d165
0869c881
03003ef8
0869fc05
0869d81d
0869cf61
What you want to do at this point is find addresses between each list that
match. So based on my lists, here are the common addresses so far:
03003ef8
0869fc05
0869e3d5
Now, just to be safe, I am going to continue through the cellar and kill
everything so I can exit the tavern.
Once I'm outside, I'll set the breakpoint again, write down more addresses,
and update my common addresses list... And funny that! My list of common
addresses matches exactly the address list I made while outside of the
tavern. Good enough, let's make us a master code!
We've got only three common addresses, as listed above. To make the master
code, we need to search for these addresses in the ROM. When searching for
32-bit values in a GBA ROM, you have to 'byte swap' the value, and search
for that. As an example, the first common address is '03003ef8.' If we split
that into bytes, we get '03 00 3e f8.' Then we reverse the order of the
bytes to byte swap it, and we get 'f8 3e 00 03.' Now search for 'f83e0003'
in the rom. Well, our first minor snag. This pointer is not present in the
ROM at all. So remove that address from the list, and move on.
Searching for the next pointer (05fc6908) turns up four possible locations.
Our second minor snag -- any one of those four could be the correct one, or
they could each be used for four different parts of the game. This is not
good. For the sake of simplicity, set that address aside, and use it only
in the emergency that our 3rd address is also no good.
Searching for the third pointer in the rom (d5e36908) we are left with a
grand total of only one possible location! Success! We now have the location
of our master code. The pointer rests at offset 007EF48C. So attach the
normal 'C4' master code codetype to it. Then append a 'value' of 000084x3 to
it, for a standard long branch type master code, where 'x' is the register
number that is used by the bx instruction. In this case, it would be 1,
for r1.
Baulder's Gate: Dark Alliance
(m)
C47EF48C 00008413
Pretty simple, eh?
If that third common address had been no good, you could have either gone back
to test all 4 possibilites from the second pointer, or just move on to 'bx r2'
and record the addresses from the r2 register. Usually after about r7, they
stop getting used so often.
That about does it for now. I'll continue the tutorial with Phantasy Star
later tonight, or tomorrow some time.
--------------------------------------------------------------------------------
rrr. Getting back on track, here's how you hack a master code for a game like
Phantasy Star within Phantasy Star Collection.
The first thing I'm going to say is that Phantasy Star Collection contains
four executables. So this is one reason that hacking this particular game is
so difficult. You got three executables -- one for each of the three games
within the collection -- and the fourth executable is the initial loader\game
selector.
The loader executable does not need any hacking, and two of the three game
executables have easily reached master code locations. But, after doing a
little research, it's plain to see that the Phantasy Star executable lies at
ROM address 08738000. The problem here should be obvious; a standard bl-type
master code absolutely CANNOT be used on any address above 0840001C. It is an
impossibility.
If you begin to hack the Phantasy Star master code like we did with Baulder's
Gate, you run into a HUGE problem right off the bat.... There are no long
branch routines in the Phantasy Star executable. Bummer.
What we do to resolve this issue is take a completely different approach. We
will start with the interrupt handler. Interrupts will occur several times
per second, so they are perfect for our needs.
To find the interrupt handler, load up Phantasy Star. The title screen will
work just as well as anywhere. If you're using VBA-SDL, (my emulator of
choice for master code hacking) bring up the debug console, and use the 'mw'
command to display the contents of the interrupt vector. The GBA interrupt
vector is always at address 03007FFC, so use command "mw 03007FFC". The first
value displayed will be [should be] a pointer -- this is the pointer to the
interrupt handler. Mine is displaying '020207d0.'
This is an ARM address. You can tell, because the pointer is an even number.
An odd number means it is a Thumb address. (For example, if it where
'020207d1' that would indicate Thumb assembly) Disassemble to ARM, starting
at 020207d0. (Command "da 020207d0") And search for the first bx instruction
you can find. Here is what I found:
02020884 e59f1010 ldr r1, [$0202089c] (=$02000070)
02020888 e0811002 add r1, r1, r2
0202088c e5910000 ldr r0, [r1]
02020890 e12fff10 bx r0
This assembly loads pointer 02000070 into register r1. Then it offsets the
register by adding the value of r2 to it. Finally, it loads a pointer from
the resulting address into register r0, and branches to the pointer in r0
using the bx instruction. This is a prime example of a "jump table." A jump
table is a fairly large table of pointers stored in RAM. One of the pointers
will be loaded from the table, and that pointer is jumped to, hence the name:
jump table.
So let's start by dumping the jump table from address 02000070 using the
command: "mw 02000070"
02000070 087384a1 0873a9fd 0873aa01 0873a9fd
02000080 0873a9fd 0873aa21 0876ca91 0873a9fd
02000090 0873a9fd 0873a9fd 0873a9fd 0873a9fd
020000a0 0873a9fd 0873a9fd 00000000 00000000
Looking good, eh! You can tell these are all ROM pointers, so maybe one of
these will be something of importance that can be used as a master code.
All of these pointers are odd numbers, and as we know, that means they are
all pointers to Thumb assembly!
This jump table contains a total of five different pointers:
087384a1
0873a9fd
0873aa01
0873aa21
0876ca91
Let's disassemble a little bit from each of these addresses, and compare
notes later. (Notice! Before you will be able to disassemble, you must
'convert' each pointer to an even number. Do this by simply subtracting 1
from the pointer. As an example with the first pointer, you will disassemble
is using command: "dt 087384a0". Then the next using "dt 0873a9fc")
087384a0 b5f0 push {r4-r7,lr}
087384a2 4a2b ldr r2, [$08738550] (=$020004e8)
087384a4 482b ldr r0, [$08738554] (=$04000130)
087384a6 8801 ldrh r1, [r0, #0x0]
087384a8 4b2b ldr r3, [$08738558] (=$000003ff)
087384aa 1c18 add r0, r3, #0x0
087384ac 4041 eor r1, r0
...
0873a9fc 4770 bx lr
0873aa00 4904 ldr r1, [$0873aa14] (=$0400000c)
0873aa02 4a05 ldr r2, [$0873aa18] (=$00004409)
0873aa04 1c10 add r0, r2, #0x0
0873aa06 8008 strh r0, [r1, #0x0]
0873aa08 3908 sub r1, #0x8
0873aa0a 4a04 ldr r2, [$0873aa1c] (=$00007028)
0873aa0c 1c10 add r0, r2, #0x0
0873aa0e 8008 strh r0, [r1, #0x0]
0873aa10 4770 bx lr
0873aa20 4770 bx lr
0876ca90 4906 ldr r1, [$0876caac] (=$02000052)
0876ca92 8808 ldrh r0, [r1, #0x0]
0876ca94 2800 cmp r0, #0x0
0876ca96 d008 beq $0876caaa
0876ca98 8808 ldrh r0, [r1, #0x0]
0876ca9a 3801 sub r0, #0x1
0876ca9c 8008 strh r0, [r1, #0x0]
0876ca9e 0400 lsl r0, r0, #0x10
0876caa0 2800 cmp r0, #0x0
0876caa2 d102 bne $0876caaa
0876caa4 4902 ldr r1, [$0876cab0] (=$02000054)
0876caa6 2001 mov r0, #0x1
0876caa8 7008 strb r0, [r1, #0x0]
0876caaa 4770 bx lr
Now then... The second and fourth addresses only contain a "bx lr" instruction,
meaning both routines simply return, doing absolutely NOTHING. I would not trust
either of those. Of the remaining three, the first one looks very familiar...
it's a joypad read routine! This is VEEERRRRRRY promising. So let's take the
pointer to this joypad routine (087384a1) and do the byte swap trick. Hex search
the Phantasy Star Collection rom for the value (a1847308), and wouldn't you know
it! There's only one match, and it is definitely inside the Phantasy Star
executable.
The pointer to the joypad routine is located at offset 007383FC... This means we
get to make us a master code and test it out. Attach the C4 codetype, and append
the 000084x3 value! If you remember the ARM assembly we disassembled in the
interrupt handler, the first bx instruction we came across was 'bx r0'. So of
course we are going to use the value of '0' to replace the 'x' in our new master
code. (Again, this 'x' is used to select which register was originally used to
branch to the original address.)
Phantasy Star Collection
Phantasy Star (m)
C47383FC 00008403
If you give her a test, you'll find that she sure works like a champ. Another
difficult-to-hack master code solved. Case closed.
P.S. You may be wondering why you can't just use the interrupt handler pointer
that you pulled from address 03007FFC. This is a great question. When the
interrupt handler is run, the BIOS is what loads the pointer to jump to. But,
the whole reason for telling the master code which register is used to run the
original address is an important factor, here. After the AR is finished doing
it's thing, it MUST run the original address. If it does not, you'll be left
with nothing more than glitches and crashing. When AR runs that original
address, it does so by executing a bx instruction.... By having that bx
instruction use the same exact register which the original used, you eliminate
any possible register corruption.
This leads us back to the original question; why can't I just use the pointer
to the interrupt handler? Simply put, the best explanation is because a bx
instruction is NOT used to run the interrupt handler. So you would only run
the risk of corrupting registers by doing so.
I hope you enjoy these technical explanations. They are fun to write, and
educational for everyone! It's a win-win situation.
--------------------------------------------------------------------------------
dlong: How many rom patches does the long branch master code use up?
--------------------------------------------------------------------------------
Long branch type master codes only use 2 of the 3 rom patches allocated for
master codes. What the long branch type master code actually does is replace
the pointer at the master code address with a pointer to 08000021 -- the place
where AR keeps it's code engine entry point.
F) Gameboy Advance ASM Tutorial - by Kenobi
The following is a hands on tutorial in using VBA SDL in hacking rom patch codes.
The game used for this lesson was IronMan for GBA.
There are two examples given:Item never decreases code and invincilibity.
This tutorial is used with permission of Kenobi who generously gave of
his time to prepare and walk thru this tutorial with macrox.
Game info: In IronMan there is a blue orb that gives him advanced blast powers against
his enemies. There are two levels to this power. The first is like a giant ray blast
which destroys most of his enemies in a direct line of action, while the second level
destroys all the enemies on screen.
ASM GBA Hacking - 1st Part Example #1 - Item Never Decreases
- Blue Orb Quantity never decreases code.
What you will need :
VBA (normal).
VBASDL.
The rom file. (Neither the authors nor GSC support the method of obtaining
this file).
A save state at the very start of level 03, with the blue orb on Iron Man.
The address of the blue orb quantity. [0202CCF4]
Optional but essential info: GBA Tech document.
http://www.work.de/nocash/gbatek.htm
You will need to study this document to be able to understand the call
functions and thus make the most out of VBA SDL hacking.
- Load the game in VBA (normal). Load the save state, and remove ALL the cheats
(even if they are off).
Take the blue orb if you didn't took it already, then save the save state.
- Now load the game in VBASDL, load the save state, then press F11 to enter the
debugger.
- Type "BPW 0202CCF4 2" in the DOS window to set a break on write on address
0202CCF4 for 2 bytes.
- Type "c" in the DOS window go go back to the game.
- Use the blue orb power (press L). The game will freeze because the break on
write did happen.
(the quantity of blue orb decreased).
- Look in the DOS window. You'll see that :
Breakpoint (on write) address 0202ccf4 old:00000001 new 00000000
R00=00000000 R04=00000000 R08=0202cb00 R12=00000001
R01=0202ccf4 R05=00000001 R09=0202cbd0 R13=03007ba4
R02=0202cb84 R06=0202cbd0 R10=0202cbcc R14=0802c5fd
R03=080365bf R07=0202cbcc R11=00000000 R15=0802c63e
CPSR=6000003f (.ZC...T Mode: 1f)
0802c63c 9004 str r0, [sp,#0x10]
- The address of the very last line is what we need : 0802c63c.
- Go back to VBA (normal). Make "Tools" then "Dissassemble", click
the "THUMB" button, and enter the address we just found.
- You'll see a lot of stuff. The 1st line will be :
0802c63c 9004 str r0, [sp, #0x10]
- Go up one line. You'll see that :
0802c63a 6008 str r0, [r1, #0x0]
- This should be the line that changed the value of the blue orb
quantity, and that triggered the breakpoint.
- We'll make sure this line is the one we are looking for.
Go back to VBASDL, load the save state, and press F11.
- Type in "bt 0802c63a" (this will set a THUMB breakpoint on address
0802c63a. That means when the asm code stored at address 0802c63a
is executed, the game will freeze).
- Type "c", then use the blue orb power. The game will freeze.
- Type "mw 0202CCF4". You'll see a lot of numbers, the very fist one
(top left) will be the blue orb quantity. It should be "0001"
- Type "n", then type again "mw 0202CCF4" (you can use the up/down arrows
to select a line you already typed in). You'll see that the number has
changed.
Now, it's "0000". That means the line 0802c63a is where the game saves the
new value of the blue orb when you use one.
- Now we have 2 choices. We could just remove the asm code of line 0802c63a, so
that the game never updates the quantity of the blue orb.
The THUMB asm code that "deletes" a line (it's called "noop" which should mean
no operations)is 46C0.
--------------------
How did I know it? Well, look at the GBA tech document http://www.work.de/nocash/gbatek.htm
click on "Pseudo Instructions and Directives".
You'll see :
THUMB Pseudo Instructions
nop mov r8,r8
ldr Rd,=Imm ldr Rd,[r15,disp] ;use .pool as parameter field
add Rd,=addr add Rd,r15,disp
adr Rd,addr add Rd,r15,disp
mov Rd,Rs add Rd,Rs,0 ;with Rd,Rs in range r0-r7 each
Look at the 1st like.
The document tells me that, in THUMB Asm, nop = mov r8,r8. I just followed
what it said :)
And that's how I use 46C0, because it means "MOV R8, R8".
--------------------
To check that everything will be allright, select "Tools" then "Memory
Viewer". Choose "16 bits", then enter the address "0802c63c". Type 46C0
(that'll patch the game "on the fly"), then use the
blue orb within the game : it's quantity won't decrease.
So the raw AR V1/2 code could be :
6401631D 000046C0
- We could also try to find the line where the games decrease the quantity of
blue orbs, and remove it.
The only way in THUMB asm to decrease a number is to subtract 2 values. So we
need to find a instruction
that looks like "sub rx, ry" (x and y being 2 numbers) or "sub rx, #0xYY" (YY
being a number).
- Go back to VBA (normal), and go up one line until you find the "sub"
instruction (shouldn't be hard to find :) ).
If you create a code that NOOP this line, the quantity of blue orb will never
decrease.
- Even funnier. We could change this line with an instruction that does anything
else to the value !
For exemple, we could put any number we want (between 0 and 255).
Or we could increase the number instead of decreasing it !
Let's look at it to have some fun... :)
- Lets say you want to set the quantity of blue orb to 255 ($FF) when the player
uses it.
1st, look at the precise instruction of line 0802c638 (where the "sub"
instruction lies).
You see : 3801 sub r0, #0x1
This instruction means "Remove 1 from the value stored in r0".
- In asm, the instruction that put a number in a register is called MOV (=move).
To set the quantity of blue orb to 255, we need to change the instruction to :
mov r0,#0x255
You could try to find how to create the MOV instruction in hexadecimal in the
gbatech documents...
But MOV is one of the easier instructions to learn, and you can find it very
easily by yourself.
To create a MOV in hex, do this :
- Put a "2" at the start.
- Then put the # of the register you want to write to. We want to write to
register 0. That makes "20"
- Now put the value you want to write (in hexadecimal). 255 is $FF. The hex
code will be "20FF".
To check that everything will be alright, select "Tools" then "Memory
Viewer". Choose "16 bits",
then enter the address "0802c638". Type 20FF (that'll patch the game "on the
fly"), then use the
blue orb within the game. The 1st time you use it it'll be "normal", then
it'll be "powerful" (because it's
quantity/power will be 255). The code is working :)
(btw : the gfx will be messed up because the max value of the blue orb should
be 2).
- Now let's say you want to add 1 to the quantity of blue orb each time the
player uses it.
We need to change the "sub" instruction to an "add" instruction. Look at the
GBA tech document.
Click on "THUMB Instruction Set", then click on "THUMB.3:
move/compare/add/subtract immediate".
You'll see that :
Opcode Format
Bit Expl.
15-13 Must be 001b for this type of instructions
12-11 Opcode
00b: MOV Rd,#nn ;move Rd = #nn
01b: CMP Rd,#nn ;compare Void = Rd - #nn
10b: ADD Rd,#nn ;add Rd = Rd + #nn
11b: SUB Rd,#nn ;subtract Rd = Rd - #nn
10-8 Rd - Destination Register (R0..R7)
7-0 nn - Unsigned Immediate (0-255)
ARM equivalents for MOV/CMP/ADD/SUB are MOVS/CMP/ADDS/SUBS same format.
Execution Time: 1S
Return: Rd contains result (except CMP), N,Z,C,V affected (for MOV only N,Z).
- Start to look at the "Opcode" lines. You have :
00b: MOV Rd,#nn ;move Rd = #nn
01b: CMP Rd,#nn ;compare Void = Rd - #nn
10b: ADD Rd,#nn ;add Rd = Rd + #nn
11b: SUB Rd,#nn ;subtract Rd = Rd - #nn
- This is what we need : ADD Rd, #nn. Rd will be R0, and #nn will be 1.
- Now open 2 windows calculator in scientific mode. Choose "bin" for the first
one, and "dec" for the second one.
- Lets start to create the instruction :
Bit Expl.
15-13 Must be 001b for this type of instructions
+ That means you have to type "001" in the first windows calculator (the 1st 0es
won't appear).
12-11 Opcode
00b: MOV Rd,#nn ;move Rd = #nn
01b: CMP Rd,#nn ;compare Void = Rd - #nn
10b: ADD Rd,#nn ;add Rd = Rd + #nn
11b: SUB Rd,#nn ;subtract Rd = Rd - #nn
+ We want the "ADD" instruction, so you have to enter "10" in the first windows
calculator (it'll show "110").
10-8 Rd - Destination Register (R0..R7)
+ Destination register will be R0 (which means "0"). So type "000" (for bits 10,
9 and 8) in the first windows
calculator (it'll show "110000").
7-0 nn - Unsigned Immediate (0-255)
+ Now enter the value you want to add in the second windows calculator ("1"),
then click on the "bin" button.
It'll show "1". So type "00000001" (for bits 7-0) in the first windows
calculator
(it'll show "11000000000001").
+ Choose "hex" in the 1st windows calculator, and it'll show "3001". It's the
hexadecimal form of "ADD r0, #0x1".
To check that everything will be allright, select "Tools" then "Memory
Viewer". Choose "16 bits",
then enter the address "0802c638". Type 3001 (that'll patch the game "on the
fly"), then use the
blue orb within the game : the more you use it, the more powerful it'll
becomes. The code it working !
ASM GBA Hacking - 2nd Part Example #1 - Item Never Decreases
You'll need :
either to install MAPPY VM :
http://www.bottledlight.com/tools/mappyvm_0.9d.zip
or
to get a good hexeditor (I use Winhex).
- Now let's try to find something way more difficult : a code that will make the
game think you always have the blue orb. Use the dissassembler of VBA (normal),
and go back at the that was subtracting the blue
orb value (0802c638).
- Scroll up the lines until you find an instruction "bl..." or "bx...".
You'll find a "bl $08040c44" at line 0802c5f8.
Look at the line just under this one : 0802c5fa.
- Use VBA sdl (load the game, the save state, press F11) and type "bt 0802c5fa".
Type "c", then use the blue orb : the game will freeze.
- Now the tricky part. You know where you are, but you don't know where you came
from (and we need to find that out).
There are a lot of way to find out where you came from, so I will only explain
the way that works for Iron Man.
- Press "n" and look at all registers until you find something interessing.
After about 27 "n", you'll see "0202ccf4" in R1...! It's the address of the
blue orb quantity!
- Now look at the line just up. (0802c634) :
441 add r1, r8
- That means the game computed the value 0202ccf4 by doing r1 = r1 + r8. Now
look at the values of r1 and r8 for
the line 0802c634 : R01=000001f4, R08=0202CB00
- That means that 0202CB00 is something like the base address for all the blue
orb quantities addresses, and 1f4
is the "modifier" than, once added to 0202CB00, gives the blue orb quantity
address for this particular level.
*If you use MAPPY !
- Now launch MAPPY VM, and load the Iron Man rom with it.
- Then make "File", "Export dissassembly". Change "ARM" to "THUMB",
enter "08000000" in the middle input box,
and enter "200000" in the input box close to "THUMB". Click "Add",
then choose a destination
(click the "..." button), and finally click "OK". Now open the file
that has been created in wordpad.
- Search "0202CB00". You'll find nothing :(... That's not a big deal.
Look back in VBASDL dos window.
Scroll up, until you see that R01 value is different to 000001f4, and
look the line just above.
- You'll see that :
0802c630 21fa mov r1, #0xfa
0802c632 0049 lsl r1, r1, #0x1
- Translate $fa to decimal (gives 250), then go back to worpad, and
search "mov r1, #250".
- You'll find :
0802B2EE mov r1, #250
0802C630 mov r1, #250
0802CDD4 mov r1, #250
- As you can see, we already know for the second line (0802c630). So the
place where the game checks
that you have enought blue orb must be either near 0802b2ee, or 0802cdd4.
*If you use Winhex!
- Open the rom file in winhex.
- Search this hex value : "00CB0202" (= 0202CB00 reverted). You'll find
nothing :(... That's
not a big deal.
- Look back in VBASDL dos window. Scroll up, until you see that R01
value is different to 000001f4,
and look the line just above.
- You'll see that :
0802c630 21fa mov r1, #0xfa
0802c632 0049 lsl r1, r1, #0x1
- Take the 21fa and the 0049, and write them like this : fa214900. Seach
this number in winhex.
- You'll find one at 2B2EE, one at 2C630 and one at 2CDD4. Add 08000000
to these numbers to convert them into addresses. That gives :
0802B2EE
0802C630
0802CDD4
- As you can see, we already know for the second line (0802c630). So the
place where the game checks that you have enought blue orb must be either near 0802b2ee, or
0802cdd4.
- Go back to VBASDL. Quit the game (press esc if you are in the game, or type
"q" then "y" in the dos window).
- Reload the game and the save state, use the blue orb power (so you have none
left), press F11,
then type "bt 0802b2ee", "bt 0802C630", "bt 0802cdd4", then "c".
- Use the blue orb power : then game will freeze, and you'll be at address
0802b2ee. As you don't have any
blue orb power left, that means we found the place where the game will check
if you have one left...
- Press "n" 5 times. You'll see that :
0802B2EE 21fa mov r1, #0xfa
0802B2F0 lsl r1, r1, #0x01
0802B2F2 add r0, r4, r1
0802B2F4 ldr r0, [r0,#0x0]
0802B2F6 cmp r0,#0x0
0802B2F8 ble $0802b2fc
- The three 1st lines will "create" the value 0202CFF4 in R0.
- The fourth line load the value that is in the address stored in R0 to R0 (that
mean it'll load the quantity
of blue orb you have to r0).
- The fith line compare this value to 0. And the last line will jump to address
0802b2fc if the result of
the comparison is "less or egal".
- So we have different choices to make the game think you always have the blue
orb :
+ We could change the "ldr r0, [r0, #0x0]" to something like "mov r0, #0x1" or
"mov r0, #0x2".
Then the result of "cmp r0, #0x0" will always be false... The only problem is
that this doesn't let you choose
which power you use...
+ So I'll use a trick. I'll change the instruction that read the blue orb
quantity with an instruction that writes
to the blue orb quantity. And as the content of r0 won't be destroyed by my
instructions, it'll stay "0202CCF4",
and when the game will compare it to 0 (thinking it's the quantity of blue
orb), it'll always find that it is
superior to 0, hence it'll think I always have blue orbs...
The hard part is that you can't do much with only one asm instruction. You can
only use something like "str Rx, [Ry, #0xZZ]".
That means you can't choose the value you will write, and the address where you
want to write HAS to be in in the registers
(and btw in THUMB we can only access registers 0-7 directly!)
Hopefully, this is the case : R0 has the address of the blue orb values.
Now I need to find what value I'm going to write. Let's look at the registers
R0-R7 (the only one we can use) for line 0802D2F4 :
R00=0202ccf4 R04=0202CB00
R01=000001f4 R05=00000000
R02=00000200 R06=00000000
R03=0802e615 R07=0202CBD4
R00 is the address for the bue orb quantity for this level. We'll write there,
but we can't use this as the value we'll write,
because it'll change for every level (we won't have a stable result).
R01 and R04 are "linked" to R00 (R01+R04=R00). So here too, we can't use them
as the value we'll write,
because it'll change for every level (we won't have a stable result).
R03 could be safe (not change with the level). Same thing for R05 and R06.
R07 seems close to R04 (R07=R04+$D4), which means it might change with the
levels, and won't give a stable result.
+ We can use, as data : R03=0802e615, R05=00000000, R06=00000000. R05 and R06
are 0es. If we write 0es to the blue orb
quantity, the game will launch the 1st power. And R03 is >1, so writing this
value to the blue orb quantity will make
then game launch the 2nd power (I discovered this by testing the values).
+ So we'll create 2 instructions :
str r5, [r0, #0x0] (that will write the value of register r5 at address r0+#0x0)
and
str r3, [r0, #0x0] (that will write the value of register r3 at address r0+#0x0)
+ Lets look at the GBA tech documents. Click on Click on "THUMB Instruction
Set", then click on
"THUMB.9: load/store with immediate offset". You'll find that :
Opcode Format
Bit Expl.
15-13 Must be 011b for this type of instructions
12-11 Opcode (0-3)
0: STR Rd,[Rb,#nn] ;store 32bit data WORD[Rb+nn] = Rd
1: LDR Rd,[Rb,#nn] ;load 32bit data Rd = WORD[Rb+nn]
2: STRB Rd,[Rb,#nn] ;store 8bit data BYTE[Rb+nn] = Rd
3: LDRB Rd,[Rb,#nn] ;load 8bit data Rd = BYTE[Rb+nn]
10-6 nn - Unsigned Offset (0-31 for BYTE, 0-124 for WORD)
5-3 Rb - Base Register (R0..R7)
2-0 Rd - Source/Destination Register (R0..R7)
Return: No flags affected, data loaded either into Rd or into memory.
Execution Time: 1S+1N+1I for LDR, or 2N for STR
+ We need to use the 1st opcode, "0: STR Rd,[Rb,#nn] ;store 32bit data
WORD[Rb+nn] = Rd"
+ Open the 1 windows calculator, and click on "bin".
15-13 Must be 011b for this type of instructions
-> Type "011" (calculator will show "11")
12-11 Opcode (0-3)
0: STR Rd,[Rb,#nn] ;store 32bit data WORD[Rb+nn] = Rd
-> Type "00" (calculator will show "100")
10-6 nn - Unsigned Offset (0-31 for BYTE, 0-124 for WORD)
-> Type "00000" (calculator will show "11000000")
5-3 Rb - Base Register (R0..R7)
-> R00 is the base register : type "000" (calculator will show "11000000000")
2-0 Rd - Source/Destination Register (R0..R7)
-> R05 will be the source register. 5 is 101 in binary, so type in "101"
(calculator will show "11000000000101")
+ Now click on the "HEX" button, and the calculator will show "6005". This is
the hex value of the instruction :
str r5, [r0, #0x0]
+ Redo these steps to create the second instruction, but at the end enter "011"
for R03.
The hex value will be "6003", which is the hex value for :
str r3, [r0, #0x0]
Now you just have to create the V1/2 raw codes using the address 0802d2f4 and
these values 6005 and 6003.
1st code :
6401597a 00006005
2nd code :
6401597a 00006003
We could also use a joker code to select which power to use. In GBA, all the key
events are stored
at address $04000130.
Go back to VBA (normal), open the memory editor, select 16 bits, and go to the
address 04000130.
Check the "Automatic Update" box.
The first number will be 03FF.
Now press start. The number will change to 03F7.
Let go start, and press select. The number will change to 03FB.
That means we can create our codes that way :
D4000130 000003F7 ( = "If the value at 04000130 if equal to the 03F7 (= start
button pressed), execute the next code")
6401597a 00006005
D4000130 000003FB ( = "If the value at 04000130 if equal to the 03FB (= start
button pressed), execute the next code")
6401597a 00006003
Here is the V3 version of it (it's working, I tested it myself!) :
4A400130 000003F7
00000000 1801597A
00006005 00000000
4A400130 000003FB
00000000 1801597A
00006003 00000000
Explanations on Type 6 ('rom patching') Codes
Start the game, and press L : nothing will happen, because you don't have blue
orbs.
Now press Start (twice to exit the menu). The code 6401597a 00006005 will be
executed.
Press L : Iron Man will always use his 1st power.
Here is how it works :
The code will make the AR write the values 0401597a and 6005 at the special
place in the action replay.
I'll call this place the 'rom patching register'.
Then a special chip, called the 'FPGA' (thanks to Parasyte for the info), will
"patch"
the address 0802b2f4 (=2*0401597a) with the value 6005.
That will replace the instruction 'ldr r0, [r0,#0x0]' with 'str r5, [r0, #0x0]'.
Now the trick with the Type 6 codes (or rom patch codes) if that they are always
active,
until another code "erase" them (change the value of the 'rom patching
register').
That's why if you press Select, then L, Iron Man will always use his 2nd power.
Because the code 6401597a 00006003 will write the values 0401597a and 6003 to
the 'rom patching register'.
It'll replace the old '6005'. That means that now the 'FPGA" patches the address
0802b2f4 wirh the value '6003'
That will replace the instruction 'ldr r0, [r0,#0x0]' with 'str r3, [r0, #0x0]'.
One of the conclusion of this last explanation is that Type 6 codes are really
unlike the other one.
They need to be excuted only ONCE to be active until something changes the value
of the 'rom patch register'.
Finally, here is something even better (only for v3) :
1st set of codes:
48400131 00000003
(insert your invincibility
code, raw v3, here)
2nd set of codes:
4A400130 000001FF
00000000 1801597A
00006003 00000000
3rd set of codes:
4A400130 000001BF
00000000 1801597A
00006005 00000000
Here is what will happen during the game :
1st set of codes:
If the 8 bits value at address 04000131 if egal to 03 (= if you don't press L or
R),
the invincibility code will be enable.
2nd set of codes:
If the 16 bits value at address 04000130 if egal to 1FF (= if you press L),
Iron Man will use its 2nd power.
3rd set of codes:
If the 16 bits value at address 04000130 if egal to 1BF (= if you press Up and
L),
Iron Man will use its 1st power.
I know this is a bit useless on a 'real AR V3', that should handle multiple rom
patching codes.
But on an AR2 upgraded to AR3, that can not handle multiple rom patching codes,
it can be really
useful.
Finally, it's kinda hard to make this exact codes for AR2, because AR2 doesn't
handle the
'If the 8bits value...' type of code. Only the 16bits value.
So to make a code that is activated if you don't press L or R, you'll have to do
a lot of codes,
like that :
D4000130 00003FF (if no button are pressed)
(invincibility code)
D4000130 00003EF (if only Right is pressed)
(invincibility code)
D4000130 00003DF (if only Left is Pressed)
(invincibility code)
...
That means you have to write one set of code for every key combinaison you want
the invicibility
to be active... Usually, that means : no button, Up, Down, Left, Right, A, B.
But you could also create code for Up+A, Down+A, Left+A, Right+A, Up+B, Down+B,
Left+B, Right+B...
For this exemple, you could have to write 30 lines of codes to have the desire
effect.
And you could also want to write codes for Up+Right, Down+Right... Or
Up+Right+A... !
That could make up to 64*2 lines of codes, for something that is handled in 3
lines with the AR3 !
It's really stupid... So AR V3 rules ! :)
note:
BTW for assistance in making activator codes, the value of the GBA buttons are this:
at address 04000130, just remember to replace the first zero with D, that is D40000130.
So for an activator calling A D40000130 000003FE. Here are the other values.
Button A - 03FE
Button B - 03FD
Button L - 01FF
Button R - 02FF
Start - 03F7
Select - 03FB
Up - 03BF
Down - 03EF
Left - 03DF
Right - 037F
No buttons pressed - 03FF
All buttons pressed - 0000
For other combos just use the normal VBA. Load VBA, load any game, halt game, open mem viewer,
goto address 04000130 at 16 bits, choose auto update, then start pressing buttons
and hold and watch the value change.
ASM GBA Hacking - Example #2 - Invincibility
Using Break Point Read (bpr) to find Invincibility (from IronMan GBA level 1)
We will assume the reader has a basic knowledge of hacking health codes in the
normal code generator of VBA.
We will also assume we have found the code for infinite health for level 1 which
is 020200ed 00000064. We will also assume the reader has already saved a slot
for level 1 for ease on hacking the code at hand. (The reader will be required
to reset the game in the normal VBA several times in the exercise to follow.)
Now it is told to the reader to take on faith that using a break on read is
easier to find than a break on write. It is also to be made clear that a study
of ASM thumb calls is mandatory to understand to get anywhere in using SDL VBA
as a tool in hacking codes. This study is not done overnight but will be an
ongoing journey which if done with dedication will
reward the reader with the ability to hack some very cool codes.
The goal here is to find an address that will "kill" the call of IronMan losing
health and replace it with
an address that will trick the game into thinking nothing is happening to
IronMan and hence becoming
invincible. The reader is to understand that he will need to have both the SDL
and normal versions of VBA on hand and will use both programs to hack the code shown.
To begin we drag the IronMan rom over to the SDLk.exe file. This will
start the SDL VBA graphics screen and the Dos Window that will be used
to type commands and view call results. A special adaptation that must be used
in this example is SDL VBA 1.4.1 with bpr support. The authors will not
support the reader in obtaining the rom and leave the reader to his own devices
for doing so.
Next we enter the 1st level of the game...
So load the game, enter the 1st level, and press F11 to enter the debugger.
Now we type bpr 020200ed 1 (this is the address where the health is stored, and
the health takes one byte.
Now type c and resume the game. Now let IronMan take a hit.
The game will freeze and yield the following info
in the Dos Window of SDL VBA. "080399da 9200 str r2, [sp, #0x0]"
which is called when IM is hit. (IM = IronMan)
Next open the normal VBA program now. Do not close the SDK VBA.
Then open the dis-assembler on the tool bar and go to address "080399da", and
check the thumb button.
This address is the same we found when called in SDL VBA when IM got hit.
Leave the debugger window open.
Now also open the memory editor of vba (normal), select 16 bits and go to
"080399da" address too.
Now look at the dis-assembler of the normal vba, and scroll up one line
you see "Ldr r2, [r4, #0x0]".
That's where the break on read happened.
And that's where the game loads your life from memory.
Now look back at SDL VBA, after the break on read
you see r0=0, r1=03007c90, r2=00006400 (= your life), r3=0, r4=020200ec
(= address where the life is stored in memory),
r5=02020ff4...
What we'll try to do is to make the program not load your life value as it would
normally and replace it with another value. The way we'll do this is to take the
value in r4, and put it in r2.
Value in r4 is the address where your life is stored, and will always be a "big
number", so it should make you invincible.
So go back to the memory editor of normal vba, go to address 080399d8, and
change the value to 1c22. This is the same as "mov (r2, r4)", which means it'll
put the value of r4 in register r2 (instead of loading IM HP to r2).
Once it's done, play a bit of the game in vba normal...at this point you will
observe that both IM and the enemy are invincible. The code is working, but not
the way we want. That's because at this address, the choice between "enemy HP"
and "IM HP" has already be done, and the game is just executing a "script" that
remove the damages to the HP. So we need to go "back" to find the place
where the choice between "enemy is hit" and "IM is hit" is done (and we'll try
to make the game never choose "IM is hit").
Go back to SDL VBA, and type "last", now type "c", and get hit again you'll see
a lot of registers now.
Look at the first R15 = 08000838
R15 is VERY important. It'll ALWAYS is the address of the VERY NEXT INSTRUCTION
that will be executed. When you know R15, you know the address you are at.
So before going to 080399da, the game was something near 08000838 (I say
somewhere near because the "last" call is a bit buggy. it doesn't give the
real r15, but a value close to it).
So look at address 08000838 in the dis-assembler of normal vba.
Scroll a bit up until you find a "bl", a "bx" or a "mov pc, ..." and you'll see...
"bl $080399c8".
Ok, that's where the program jumps to 080399c8, which is near the place where
the break on read happened.
Now scroll up in vba dis-assembler, until you see a "bl ..", a "bx .."
or a "mov pc, ...".
that will be "0800820 bl $08049880"
now look at the instructions between the 2 bl's
(between 08000820 and 08000832), and find any "cmp".
You'll see "0800082a cmp r6, #0x0", and after that "0800082c beq $08000830".
That means that the game will compare the value of R6 and 0. And if they are equal,
it'll jump to the address 0800082c.
Now open the memory editor of vba normal, go to the address 0800082c (the
address of the beq), and change the value to d100, also reset the game and
reload level 1 save. This will change the "beq" (= if equal) to
"bne" (= if not equal)).
So once you've changed the value to d100, play a bit the game, and see what
happens. You'll see that neither you nor the enemies are invincible... This is
not a good choice to set the code we want. Go back to vba dis-assembler,
and go back to address 08000820 (the 2nd bl we found).
So do the same thing as before from 08000820, scroll up until you
find a "bl ..." (or a "bx ...", or a "mov pc, ..."), then scroll down until
you find a "cmp".
You will see a "cmp" at 0800080c
and under if, at 0800080e, you'll see "beq ...".
So go back to the memory editor, go to address 0800080e, and change
"d0.." to "d1.."
Remember to reset the game and then reload level 1. Now play the game and
observe that IM is now invincible but the enemies die. This is what we had
set out to do!
Although the reader would expect the hack is done and the code determined we
must advise that we are "almost there"�
Because changing d0 to d1 isn't good enough. It only "inverts" the condition
("if equal" becomes "if not equal"). It could seem good, but it may create some
bugs (for example, if an enemy was hit, IM could loose its HP). I know it's not
the case, but you never know what can happen. We need to create something that
is "always true", so chances of bug will be 0%. That's what we'll do in the
following lines.
To be 100% sure the code is working, we'll do it another way.
above the "beq", you see :
lsl r0, r0, 18
then
cmp r0, #0x0"
what we want, is either the cmp r0, #0x0 to be always true, or to be always
wrong (we don't know that yet), so that the "beq" (=if equal) always
(or never) executes.
"lsl r0, r0, #0x18" is not an important operation. It'll shit the value of
r0 #0x18 bits to the left (00000001 becomes 01000000). That mean we can edit
it to create our code.
We'll start to change the "lsl r0, r0, #0x18" with "mov r0, #0x0" (we do that
to make the "cmp r0, #0x0" always true).
So go to address 0800080a in the memory editor, and change 0600 with
2000 (= mov r0, #0x0).
Note about creating a simple MOV code :
2 0 00 : 2 = MOV ; 1st 0 is the destination register (0 to 7);
2nd and 3rd zeroes are the values (0 to FF).
So 25FF is "mov r5, #0xff"
2365 = "mov r3, #0x65"
and 2000 = "mov r0, #0x0"
-Reset the game and reload level 1.
It should make you invincible, and only the enemies will die.
So we have your code : put 2000 at address 0800080a
And the "raw rom patch code" is :
0800080a 00002000
Question : why do we have to go up some lines in the dissassembler?
Answer : because, as you saw, the very first code we found
(with the break on read) makes the player and the enemies invincible.
That means, the choice between enemies HP and player HP is made before
this place So we have to backtrack from the place the break on read happened.
That's why we kept going up in the addresses but the search down the chain
is the same.
So the rule is to repeat the search inspection as noted until we find a stable
address to do exactly what we wanted in the first place. The reader might be
thinking that this is a lot of work. The motivation for using. This method is
simple. You see, in IronMan the health code changes in address from level to level.
This means you would have to hack a unique code for each level.
Tedious at best and boring at worst in actually using the codes to play the game.
The ASM method gets to the heart of the problem by finding the address that holds
the true call on IronMan health and this one code is good for all levels.
The added plus is that IronMan is more than with inf. health...the code make him invincible.
That is, HP never decrease!
We hope these 2 examples serve as a beginning for the reader to explore further
the endless possibilities and power of ASM hacking for GBA and indeed in
any ASM hacking process for any platform.
G) Hacking with the ProAction Replay/GameShark PRO 3.0 for Game Boy
-submitted by Curly8od
How To Hack For Action Replay Pro For Gameboy
Table of Contents
Inf Lives 1
Inf Ammo 2
Inf Money 3
Have an Item 4
Walk through walls 5
Capture The Pokemon You Want 6
All Weapons 7
Bullet Mod 8
Character Mod 9
Cut Scene Mod 10
Activate In Game Cheats 11
Text Mod 12
Some F.A.Q 13
Updates Since version 1.2
Added How To Hack Character mod,Cut Scene Mod And Activate In Game Cheats
Added another question in the F.A.Q
1.
Inf Lives
Step 1:Start the game and as soon as you can move press the button on
top of the action replay
Step 2:Select code gen
Step 3:In code gen select start generator
Step 4:Start the game and lose a life
Step 5:Press the button on the action replay. Go to code gen and select
less and a number will appear at the bottom
Step 6:Do step 1 again then select code gen
Step 7:Select greater than a number with maybe letters will appear.
They mean: 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8 9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15
Step 8:Keep on doing steps 4-7 until you get 10 or less
Step 9:Go to view cheats and write down the number of codes you got
closest to ten
Step 10:Try the codes
2.
Inf Ammo
Step 1:Start the game and as soon as you can move press the button on
top of the action replay
Step 2:Select code gen
Step 3:In code gen select start generator
Step 4:Start the game and use some ammo
Step 5:Press the button on the action replay. Go to code gen and select
less and a number will
appear at the bottom
Step 6:Do step 1 again then select code gen
Step 7:Select greater than a number with maybe letters will appear.
They mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8 9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15
Step 9:Go to view cheats and write down the number of codes you got
closest to ten
Step 10:Try the codes
3.
Inf Money
Step 1:Start the game and as soon as you can move press the button on
top of the action replay
Step 2:Select code gen
Step 3:In code gen select start generator
Step 4:Start the game and spend some money
Step 5:Press the button on the action replay go to code gen and select
less and a number will
appear at the bottom
Step 6:Do step 1 again then select code gen
Step 7:Select greater than a number with maybe letters will appear.
They mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8 9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15
Step 9:Go to view cheats and write down the number of codes you got
Closest to ten
Step 10:Try the codes
4.
Have An Item
Step 1:Start the game and as soon as you can move press the button on
top of the action replay
Step 2:Select code gen
Step 3:In code gen select start generator
Step 4:Start the game and as soon as you can move press the button on
top of the action replay
and go to code gen and select less and some numbers will apear
Step 5:Then start the game again and get the item that you want then
press the button on the
action replay
Step 6:Go in to code gen and select greater than. go to view cheats and
write down 15 codes
Step 7:Try the codes you wrote down
5.
Walk Through Walls
Step 1:Start the game and as soon as you can move press the button on
top of the action replay
Step 2:Select code gen
Step 3:in code gen select start generator
Step 4:Start the game and move one step then press the button on the
top of the action replay
Step 5:Select less then a number with maybe letters will appear. They
Mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8 9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15
Step 6:Keep on doing steps 4-5 until 10 codes or less are found
Step 7:Go to view cheats and write down how many codes were found
Step 8:Try the codes
6.
Capture The Pokemon You Want
Step 1:Start the game and as soon as you can move press the button on
top of the action replay
Step 2:Select code gen
Step 3:In code gen select start generator
Step 4:Start the game and get in a wild battle with the pokemon you
want then press the button on top of the action replay
Step 5:Go to code gen and select less then a number with maybe letters
will appear thy mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8 9=9 0=0 a=10 b=11 c=12 d=13
e=14 f=15
Step 6:Keep on doing steps 4-5 till you get about 10 codes found
Step 7:Go to view cheats and write down how many codes were found
Step 8:Try the codes
7.
All Weapons
Step 1:Start the game and get a weapon then press the button on top of
the action replay
Step 2:Then go to code gen and select start gen then start the game
again and get a different
weapon
Step 3:Press the button on the action replay and go to code gen and
select different
Step 4:Start the game again and get the same weapon as last
Step 5:Then press the button on the action replay and select different
and numbers with maybe letters will appear they mean
1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8 9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15
Step 6:Keep on doing steps 4-5 until around ten codes are found
Step 7:Then view cheats and write down how many codes were found
Step 8:Try the codes you wrote down!
8.
Bullet Mod
Step 1:Start the game and as soon as you can move press the button on
top of the action replay.
Step 2:Select code gen.
Step 3:In code gen select start generator.
Step 4:Start the game again and get a gun and fire it then press the
button on the top of the action replay.
Step 5:Go to code gen and select different.
Step 6:Start the game again and get a different weapon then fire some
bullets the press the button
on the top of the action replay and go to code gen and select different
and some numbers maybe letters will appear they mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7
8=8 9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15.
Step 7:Keep on doing steps 4-6 till around ten codes are found.
Step 8:Go to view cheats and write down how many codes where found.
Step 9:Try the codes!.
9.
Character Mod
Step 1:Start the game and as soon as you can move press the button on
top of the action replay.
Step 2:Select code gen.
Step 3:In code gen select start generator.
Step 4:Start the game again and change charcter and press the button on
the top of the action replay
and go to code gen
Step 5:Select same and some numbers maybe
letters will appear they mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8
9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15.
Step 6:Start the game and chose a different character then press the
button on the action replay
and go to code gen
Step 7:Select different and some numbers maybe
letters will appear they mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8
9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15.
Step 8:Keep on doing steps 4-7 until around 10 or less codes are found
Step 9:Go to veiw cheats and write down how many codes where found
Step 10:Try the codes!
10.
Cut Scene Mod
Step 1:Start the game and as soon as you can move press the button on
top of the action replay.
Step 2:Select code gen.
Step 3:In code gen select start generator.
Step 4:get in to a cut scene and then press the button on top of the
action replay and go to code
gen and select different. Some numbers maybe
letters will appear they mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8
9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15.
Step 5:Play the same cut scene and press the button on the top of the
action replay. Go to code gen
and select Equal. Some numbers maybe
letters will appear thay mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8
9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15.
Step 6:Dont play a cut scene and press the button on the top of the
action replay. Go to code gen
and select different. Some numbers maybe
letters will appear they mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8
9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15.
Step 7:Keep on doing steps 4-6 until around 10 codes are found.
Step 8:go to view cheats and write down how many codes where found.
Step 9:Try the codes!
11.
Activate In Game Cheats
Step 1:Start the game and as soon as you can move press the button on
top of the action replay.
Step 2:Select code gen.
Step 3:In code gen select start generator.
Step 4:start the game again and put a code on and press the button on
the action replay. Go to
code gen and select greater. Some numbers maybe
letters will appear they mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8
9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15.
Step 5:start the game again and don't put a code on then press the
button on the top of the
action replay and go to code gen and select less and Some numbers maybe
letters will appear they mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8
9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15.
Step 6:Keep on doing steps 4-5 until around 10 codes are found.
Step 7:Go to view cheats and write down how many codes where found.
Step 8:Try the codes!
12.
Text Mod
Step 1:Start the game and as soon as you can move press the button on
top of the action replay.
Step 2:Select code gen.
Step 3:In code gen select start generator.
Step 4:Start the game again and talk to some one then talk to someone
different and press the button on the top of the action replay
Step 5:Go to code gen and select different and some numbers maybe
letters will appear they mean 1=1 2=2 3=3 4=4 5=5 6=6 7=7 8=8
9=9 0=0 a=10 b=11 c=12 d=13 e=14 f=15.
Step 6:Keep on doing steps 4-5 untill you have 10 or less codes!
Step 7:Try the codes!
13.
Some F.A.Q
Q. What Dose A Bullet Mod Do
A. Changes The Type Of Bullets Like If I Had A Shotgun And I Wanted It
To Shoot Pistol Bullets.
Q. Where Do I Find The Numbers And maybe Letters.
A. At The Bottom Of The Screen In Code Gen Your Action Replay Will
Freeze While You Press The Button And Then Numbers With Maybe Letters Will Appear
At The Bottom.
Q. What do the numbers and maybe letters tell you?
A. How many codes where found.
Credits: Omegakid,Pichu
Written by Aaron
Nickname curly8od
Email [email protected]
Version 1.3
Official site www9.50megs.com\curly8od
------------------------------------------------------------------------
F) Online code porter
You can convert a code from one version of the game by knowing the
difference in offsets one version of a game has from another version. Please
see the FAQ section for more info on how to do this. GSCentral has an
automatic code porter that the reader is welcome to try. The authors would
like to thank Crocc for permission to use the code porter found at GSCentral
www.gscentral.com/port.pl
| Name | Description | Author |
| GSCC2k2 | Game Software Code Creator 2002 supports both N64 and PSX Gameshark Pro, older PSX GS versions, and Caetla. Has tons of options including Breakpoints (N64). | CodeMaster |
| Float Convert | Used for converting 32-Bit hex values to IEEE-754 Floating Point and vice versa. | ??? |
| Patch Code Unpatcher v1.1 | Expands N64/PSX Patch ('50') codes. | Viper187 |
| Gameboy/Gameboy Advance Utilities | ||
| ARCrypt Final 2_2 | Gameboy Advance Gameshark & AR code encryptor/decryptor | Kenobi & Parasyte |
| CBA Crypt | Gameboy Advance Codebreaker code encryptor/decryptor | Parasyte |
| Gamecube Utilities | ||
| GCN Crypt v1.2 | Encrypt/Decrypt Gamecube Action Replay Codes! | Parasyte |
| GCN AR Code Type Helper | Puts codes into proper decrypted AR format for you. | Parasyte |
| Playstation 2 Utilities | ||
| PS2DIS 0.99 | PS2 Disassembler, used for finding codes via SLUS files | Hanimar |
| PS2 Code Decoder - Beta 2 | Code Encryptor/Decryptor | iN tHE mIND |
| MAXcrypt v1.0 | Encrypts/decrypts Action Replay MAX codes | Parasyte |
| N64 Utilities | ||
| Official N64 Hack Utilities 3.2 | The official PC tools for GS Pro 3.2 | Datel |
| Official N64 Hack Utilities 3.3 | The official PC tools for GS Pro 3.3 | Datel |
| N64 Utils Patch | N64 Utils patch that allows dumping ROM. | ??? |
| RAM Compare v1.2 | DOS app for comparing RAM dumps that you can get from certain N64 emulators. | The Phantom |
| Byteswap v1.0 | Can convert Project64 save state files to regular RAM dumps. They must be .pj (uncompressed) save states! | The Phantom |
| VTR Compare 0.99 Beta | Viper's Text Ram Comparer uses text format RAM dumps from Nemu64 for searching comparisons. This baby has options even GSCC2k2 doesn't :) | Viper187 |
| RAM 2 Text v1.0 | Converts normal RAM dumps to text format for use with VTR Compare. | Viper187 |
| Cheater64 v2.1 | This is about the best comparer for hacking N64 with emulators thus far. It supports RAM dumps and PJ64 save states. | Viper187 |
| Niew | Assembler/Disassembler (DOS) typicly used for ASM hacking - COP1 instructions aren't supported. | Titanik |
| LemAsm | Assembler/Disassembler - Windows - supports COP1 Instructions | Lemmy |
| R3400i Documentation | Wanna learn N64 Assembly language? | N/A |
| Xploder64 | Official upgrade/codelist Utils for Xploder64 | Fire International |
| GSProN64Crypt | A program that can decompress the .enc (GS ROM) file included with the official utils. | CodeMaster |
| Goldeneye 007 Target Time Calc v1.0 | Use to calculate values for Wreck7's 'target time modifiers' on Goldeneye. | Viper187 |
| Nemu | Nintendo 64 emulator | nemu |
| Nemu INI (Alternate) | Unofficial INI file for Nemu | ??? |
| PJ64 | Nintendo 64 emulator | PJ64 |
| PSX Utilities | ||
| Official PSX GS Pro Hack Utilities v3.20 | The official utils from Datel for use with GS Pro v3.20 or upgrading from 3.0 | Datel |
| Official PSX CDX Hack Utilities v3.20 | The official utils from Datel for use with GS CDX | Datel |
| Xplorer Button Value Calculator v1.3 | Calculates button values for Xplorer Joker Codes | ??? |
| Caetla | An unofficial cheat rom for flashing to older cheat device hardware. PC Comms Link required. | ??? |
| Undatel 3 | A program that can decompress the .enc (GS ROM) file included with the official utils. | ??? |
| Sega Dreamcast Utilities | ||
| DCCrypt | Encrypt/Decrypt Dreamcast GS codes | Parasyte |
KeyCodes: |