Hacking NDS
EnHacklopedia >> {{ #ifeq: Hacking NDS | EnHacklopedia | Index | Hacking NDS }} |
---|
Contents
Action Replay DS
Description
The first commercial DS cheat code solution, this device was developed by Datel. It supports swapping out cartridges after loading the AR software. For updating, the user may either manually enter codes or use the included proprietary USB cable that comes with the device. The user has been able to manually update codes since firmware version 1.52.
Code Types
Type | Description |
---|---|
Constant RAM Writes | |
Type 0x00 32-bit 0XXXXXXX YYYYYYYY |
Writes word YYYYYYYY to [XXXXXXX+offset]. |
Type 0x01 16-bit 1XXXXXXX 0000YYYY |
Writes halfword YYYY to [XXXXXXX+offset]. |
Type 0x02 8-bit 2XXXXXXX 000000YY |
Writes byte YY to [XXXXXXX+offset]. |
Conditional 32-Bit Code Types | |
Type 0x03 Greater Than 3XXXXXXX YYYYYYYY |
Checks if YYYYYYYY> (word at [XXXXXXX]) If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x04 Less Than 4XXXXXXX YYYYYYYY |
Checks if YYYYYYYY < (word at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x05 Equal To 5XXXXXXX YYYYYYYY |
Checks if YYYYYYYY == (word at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x06 Not Equal To 6XXXXXXX YYYYYYYY |
Checks if YYYYYYYY != (word at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Conditional 16-Bit + Masking RAM Writes | |
Type 0x07 Greater Than 7XXXXXXX ZZZZYYYY |
Checks if (YYYY)> (not (ZZZZ) < halfword at [XXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x08 Less Than 8XXXXXXX ZZZZYYYY |
Checks if (YYYY) < (not (ZZZZ) & halfword at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x09 Equal To 9XXXXXXX ZZZZYYYY |
Checks if (YYYY) == (not (ZZZZ) & halfword at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x0A Not Equal To AXXXXXXX ZZZZYYYY |
Checks if (YYYY) != (not (ZZZZ) & halfword at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Offset Codes | |
Type 0x0B Load offset BXXXXXXX 00000000 |
Loads the 32-bit value into the 'offset'. Offset = word at [0XXXXXXX + offset]. |
Type 0xD3 Set offset D3000000 XXXXXXXX |
Sets the offset value to XXXXXXXX. |
Type 0xDC Set offset DC000000 XXXXXXXX |
Adds an offset to the current offset. (Dual Offset) |
Loop Code | |
Type 0x0C C0000000 YYYYYYYY |
This sets the 'Dx repeat value' to YYYYYYYY and saves the 'Dx next code to be executed' and the 'Dx execution status'. Repeat will be executed when a D1/D2 code is encountered. When repeat is executed, the AR reloads the 'next code to be executed' and the 'execution status' from the Dx registers. |
Special Codes | |
Type 0xD0 Terminator D0000000 00000000 |
Loads the previous execution status. If none exists, the execution status stays at 'execute codes'. |
Type 0xD1 Loop execute variant D1000000 00000000 |
Executes the next block of codes 'n' times (specified by the 0x0C code type), but doesn't clear the Dx register upon completion. |
Type 0xD2 Loop Execute Variant/ Full Terminator D2000000 00000000 |
Executes the next block of codes 'n' times (specified by the 0x0C code type), and clears all temporary data. (i.e. execution status, offsets, code C settings, etc.) This code can also be used as a full terminator, giving the same effects to any block of code. |
Data Register Codes | |
Type 0xD4 Add Value D4000000 XXXXXXXX |
Adds 'XXXXXXXX' to the data register used by code types 0xD6 - 0xDB. More arithmetical/logical operations can be set using the 'NDS AR HACK #2'. |
Type 0xD5 Set Value D5000000 XXXXXXXX |
Set 'XXXXXXXX' to the data register used by code types 0xD6 - 0xD8. |
Type 0xD6 32-Bit Incrementive Write D6000000 XXXXXXXX |
Writes the 'Dx data' word to [XXXXXXXX+offset], and increments the offset by 4. |
Type 0xD7 16-Bit Incrementive Write D7000000 XXXXXXXX |
Writes the 'Dx data' halfword to [XXXXXXXX+offset], and increments the offset by 2. |
Type 0xD8 8-Bit Incrementive Write D8000000 XXXXXXXX |
Writes the 'Dx data' byte to [XXXXXXXX+offset], and increments the offset by 1. |
Type 0xD9 32-Bit Load D9000000 XXXXXXXX |
Loads the word at [XXXXXXXX+offset] and stores it in the'Dx data register'. |
Type 0xDA 16-Bit Load DA000000 XXXXXXXX |
Loads the halfword at [XXXXXXXX+offset] and stores it in the'Dx data register'. |
Type 0xDB 8-Bit Load DB000000 XXXXXXXX |
Loads the byte at [XXXXXXXX+offset] and stores it in the'Dx data register'. This is a bugged code type. Check 'AR Hack #0' for the fix. |
Miscellaneous Memory Manipulation Codes | |
Type 0x0E Patch Code EXXXXXXX YYYYYYYY |
Copies YYYYYYYY bytes from (current code location + 8) to [XXXXXXXX + offset]. |
Type 0x0F Memory Copy Code FXXXXXXX YYYYYYYY |
Use the code type D3, DC or B before to set the offset. D2 should be needed to clear the offset after the code. D3000000 XXXXXXXX FYYYYYYY ZZZZZZZZ This should copy ZZZZZZZZ bytes from offset (=XXXXXXXX in this case) to YYYYYYYY. (YYYYYYYY if fixed, no offsets are added to it). |
Code Hacks
The following codes modify the AR code handler.
As they write to a fixed address, they are not compatible with any game that uses an 'M' code (since the 'M' code changes the location of the code handler in memory).
Type | Description |
---|---|
Hack #0 | |
0xDB Code Type Fix 023FE4D8 0A000003 |
Fixes a bug in the Action Replay Code Handler. |
Hack #1 - Offset Support for Conditionals | |
Offset support: 023FE20C E5933000 No offset support 023FE20C E5903000 |
For code type 0x03 |
Offset support: 023FE224 E5933000 No offset support: 023FE224 E5903000 |
For code type 0x04 |
Offset support: 023FE23C E5933000 No offset support: 023FE23C E5903000 |
For code type 0x05 |
Offset support: 023FE254 E5933000 No offset support: 023FE254 E5903000 |
For code type 0x06 |
Offset Support: 023FE26C E1D320B0 023FE270 E1E03004 No offset support: 023FE26C E1E03004 023FE270 E1D020B0 |
For code type 0x07 |
Offset Support: 023FE290 E1D320B0 023FE294 E1E03004 No offset support: 023FE290 E1E03004 023FE294 E1D020B0 |
For code type 0x08 |
Offset Support: 023FE2B4 E1D320B0 023FE2B8 E1E03004 No offset support: 023FE2B4 E1E03004 023FE2B8 E1D020B0 |
For code type 0x09 |
Offset Support: 023FE2D8 E1D320B0 023FE2DC E1E03004 No offset support: 023FE2D8 E1E03004 023FE2DC E1D020B0 |
For code type 0x0A |
Offset Support: C0000000 00000003 023FE20C E5933000 DC000000 00000018 D2000000 00000000 No offset support: C0000000 00000003 023FE20C E5903000 DC000000 00000018 D2000000 00000000 |
For code types 0x03 - 0x06 all at once. |
Offset Support: C0000000 00000003 023FE26C E1D320B0 023FE270 E1E03004 DC000000 00000024 D2000000 00000000 No offset Support: C0000000 00000003 023FE26C E1E03004 023FE270 E1D020B0 DC000000 00000024 D2000000 00000000 |
For code types 0x07 - 0x0A all at once. |
Hack #2 - ORR/AND/ADD Codes | |
023FE424 E1833004 | Makes the D4 code type execute a 'ORR' instruction. |
023FE424 E0033004 | Makes the D4 code type execute a 'AND' instruction. |
023FE424 E0833004 | Makes the D4 code type execute an 'ADD' instruction. |
Hack #3 - Add Dx Data to Offset Codes | |
023FE424 E08AA003 | This code changes the D4 code type to make it add the Dx Data to the offset. It could be useful if the game's pointer's offset changes. |
Hack #4 - Execute Custom ASM Routines | |
023FE074 012FFF11 | This code changes the 0x0E code type to make it execute the data entered by the hacker. |
023FE074 E3520003 | Reverts code type 0x0E to normal |
023FE074 012FFF11 EXXXXXXX 00000010 AAAAAAAA BBBBBBBB CCCCCCCC E12FFF1E |
When the E code type will be encountered, the code handler will jump to and execute (ie. bx to) the AAAAAAAA, BBBBBBBB, CCCCCCCC and E12FFF1E instructions (means the instructions must be in ARM, and not THUMB). |
Codebreaker DS
Description
This is Pelican's entry into the DS cheat-device industry. It supports swapping out the cartridges and also gives the user the option of connecting another game card onto it. For updating, the user may either manually enter codes or use WiFi to connect to a computer running the Codebreaker software.
Code Types
Type | Description |
---|---|
Auto-Game Recognizers | |
Type 0x00 With Encryption 0000YYYY XXXXXXXX |
YYYY = Game's Header CRC16 XXXXXXXX = Game's Nintendo ID |
Type 0x08 Without Encryption 8000YYYY XXXXXXXX |
YYYY = Game's Header CRC16 XXXXXXXX = Game's Nintendo ID |
Constant RAM-Write Codes | |
Type 0x00 8-Bit 0XXXXXXX 000000YY |
XXXXXXX = Address to be written to YY = Byte to be written |
Type 0x10 16-Bit 1XXXXXXX 0000YYYY |
XXXXXXX = Address to be written to YYYY = Halfword to be written |
Type 0x20 32-Bit 2XXXXXXX YYYYYYYY |
XXXXXXX = Address to be written to YYYYYYYY = Word to be written |
Increment/Decrement Codes | |
Type 0x30 8/16-Bit 3XXXXXXX 000UYYYY |
XXXXXXX = Address to be written to U = Bit-type Write, 0 for 8-Bit and 1 for 16-Bit YYYY = Halfword/Byte to be written |
Type 0x38 32-Bit 3XXXXXXX YYYYYYYY |
XXXXXXX = Address to be written to YYYY = Word to be written |
Serial Repeat Constant Write (Slider) Code | |
Type 0x40 Slider 4XXXXXXX TWWWZZZZ YYYYYYYY VVVVVVVV |
XXXXXXX = Address to be written to T = Bit-type Write, 0 for 32-Bit, 1 for 16-Bit and 2 for 8-Bit WWW = Number of times to repeat ZZZZ = Increase Address by (Multiply by data size (1 << (2 - T))) YYYY = Word to be written VVVVVVVV = Increase Value by |
Memory Copy Code | |
Type 0x50 Copy Bytes 5XXXXXXX YYYYYYYY ZZZZZZZZ 00000000 |
XXXXXXX = Address to be copied to YYYYYYYY = Number of Bytes to copy ZZZZZZZZ = Address to copy from |
Pointer | |
Type 0x60 Copy Bytes 6XXXXXXX YYYYYYYY ZZZZZZZZ BCTUVVVV |
XXXXXXX = Pointer Address YYYYYYYY = Word/Halfword/Byte to be written ZZZZZZZZ = Offset to add to the Pointer Address B = Bit-type Write, 0 for 8-bit, 1 for 16-Bit, and 2 for 32-Bit C = Condition Enabled, 0 for disabled, 1 for enabled T = Condition type to check against VVVV [0 is ==, 1 is !=, 2 is <, 3 is>, 4 is == and == 0000, 4-7 follow the pattern set by 0-3] U = Bit-type Load, 0 for 8-Bit, and 1 for 16-Bit VVVV = Halfword/Byte to check against |
8/16-Bit Special Bitwise Write | |
Type 0x70 7XXXXXXX 00TBYYYY |
XXXXXXX = Address to be written to YYYY = Halfword/Byte to be written T = Operation type, 0 for OR, 1 for AND, 2 for XOR B = Bit-type Write, 0 for 8-Bit, and 1 for 16-Bit |
32-Bit Write On Bootup-Hooks | |
Type 0xA0 Hook 1 AXXXXXXX YYYYYYYY |
XXXXXXX = Address to be written to YYYY = Word to be written |
Type 0xA8 Hook 2 AXXXXXXX YYYYYYYY |
XXXXXXX = Address to be written to YYYY = Word to be written |
Conditional Codes | |
Type 0xD0 16-Bit DXXXXXXX ZZTUYYYY |
ZZ = Lines to skip, 00 means 01 by default XXXXXXX = Pointer Address YYYY = Word/Halfword/Byte to be written T = Condition type to check against VVVV [0 is ==, 1 is !=, 2 is <, 3 is>, 4 is == and == 0000, 4-7 follow the pattern set by 0-3] U = Bit-type Load, 0 for 16-Bit, and 1 for 8-Bit VVVV = Halfword/Byte to check against |
Enable Code-Hooks | |
Type 0xF8 Hook 2 FXXXXXXX TYYYYYYY |
XXXXXXX = Hook Address |
Using CBDSCrypt
CBDSCrypt is a utility developed by kenobi. It is capable of both encrypting and decrypting codes for the Codebreaker DS, as well as creating master codes. A ROM of the game the codes are for is required in order to use this application. To use the program, simply run it, and then drag and drop the ROM image on top of the program. Paste the codes that are to be encrypted or decrypted into the left text area, and press the appropriate button "encrypt" or "decrypt" and the resulting codes will appear in the right text area.
Master codes can be generated by pressing the (M) button. This program uses two methods to generate potential master codes, Parasyte's method and kenobi's method. Parasyte's method entails finding the location of the following instructions in both of the ARM executables:
Inst | Operands | Comments |
---|---|---|
ldr | r1, =intr_table | @ 0xE59F1008 |
ldr | r0, [r1,r0,LSL#2] | @ 0xE7910100 |
ldr | lr, =ret_loc | @ 0xE59FE004 |
bx | r0 | @ 0xE12FFF10 |
They might not be found in the ARM9 executable because of decompression, but it will always be in plain sight in the ARM7. All that is necessary is to hook that =ret_loc, which is always 2 words after that bx r0. It is done the same way as hooking any other pointer. This is also how Kwurdi's automatic hook search has functioned for the last two and half years, and it hasn't failed yet.
Kenobi's method involves simulating the ARDS's automated (M) code finder. To start, search for the 32-bit value 0x0380FFF8, beginning at the ARM7 executable. After this is found, search for the following 0x0380FFF8. Following this, search backwards for the first bx r14 (0xE12FFF13). Subtract 4 from this address and then convert it to a RAM address. To convert it to a RAM address, take the address and subtract the 32-bit value that is located at 0x30 in the ROM; then add the 32-bit value that is located at 0x38 in the ROM. The (M) code is F2[ram address] 023FC000.
Nitro Hax
Description
This a homebrewed alternative to the others written by DS Homebrewer Chishm. It runs off of a flash cart, from which it can parse official Action Replay subscriptions. This device supports all official Action Replay code types, using a custom cheat handler.
Code Types
Type | Description |
---|---|
Constant RAM Writes | |
Type 0x00 32-bit 0XXXXXXX YYYYYYYY |
Writes word YYYYYYYY to [XXXXXXX+offset]. |
Type 0x01 16-bit 1XXXXXXX 0000YYYY |
Writes halfword YYYY to [XXXXXXX+offset]. |
Type 0x02 8-bit 2XXXXXXX 000000YY |
Writes byte YY to [XXXXXXX+offset]. |
Conditional 32-Bit Code Types | |
Type 0x03 Greater Than 3XXXXXXX YYYYYYYY |
Checks if YYYYYYYY> (word at [XXXXXXX]) If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of thecode list is reached. |
Type 0x04 Less Than 4XXXXXXX YYYYYYYY |
Checks if YYYYYYYY < (word at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x05 Equal To 5XXXXXXX YYYYYYYY |
Checks if YYYYYYYY == (word at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x06 Not Equal To 6XXXXXXX YYYYYYYY |
Checks if YYYYYYYY != (word at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Conditional 16-Bit + Masking RAM Writes | |
Type 0x07 Greater Than 7XXXXXXX ZZZZYYYY |
Checks if (YYYY)> (not (ZZZZ) < halfword at [XXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x08 Less Than 8XXXXXXX ZZZZYYYY |
Checks if (YYYY) < (not (ZZZZ) & halfword at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x09 Equal To 9XXXXXXX ZZZZYYYY |
Checks if (YYYY) == (not (ZZZZ) & halfword at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Type 0x0A Not Equal To AXXXXXXX ZZZZYYYY |
Checks if (YYYY) != (not (ZZZZ) & halfword at [XXXXXXX]). If not, the code(s) following this one are not executed (ie. execution status is set to false) until a code type D0 or D2 is encountered, or until the end of the code list is reached. |
Offset Codes | |
Type 0x0B Load offset BXXXXXXX 00000000 |
Loads the 32-bit value into the 'offset'. Offset = word at [0XXXXXXX + offset]. |
Type 0xD3 Set offset D3000000 XXXXXXXX |
Sets the offset value to XXXXXXXX. |
Type 0xDC Set offset DC000000 XXXXXXXX |
Adds an offset to the current offset. (Dual Offset) |
Loop Code | |
Type 0x0C C0000000 YYYYYYYY |
This sets the 'Dx repeat value' to YYYYYYYY and saves the 'Dx next code to be executed' and the 'Dx execution status'. Repeat will be executed when a D1/D2 code is encountered. When repeat is executed, the AR reloads the 'next code to be executed' and the 'execution status' from the Dx registers. |
Special Codes | |
Type 0xD0 Terminator D0000000 00000000 |
Loads the previous execution status. If none exists, the execution status stays at 'execute codes'. |
Type 0xD1 Loop execute variant D1000000 00000000 |
Executes the next block of codes 'n' times (specified by the 0x0C code type), but doesn't clear the Dx register upon completion. |
Type 0xD2 Loop Execute Variant/ Full Terminator D2000000 00000000 |
Executes the next block of codes 'n' times (specified by the 0x0C code type), and clears all temporary data. (i.e. execution status, offsets, code C settings, etc.) This code can also be used as a full terminator, giving the same effects to any block of code. |
Data Register Codes | |
Type 0xD4 Add Value D4000000 XXXXXXXX |
Adds 'XXXXXXXX' to the data register used by code types 0xD6 - 0xDB. More arithmetical/logical operations can be set using the 'NDS AR HACK #2'. |
Type 0xD5 Set Value D5000000 XXXXXXXX |
Set 'XXXXXXXX' to the data register used by code types 0xD6 - 0xD8. |
Type 0xD6 32-Bit Incrementive Write D6000000 XXXXXXXX |
Writes the 'Dx data' word to [XXXXXXXX+offset], and increments the offset by 4. |
Type 0xD7 16-Bit Incrementive Write D7000000 XXXXXXXX |
Writes the 'Dx data' halfword to [XXXXXXXX+offset], and increments the offset by 2. |
Type 0xD8 8-Bit Incrementive Write D8000000 XXXXXXXX |
Writes the 'Dx data' byte to [XXXXXXXX+offset], and increments the offset by 1. |
Type 0xD9 32-Bit Load D9000000 XXXXXXXX |
Loads the word at [XXXXXXXX+offset] and stores it in the'Dx data register'. |
Type 0xDA 16-Bit Load DA000000 XXXXXXXX |
Loads the halfword at [XXXXXXXX+offset] and stores it in the'Dx data register'. |
Type 0xDB 8-Bit Load DB000000 XXXXXXXX |
Loads the byte at [XXXXXXXX+offset] and stores it in the'Dx data register'. This is a bugged code type. Check 'AR Hack #0' for the fix. |
Miscellaneous Memory Manipulation Codes | |
Type 0x0E Patch Code EXXXXXXX YYYYYYYY |
Copies YYYYYYYY bytes from (current code location + 8) to [XXXXXXXX + offset]. |
Type 0x0F Memory Copy Code FXXXXXXX YYYYYYYY |
Use the code type D3, DC or B before to set the offset. D2 should be needed to clear the offset after the code. D3000000 XXXXXXXX FYYYYYYY ZZZZZZZZ This should copy ZZZZZZZZ bytes from offset (=XXXXXXXX in this case) to YYYYYYYY. (YYYYYYYY if fixed, no offsets are added to it). |
Dipstar
Description
The most unprofessional looking of the lot, this homebrew outdates all other cheat devices. This piece of software is the only one that can support ROMs, and will only run off certain flash carts.
Code Types
Ways to Hack
Without Real Hardware
There are several different ways to hack Nintendo DS codes without real hardware. Most of these methods entail the use of emulators and ROMs.
- Renegade64 + No$gba This article assumes general usage knowledge of Renegade 64. After attaching Renegade 64 to No$gba, all that is needed to do is to bring up the cheat search window as normal. This is the recommended method.Tips for optimal No$gba usage:
- Set "GBA Mode" To "VGA (Poppy Bright)".
- The majority of games use "EEPROM 8Kbytes" and their NDS Cartridge Backup Media.
- If the sound is crap, it is better to disable it to gain speed.
- If games run slow, setting "Emulation Speed" to "Unlimited MHZ Disaster- 10%" may help.
- HasteDS + Other Emulators HasteDS (unaffectionately called HateDS) is a less-powerful, somewhat buggy emulator hooker (Heh). While less powerful, it can hook a variety of other emulators.
Emulators HasteDS can hook:- No$gba.
- DeSmuME.
- iDeaS.
- NeeDS
Using Datel's Trainer Toolkit
Starting Out
An Action Replay with firmware version 1.52 or higher is required to use the toolkit. An Action Replay is not included with the Toolkit.
To start Training, insert the Trainer Board into the GBA slot of your DS or DS Lite. Connect the supplied USB cable from the mini USB port on the left side of the Trainer Board to a spare USB port on a nearby computer. Next, insert the Action Replay DS into the DS slot of DS or DS Lite being used. It is not necessary to connect your AR to the computer to use the Toolkit. AFter starting up the DS or DS Lite, Windows will detect the Trainer Board. If the drivers for the Toolkit have not been installed, do so now by following the instructions in the manual. At the point the Action Replay logo appears on screen, remove your ARDS in insert the game to be trained. Tap the bottom screen to start.
Next the hacker must open up the Trainer software on the computer he is using. By default, it will start a new file. If there is an existing file, the hacker may open it via the "File" menu. To access the tools described below, click the "Tools" menu then click on the tool to be opened. An electronic version of the included manual can be accessed by clicking "Help".
Hacking
Click "New Search". Then choose the data type. By default, the <acronym title="Trainer Toolkit">TT</acronym> will list 2 items under "Memory Ranges". The one called "Working RAM" may be removed. As the manual for the toolkit states, nothing of interest has ever been found here. If the hacker knows of a specific memory range they want to search in, then he may also remove the Main RAM, then click on "Add". The hacker will need to supply the range a name, a starting address, and an ending address. Remember to prefix with a "0x0". The ability to save and load ranges is included. Narrowing the range is useful, sometimes necessary, if the hacker needs to perform searches while connected to the Nintendo WiFi Connection as the time it takes to complete a full search of the Main RAM will take too long and the hacker will ping out.
To perform another search, choose the appropriate condition and click "Search Again". To search for a specific value in the RAM, select "Equal to" and uncheck "Previous Value". The value box will now be typed in. clicking the triangle next to the text box will allow the hacker to see previous values that have been entered. Remember to prefix the value with a 0x.
After the search is complete, the results will appear in the "Search Results" window. Each search appears next to its own purple square. Next to the square is the search number and the number of results. Clicking the "+" next to the purple square will show the individual memory ranges searched. To view the results for that memory range, double click the text next to the green square. A window will appear showing each address in numerical order and the value for the current and previous searches. The results window can display 1000 results maximum.
Toolkit: Watched Locations
The Trainer Toolkit software allows the hacker to monitor desired locations in the RAM within the "Watched Locations" window. To add a location to the "Watched Locations", right click anywhere in the "Watched Locations" window and choose "Add Location". Be sure to prefix the address with a 0x0. You also need to choose the data type. Notes are optional but they do help. You can also add locations from the any search result by right clicking on the address or value and choosing "Add to watch-list". By right clicking on items the "Watched Locations" window you can edit the information for that address and remove it.
The Run-list
The "Run-list" is an Action Replay that is updatable on-the-fly. Each code is separated by a blank line. The "Run-list" will accept all of the Action Replay code types along with some Trainer Toolkit-only code types. Each instruction may be placed on its own line or grouped together in one line with each instruction separated by a space. Stop the execution of a line of code is accomplished by commenting it out. Commenting can also be used to make notes in the "Run-list". The "Run-list" will accept double forward slashes (//) which will comment out the rest of the line following them. You may also use (/* ..... */) to comment out multiple lines. To upload the "Run-list" to the Trainer Toolkit for execution, click upload. Whenever changes are made to the "Run-List", it will be necessary to upload the list again.
Toolkit: Disassembly View
This window is not of use unless the hacker is familiar with Assembly. As the manual states, this is not a complete disassembler. An IDA Pro can be of use for disassembly if one is needed badly. By default, the disassembler will be in THUMB mode. To switch it into ARM, right click and choose "Switch to ARM". To go to a certain address, right click and choose "Goto address". Remember to prefix the address with a 0x0.
The Hex View Window
The Hex View window displays all the values in an area of memory. To go to a certain address, right click in the window and choose "Goto Address". From the right click menu the hacker can also refresh the view with the current values in memory or toggle Auto Refresh. Another useful feature within this window is the ability to export a full RAM dump. To do this, right click and choose "Save To File". A memory address range must be specified. The file browser will appear, giving the hacker the options of saving and naming the file. No extension is added to the RAM Export by default, although it is very easy to give it one. Note that when a RAM Export is performed, the Toolkit is exporting the values in the RAM as they are when "SAVE" was clicked, not as they appear in the hex view. Double clicking a value in the "Hex View" window will add it as a watched location.
Universal Activators
All commercial DS games share two universal activators, one used for handling all the buttons the GBA has and another used for the DS-unique buttons. The address for the GBA buttons is at 0x04000130, and the address for DS-specific button address is located at 0x027FFFA8. However, these activators are used differently depending on what cheat code device is being used.
Action Replay Specific
Action Replay code type 0x09 gives the hacker some nice flexibility with activators. This code type gives the hacker the option of executing code when a value is not equal to the value specified. Using this attribute we can make codes that can be activated when more than one button is being pressed. The following is a list of inverted values for DS key presses.
Value | Button |
---|---|
GBA Activator Values | |
FFFE | A |
FFFD | B |
FFFB | Select |
FFF7 | Start |
FFEF | Right |
FFDF | Left |
FFBF | Up |
FF7F | Down |
FEFF | Right Trigger |
FDFF | Left Trigger |
NDS Activator Values | |
FBFF | X |
F7FF | Y |
DFFF | Debug Button |
7FFF | NDS Not Folded |
Bitwise AND is used to combine two or more buttons together. (A & B) = (FFFE & FFFD) = FFFC
Codebreaker Specific
The Codebreaker DS conditional code type cannot execute if !=. To use the activators with Codebreaker, a different set of activator values are needed.
Value | Button |
---|---|
GBA Activator Values | |
0001 | A |
0002 | B |
0004 | Select |
0008 | Start |
0010 | Right |
0020 | Left |
0040 | Up |
0080 | Down |
0100 | Right Trigger |
0200 | Left Trigger |
NDS Activator Values | |
0400 | X |
0800 | Y |
2000 | Debug Button |
8000 | NDS Not Folded |
Bitwise OR is used to combine two or more buttons together. (A | B) = (0001 | 0002) = 0003
ARM9 Assembly
The NDS uses an ARM9 chip as its main processor. The ARM architecture provides two modes, ARM and THUMB, and well as 31 32-bit registers. Only 16 of these registers are visible at a time, with R13, R14, and R15 being for the Stack Pointer, the Link Register, and the Program Counter respectively. The ARM instruction set uses 32-bit operations, whereas the THUMB set uses 16-bit. THUMB is designed to produce smaller code with the same speed as ARM and much of the functionality. One major limitation of THUMB is that many instructions cannot access registers above R07. In ARM, 4 bits are set aside for a conditional. The operation is executed only if the current flags meet that condition. More information on ARM and THUMB can be found in the official ARM and THUMB manuals, as well as GBATek, all provided on the documents page. Compared to the GBA's ARM7 processor, the ARM9 is almost identical, with a few extra, rarely-used instructions.
Action Replay-Specific Assembly Hacking
32-Bit RAM Write
Here is an example ASM code that does the same thing as a 32-bit ram write code. This example will use the "See Though Walls" code for Metroid Prime: Hunters found in the Codejunkies code subscription.
AR Code |
---|
02046410 E3A0001E |
All that is needed in ASM is to write this 32-bit value to the correct address. To do the equivalent of the code in ASM, the address and value for the code must both be loaded into a register. The next, and final, step is to store the value into the address.
opcode | arguments | comments |
---|---|---|
ldr | r0, =0x02046410 | ; Load the address to be written to into r0 |
ldr | r1,=0xE3A0001E | ; Load the value to be written into r1 |
str | r1,[r0] | ; Store the value in r1 to the address pointed to by r0 |
bx | r14 | ; End branch |
The first line of the code sets r0 equal to 0x02046410 and the second line sets r1 equal to 0xE3A0001E. The next command str r1,[r0] stores the value of the first operand into the address pointed to by the second operand. This means that address 0x02046410 will now hold the value 0xE3A0001E which is all that is needed to accomplish a 32-bit ram write code. The last line bx r14 is an important one. This line is required at the end of all ASM codes for the AR to back to the code list and continue executing codes. Now the ASM is finished it must be converted into a code that can be entered into the AR. Using Kenobi's ASM to ARDS tool found in the tools section of this document, place the ASM code in the left window and click the convert button. The output should be:
AR Code |
---|
023FE074 012FFF11 |
E0000000 00000018 |
E59F0008 E59F1008 |
E5801000 E12FFF1E |
02046410 E3A0001E |
023FE074 E3520003 |
Add this code into the Action Replay and the effect should be the same as the original code. Of course this code is not very efficient as it takes up more space and was harder to create, but it is just an example. There are times when it is appropriate to use an ASM code and other times where it is better to use the built in code types. An example of a good use would be when a hacker needs to calculate a value for the offset in a complicated manner (Which will be covered in the next section).
Calculating the Action Replay Offset
An effective use of ASM is using it to calculate the Action Replay offset in a complicated manner that in unachievable through normal code types. Most codes for WiFi multiplayer on the Nintendo DS require a player check to make sure the code writes to the correct address for the respective players. For example the "Hold Y To Levitate" code for Metroid Prime: Hunters uses the player check to make sure only the player's character will levitate by writing the value to the correct address based upon the player number.
AR code |
---|
927FFFA8 F7FF0000 |
520D9CB8 00000000 |
020DA74C 00000400 |
D0000000 00000000 |
520D9CB8 00000001 |
020DB67C 00000400 |
D0000000 00000000 |
520D9CB8 00000002 |
020DC5AC 00000400 |
D0000000 00000000 |
520D9CB8 00000003 |
020DD4DC 00000400 |
D2000000 00000000 |
The second line of the code "520D9CB8 00000000" is an IF statement. It is a 32-bit check of the address 0x020d9CB8 to see if the value is 0x00000000. Metroid stores the player number - 1 at this address This means if the player is player 1, the address will hold 0x00000000 and if the player is playing as player 2 it will hold 0x00000001 and so forth. If the player is player 1 the AR writes the value 0x00000400 to the address 0x020DA74C (The levitation address). The address for player 2 to levitate would then be 0x020DB67C and so forth. Rather than write a check for each player and writing to the corresponding address, an ASM hack could be used to calculate an offset based upon the player number. The difference between each player's addresses in the case of this game is 0xF30 and is constant. To find the correct address to write to, multiply the player number by the offset. So if the player is currently player 4 then the equation would be:
(player number) * (Offset) = |
3 * 0xF30 = 0x2D90 |
To accomplish this in ASM, the multiply command must be used. The multiply command takes 3 arguments:
opcode | arguments | comments |
---|---|---|
MUL{cond}{S} | Rd,Rm,Rs | ;multiply Rd = Rm*Rs |
Rd will hold the value of (Rm*Rs). Now remember what the register r10 holds? r10 holds the AR offset and is listed in the 'Do not touch list'. But it's ok for us to touch in this case, because we know what we are doing now. Since this code should modify the AR offset, the result will be stored in r10. Here is what the ASM code should look like:
opcode | arguments | comments |
---|---|---|
ldr | r0,=0x020D9CB8 | ;r0 = 0x020D9CB8 |
ldr | r0,[r0] | ;r0 = value at 0x020D9CB8 |
ldr | r1,=0x00000F30 | ;r1 = 0xF30 |
mul | r10,r0,r1 | ;r10 (AR offset) = (player number) * (0xF30) |
bx | r14 | ;required to jump back to code list |
The first command 'ldr r0,=0x020D9CB8' will load the player address into r0. Then to load the value located at that address into r0 the command 'ldr r0,[r0]' is used. Next 0xF30 is loaded into r1 and finaly the new MUL command is used to calculate the offset 'mul r10,r0,r1'. r10 will hold r0 (player number) * r1 (0xF30). When the ASM is run through Kenobi's ASM to ARDS program we get the following output:
ASM to ARDS Output |
---|
023FE074 012FFF11 |
E0000000 00000018 |
E59F000C E5900000 |
E3A01EF3 E00A0190 |
E12FFF1E 020D9CB8 |
023FE074 E3520003 |
Now since r10 holds the value of the AR offset in this case, when the Action Replay returns from the ASM routine the AR offset will be set and all that is needed is one 32-bit constant RAM write code, '020DA74C 00000400'. The reason for this is because the RAM write codes use the offset, so the offset will be added to the address before writing the value. Also, it is wise to clear the offset at the end of the code so the other codes are not affected. Using the output from the ASM to ARDS program, the new code will look like this:
Hold Y To Levitate: | |
---|---|
Code | Comments |
927FFFA8 F7FF0000 | Activator |
023FE074 012FFF11 | Begin ASM |
E0000000 00000018 | |
E59F000C E5900000 | |
E3A01EF3 E00A0190 | |
E12FFF1E 020D9CB8 | |
023FE074 E3520003 | End ASM |
020DA74C 00000400 | Player 1 address + calculated offset |
D2000000 00000000 | End all and reset offset |
This technique can be used for any game where an offset must be calculated before writing a value. Using ASM rather than multiple IF tests can save lines of unnecessary code. In this case, the assembly version of the code saves 4 lines. Other games, like Mario Kart (LAN multiplayer mode), have way more than 4 players online and can benefit greatly from using ASM in place of IF statements.
Metroid Prime Hunters Auto Kill
This example will explain how to create the auto kill code for Metroid Prime Hunters by KicKenchiKen57. The Auto Kill code requires some good knowledge of the game on the hacker's before it can be made. Before beginning, some memory addresses and values will need to be found.
Needed Addresses and Values | |
---|---|
Code | Comments |
0x020D9CB8 | Player number |
0x020dab78 | Player 1 buttons |
0x00000c01 | A+X+Y key value |
0x00000F30 | Player Offset |
0x020da730 | Player 1 X coordinate |
0x020da734 | Player 1 Y coordinate |
0x020da738 | Player 1 Z coordinate |
The first address needed is the player number address. The need for this address has been addressed in the previous example. Next on the list is the player 1 button address. It is used because the auto kill code contains a hacker protection! Parasyte had mentioned that Metroid holds the buttons presses for each player on WiFi for all to see. Using this, it is possible to add in a hacker protection that works for anyone. What this protection will do is check each players buttons online. If any player is holding down a certain combination of buttons, it can be used to deactivate the auto kill code. In this case, the code is going to check for A+X+Y. If any player (with or without an Action Replay or any other cheat device) holds these buttons while a player is using the Auto Kill code, the code will be disabled until that user reboots. The last things to note are the player 1 X,Y,Z coordinate addresses. These addresses are used to warp a player to another player's location.
The Auto Kill routine works as follows. When a player has the Death Alt power up, any players that touch that player should die instantly, or take a hefty helping of damage. Assuming the user has the Death Alt code activated, all players could be killed by warping to their locations and moving on after they have died. Unfortunately, it is not enough to just check the health of each player and warp to the next when they are dead. There are other hackers and script kiddies out there who use Infinite Health cheats. This would stop the Auto Kill because the user would not move on to the next player if the hacker never died. Also, it is not desirable to warp to every player because the user controls one of those players. When the user warps to his/her own location, it basically looks like the user is not warping at all, and wastes valuable time. A timer can be used to increase the efficiency of this code. After a certain period of time elapses, the code should move on to the next player. This will prevent the code from sticking with someone who does not die. Since the code should not try to warp the hacker to a dead or inactive player, it should also check the player's health. If a player has no health, that player is either inactive (ex. player 4 in a 2 player game) or dead and should be skipped. This also allows the code to immediately switch to the next player as soon as the current player dies. The last check is the player number check. If the player number matches the player number of the code user it will be skipped. The code will also check the other players buttons to see if the defense mechanism is active.
Before writing any code, it would be wise (and necessary) to set up some variables.
Data Type | Data | Comments |
---|---|---|
player: | ||
.word | 0x020D9CB8 | ;player now holds the value 0x020D9CB8 |
All variables should come at the end of the code after the 'bx r14'. It is also good practice to leave a space between the last line of code and the variable list for better readability. With this in mind, here is what the variable list will look like.
Data Type | Data | Comments |
---|---|---|
player: | ||
.word | 0x020D9CB8 | ;address of the player number |
offset: | ||
.word | 0x00000F30 | ;offset between player data |
data: | ||
.word | 0x020DA730 | ;player 1 X coordinate |
counter: | ||
.word | 0x00000000 | ;counter set to 0 |
buttons: | ||
.word | 0x020DAB78 | ;player 1 buttons held address |
switch: | ||
.word | 0x00000000 | ;switch to determine if code is disabled (0=enabled,1=disabled) |
keys: | ||
.word | 0x00000C01 | ;test for A+X+Y keys held |
The variable list does not contain any other player data but player 1. It does not even contain the addresses for the Y or Z coordinates. That is because The ASM code is going to calculate these things on its own based upon the player number and offset to save space and to be more efficient. The next part of the code will check all players' buttons. Before the code is executed, the buttons of each player must be checked to determine if the defense mechanism is in place.
opcode | arguments | comments |
---|---|---|
mov | r0,#0 | ;clear r0 for the loop counter |
ldr | r1,offset | ;r1 = offset |
ldr | r2,buttons | ;r2 = player 1 button address |
ldr | r6,keys | ;r6 = keys to test for |
loop: | ;loop will check all players buttons | |
mla | r3,r0,r1,r2 | ;r3 = (player number * offset) + (button address) |
ldr | r3,[r3] | ;r3 now holds the buttons that are held |
and | r3,r3,r6 | ;r3 = r3 && r6 |
cmp | r3,r6 | ;if A+X+Y are held, r3 will == r6 |
streq | r1,switch | ;if so, stick the offset in the variable switch |
cmp | r0,#3 | ;if we didnt loop 4 times (0-3) |
add | r0,#1 | ;add 1 to loop counter |
bne | loop | ;and loop again |
The player 1 address for what buttons are being held is the "base address" in this code. The base address lets the assembly routine calculate the address needed for the other players' addresses. This is accomplished by multiplying the player number by the offset and adding the "base address" to it. Metroid Prime: Hunters keeps the player number's as follows:
MPH player number | Actual player |
---|---|
0 | 1 |
1 | 2 |
2 | 3 |
3 | 4 |
The address holding the button presses for player two would then be 0x020DBAA8.
Finding the address |
---|
(player number) * (offset) + (base address) |
(1) * (0xF30) + (0x020DAB78) |
player 2 address = 0x020DBAA8 |
After checking for the A+X+Y button combination, the warp code should come next, followed by the list of variables. The finished routine is below:
Inst | Operands | Comments |
---|---|---|
mov | r0,#0 | ;clear r0 for the loop counter |
ldr | r1,offset | ;r1 = offset |
ldr | r2,buttons | ;r2 = player 1 button address |
ldr | r6,keys | ;r6 = keys to test for |
loop: | ;loop will check all players buttons | |
mla | r3,r0,r1,r2 | ;r3 = (player number * offset) + (button address) |
ldr | r3,[r3] | ;r3 now holds the buttons that are held |
and | r3,r3,r6 | ;r3 = r3 AND r6 |
cmp | r3,r6 | ;if A+X+Y are held, r3 will == r6 |
streq | r1,switch | ;if so, stick the offset in the variable switch |
cmp | r0,#3 | ;if we didnt loop 4 times (0-3) |
add | r0,#1 | ;add 1 to loop counter |
bne | loop | ;and loop again |
ldr | r0,switch | ;r0 holds the value of switch |
cmp | r0,#0 | ;is the switch == 0? |
bne | quit | ;if not, we want jump to the quit label |
ldr | r0,player | ;r0 = player number address |
ldr | r0,[r0] | ;r0 holds the player number |
ldr | r3,data | ;r3 = player 1 X coordinate address |
mla | r2,r0,r1,r3 | ;r2 = ([player number * offset)+(coordinate address) |
ldr | r6,counter | ;r6 == counter variable |
add | r6,r6,#1 | ;add 1 to the counter |
mov | r8,r6,lsr #0x6 | ;r8 = counter>> 0x6 |
cmp | r8,r0 | ;does r8 == player number? |
addeq | r8,#0x01 | ;if so, add 1 to skip the player |
moveq | r6,r8, lsl #0x06 | ;r6 = r8 << 0x6 (and update r6 as well) |
cmp | r8,#0x4 | ;did do all 4 players? |
moveq | r6,#0 | ;if so reset r6 |
moveq | r8,#0 | ;and reset r8 |
ldr | r12,data | ;r12 = the player 1 x coordinate address |
mla | r3,r1,r8,r12 | ;r3 = (player number * offset) + (player 1 x coordinate address) |
ldr | r12,[r3,#0xBE] | ;r12 = the current players health (x coord address + 0xBE = health address) |
cmp | r12,#0x0 | ;is player dead or not even in the game? |
addeq | r8,#0x01 | ;if so, add 1 to r8 to skip that player |
moveq | r6,r8, lsl #0x06 | ;r6 = r8 << 0x6 (and update r6 as well) |
beq | end | ;and jump to the end label |
ldr | r12,[r3] | ;player is not dead, so load x coordinate |
str | r12,[r2] | ;and store it in the x coord address |
ldr | r12,[r3,#4] | ;load y coordinate |
str | r12,[r2,#4] | ;and store it in the y coord address |
ldr | r12,[r3,#8] | ;load z coordinate |
str | r12,[r2,#8] | ;and store it in the z coord address |
end: | ||
str | r6,counter | ;store r6 in the counter variable |
quit: | ||
bx | r14 | ;required |
Variables | ||
player: | ||
.word | 0x020D9CB8 | ;address of the player number |
offset: | ||
.word | 0x00000F30 | ;offset between player data |
data: | ||
.word | 0x020DA730 | ;player 1 X coordinate |
counter: | ||
.word | 0x00000000 | ;counter set to 0 |
buttons: | ||
.word | 0x020DAB78 | ;player 1 buttons held address |
switch: | ||
.word | 0x00000000 | ;switch to determine if code is disabled (0=enabled,1=disabled) |
keys: | ||
.word | 0x00000C01 | ;test for A+X+Y keys held |
Now one part of the code should be very obvious.
opcode | arguments | comments |
---|---|---|
ldr | r0,switch | ;r0 holds the value of switch |
cmp | r0,#0 | ;is the switch == 0? |
bne | quit | ;if not, we want jump to the quit label |
After checking the switch, if to does not equal '0' the entire section of code performing the auto kill should be skipped completely, so it branches to the label quit. After this first important check, the code then loads all of the necessary varaibles into the registers to begin looping through each player. In the loop, it uses r6 as a timer and r8 as the player number. By executing a mov r8,r6,lsr #0x6 the code does a logical right shift on r6 by 0x6 and stores it in r8. The higher the number used in the lsr, the faster r8 will change. In this case 0x6 was a good enough value to allow enough time when warping between players to kill them.
Converting Codes
There are two options here.
- Use Dlong's app.
- Convert by hand.
Before attempting this one should read up on Action Replay and Codebreaker code types. For example, Special Stage Ring Modifier hacked by DSman for Sonic Rush:
AR Code |
---|
22181F28 000000XX |
This code happens to be a simple 8-bit write, or code type 2. The Codebreaker's 8-bit write code type is 0, so to get the Codebreaker version of this code all that is needed to do is to swap out the code type digit in the front of the code.
CB Code |
---|
02181F28 000000XX |
Most codes can be ported this way. More complicated codes can be converted, but the hacker really needs to get familiar with the codes and code types of both systems to do this.
Here's a more complicated code: Moon Jump hacked by DSman for Yoshi's Island DS:
AR Code | |
---|---|
94000130 FFFD0000 | |
62105F88 00000000 | |
B2105F88 00000000 | |
20000055 00000099 | |
D2000000 00000000 |
Let's break this down first.
AR Code | |
---|---|
94000130 FFFD0000 | A run-of-the-mill universal activator. |
62105F88 00000000 | Code type 6, or a 32-bit != code type, sort of part of the pointer. (Used for the conditional) |
B2105F88 00000000 | The next two lines start to get into pointers, which will be explained in detail. |
20000055 00000099 | |
D2000000 00000000 | Code type D2, or the terminator. |
Action Replay DS pointers are laid out so that the pointer address is temporarily loaded into the data register, and then a code is written using this offset as a baseline. The Codebreaker actually has a nice pointer code type, on the other hand.
CB Code |
---|
6XXXXXXX YYYYYYYY |
ZZZZZZZZ BCTUVVVV |
X | The pointer's address. In this case it equals 02105F88. |
Y | The value to be written. Here is is 99. |
Z | The offset. The offset for this particular Moonjump address is 00000055. |
B | Bit-type Write, 0 for 8-bit, 1 for 16-Bit and 2 for 32-Bit. In this case B == 0. |
C | The Conditional used to replace the second line of the AR code. It should be equal to 1. (enabled) |
T | Conditional Type. Since line 2 of the AR is != to a 32-bit value of 0, T should equal 1 in this case. |
U | Bit count of the checked value. There is no 32-bit, so I guess 16 will have to suffice. (Or U = 1) |
V | What the conditional are checking against. (V = 0000) |
The code, once converted, turns out to be:
CB Code |
---|
62105F88 00000099 |
00000055 01110000 |
It should be easy to convert most codes if proper documentation is kept handy. Code porting is a skill to be learned, and should not be treated as a set of steps to mechanically go through.
EnHacklopedia |
---|
Basics |
Number and Data Encoding Formats - Generic Code Hacking |
Individual Systems In Depth |
Hacking Arcade - Hacking NES - Hacking SMS - Hacking SNES - Hacking Genesis - Hacking Saturn - Hacking PSX - Hacking N64 - Hacking DC - Hacking PS2 - Hacking GCN - Hacking Game Boy - Hacking Game Gear - Hacking Game Boy Advance - Hacking NDS - |
Documents and References |
Documents |
Tools |
Tools |
Legal |
---|
|