EnHacklopedia » Individual Systems » Hacking Nintendo 64

Hacking Nintendo 64

Creative Commons License

All files (HTML, CSS, images) included in EnHacklopedia are licensed under the Creative Commons Attribution-ShareAlike 3.0 License. All authors contributing to EnHacklopedia should be made aware of the license before contributing. If the author does not agree to the licensing, his or her contributions will not be accepted into the project.

History

  • 04-16-2007
    • Started on N64 Assembly (R4300i). (Viper187)
    • Updated Key Codes. (Viper187)
    • Updated the Reflashing a Defective Device portion of GS/AR User Guide. (Viper187)
  • 04-14-2007
    • Added Hacking Enable Codes. (Viper187)
    • AR picture from kenobi added. (Viper187)
    • Added Hacking Ammo - The Easy Way and the Hard Way. (Viper187)
  • 04-13-2007
    • Hacking Enablers section added. (Viper187)
    • Finding Activators section added. (Viper187)
    • Two more pictures. (Viper187)
  • 04-12-2007
    • A couple new items in the Xploder64 Code Types subsections. (Viper187)
    • More pictures thanks to kenobi. (Viper187)
  • 04-11-2007
    • Updated Legal section. (Parasyte)
    • Even more minor mistakes fixed. (Viper187)
    • More minor formatting and typographical fixes. (Viper187)
  • 04-10-2007
    • Fixed a couple typos and xhtml issues. (Viper187)
    • Slight fix on the '50' code type description. (Viper187)
    • Finished up Hacking With Emulators for now. (Viper187)
    • Added a couple more screenshots to the GS/AR User Guide. (Viper187)
    • Fixed some links now that the tools oage got updated. (Viper187)
  • 04-09-2007
    • Updated footer. (Viper187)
    • More on hacking. (Viper187)
  • 04-08-2007
    • Started on Hacking With Emulators. (Viper187)
    • Added Software Hacks for Xploder64. (Viper187)
    • Updated Hacking with GS/AR Pro. (Viper187)
    • Updated GS/AR User Guide. (Viper187)
    • Fixed some typos. (Viper187)
    • GS/AR User Guide more complete now, including some screenshots. (Viper187)
    • Updated footer. (Viper187)
    • Started on the PC Connection info. (Viper187)
    • Fixed some minor typos/grammatical mishaps. (Viper187)
    • Updated footer. (Viper187)
    • More on the Code Handler Hacks. (Viper187)
  • 04-07-2007
    • Started on Code Handler hacks. (Viper187)
    • Changed classes on ASM tables. (Viper187)
    • Added GS/AR Software Hacks. (Viper187)
  • 04-06-2007
    • Xploder64 Code Types updated. (Viper187)
    • GS/AR Code Types updated. (Viper187)
    • Updated description of 'DE' code type. (Viper187)
    • Filled some stubs in Hacking With GS Pro. (Viper187
    • Added/Changed some section stubs. (Viper187)
    • Added Basics of N64 Hacking (Viper187)
    • Updated Legal and History to proper code. (Parasyte)
    • Added N64 Xploder encryption info. (Viper187)
  • 04-05-2007
    • Added Jesus Mode example. (Viper187)
    • Small PCS description added. (Viper187)
    • Contents updated and class IDs tweaked. (Viper187)
    • Changed for new guidelines. (Viper187)
    • Name changed. (Viper187)
    • Legal/Version/History moved around. (Viper187)
    • Getting started. (Viper187)

Ways To Cheat

The hardware cheat devices for N64 come in the form of a cartridge which plugs into the N64, allowing a game cartridge to connect to the top of it. The only downside to this is that jarring the N64 typically causes the game to crash. Like the cheat devices for most other systems, they come preloaded with many codes and the ability to add more. These devices come in a few flavors: Action Replay, Equalizer, Gameshark, Gameshark Pro, and Xploder64.

NOTE: Some games will NOT work on earlier versions of these devices. This is due to protections added to certain games.

Some emulators also offer support for GS/AR codes. Project64 and 1964 are the more popular options for built-in cheating. However, some external programs/plugins can allow cheating on other emulators and sometimes even support additional code types. Note that enable codes are NOT required when cheating on emulators.

Gameshark / Action Replay

Action Replay: Front

Gameshark and Action Replay for N64 are the exact same device with different names. Action Replay was originally developed by Datel in the UK It was then sold by Interact with the Gameshark label in the U.S. Madcatz now owns that label. They're also called GameBuster in Germany.

Gameshark Pro / Action Replay Pro

GS Pro: Front AR Pro: Front

Like the GS and AR, these were both developed by the same company, just sold under different labels in different parts of the world. The difference between these and the older devices of the same brand are that they include a code generator, memory editor, and DB25 connector (v3.1+) on the back for PC connection. The code gen can be used by itself or connected to the PC in order to hack your own codes. See later sections for more info on utilizing these hacking tools.

Gameshark Lite / Equalizer

These were the last incarnation of the GS/AR on N64. They are almost identical to GS/AR Pro in cheating functionality, but the code generator and DB25 port are missing.

Xploder64 / Xplorer64

Xplorer64: Front

This is the alternative to Datel's assortment of N64 cheat devices. It was developed by Fire International (Blaze USA). Unfortunately, information about this device is difficult to find at this point.

Renegade

Renegade is a powerful hacking and cheating tool written by Viper187. It currently supports cheating/hacking on Project64, 1964, Mupen64, and Nemu. It supports all the standard GS/AR code types and a few extra ones. See the ReadMe included with the program for a current list.

PCS

PCS (by Parasyte) is a plugin for N64 emulators that can be used to find codes.

Gameshark / Gameshark Pro User Guide

Menu Layout & Controls

GS Pro: Main Menu

Game List

Adding new games is pretty straightforward; there's a "New Game" item at the top of the list or in the sub-menu (Z button). BEWARE: Rapidly deleting games is not advised and has been known to cause corruption of the device. Deleting a game here and there works, just don't overdo it trying to "organize" the list.

Adding New Codes

GS Pro: Games List

Adding new codes shouldn't be an incredibly challenging task, but it does take a little getting used to. The Edit Code screen can be accessed by pressing Z with an existing code selected or choosing "New Code" in the code list of a game. Upon selecting "New Code," the user is presented with a box to enter a name for the code. Enter a name and press the B button. This brings up the standard Edit Code screen. Select the box on the left and press A. There's a box on the right to select numbers and letters with the D-Pad and press A to enter them. The code entered appears in the box on the left. The L and R buttons will move the cursor in the code box left or right for editing. Once finished, press B to exit from the code entry. There are 3 options: Default On/Off, Exit & Save, Exit & Discard. Default On/Off tells the device to always have the code on or off each time the device is booted. The other two options are pretty much self-explanatory.

GS Pro: Code Entry Screen

Memory Card Manager

This consists of two boxes listing all controllers with memory cards plus "GamePak". It allows you to copy saves between cards, format them, or delete specific saves.

GS Pro: Memory Card Manager

Code Generator

This is only available in the "Pro" (v3.0+) versions of the GS/AR line. The expansion pack is required to utilize it. The purpose of the Code Generator is to allow the user to hack new codes. The difficulty of this task can range from easy to psychotic, depending on a few things: the user's programming knowledge, user skill, good old fashioned luck, and the type of code being attempted. This discussed more in-depth later.

Enablers

Enablers (aka "(M) Must Be On") come in many forms. Some simply disable the expansion pack (CC/DD/EE) forcing the game to run in low resolution mode. Others disable protections that would otherwise cripple/crash the device (F0/F1). Finally, there's one enabler type (FF) that simply tell the device where to store its active codes, because some games overwrite the default location. Most games that require a key code will also require a DE type enabler; apparently, the device can't find the game's entry point on its own. More in-depth information on these is available in the section about hacking them.

Key Codes

GS Pro: Key Codes Screen

Some games have added protection that prevents cheat devices from functioning. Key codes were first introduced on GS/AR version 1.08 to bypass some of these protections. They're present in all versions after that, as well. Due to these protections, some games will never work on an older version cheat device. To boot a game that requires a key code, the device must first be booted with any unprotected game. In v3.0+ of the GS, there's a menu option for setting key codes. In older versions you have to hold L+R on the main menu. Once set, the key code is only active for 1 boot up. Turn off the N64, put the protected game on the shark, and boot up. After booting the protected game once, the key code flips back to default. In devices v2.2 and higher, the key codes have an additional 32-Bit value attached to them. This is an additional special instruction, which is believed to set the default destination of the code engine. It was first required by Ocarina of Time. Xploder64 uses "boot modes" in pretty much the same way GS/AR uses key codes. A list of all the preloaded key codes in each version of GS/AR follows.

Key Code Games
Gameshark Version 1.08
? Super Mario 64 & Others
4E F8 4D D6 0A B3 D6 0A B8 Diddy Kong Racing, 1080 Snowboarding, Kobe Bryant In NBA Courtside, Banjo-Kazooie, MLB Featuring Ken Griffey Jr, Ken Griffey Jr.'s Slugfest
? Yoshi's Story, Cruis'n World, F-Zero X
Gameshark Version 1.09
? Super Mario 64 & Others
59 A6 31 F5 13 B3 DA 50 FA Diddy Kong Racing, 1080 Snowboarding, Kobe Bryant In NBA Courtside, Banjo-Kazooie, MLB Featuring Ken Griffey Jr, Ken Griffey Jr.'s Slugfest
05 63 14 98 D5 E4 CF CD 1A Yoshi's Story, Cruis'n World, F-Zero X
Gameshark Version 2.00
63 34 F1 61 A7 2C 20 1C 2E Super Mario 64 & Others
50 F2 49 08 7C 07 EE 6C 25 Diddy Kong Racing, 1080 Snowboarding, Kobe Bryant In NBA Courtside, Banjo-Kazooie, MLB Featuring Ken Griffey Jr, Ken Griffey Jr.'s Slugfest
8D 9A 8C DA F5 F2 B6 07 92 Yoshi's Story, Cruis'n World, F-Zero X
Gameshark Version 2.10
EB 03 0C 2C D2 3A AF C3 CE Super Mario 64 & Others
78 69 4F BD AC EF E9 DD 79 Diddy Kong Racing, 1080 Snowboarding, Kobe Bryant In NBA Courtside, Banjo-Kazooie, MLB Featuring Ken Griffey Jr, Ken Griffey Jr.'s Slugfest
85 A2 B3 44 44 4C F1 C1 E4 Yoshi's Story, Cruis'n World, F-Zero X
Gameshark Version 2.21
3E 75 22 68 00 99 BE BE F6
80 20 10 00
Super Mario 64 & Others
2C 48 29 16 D4 3E 90 61 47
80 20 10 00
Diddy Kong Racing, 1080 Snowboarding, Kobe Bryant In NBA Courtside, Banjo-Kazooie, MLB Featuring Ken Griffey Jr, Ken Griffey Jr.'s Slugfest
94 CB D4 8E 52 9A 30 89 E7
80 20 10 00
Yoshi's Story, Cruis'n World, F-Zero X
14 A8 3B CA CD F8 11 BE 50
80 19 00 00
Legend of Zelda: Ocarina of Time, Legend of Zelda: Majora's Mask, Perfect Dark, Conkers Bad Fur Day, Jet Force Gemini, Mickey's Speedway, Banjo-Tooie
Gameshark Version 3.0/3.1
70 14 FF AB 1A 91 14 49 B4
80 18 00 00
Super Mario 64 & Others
5B E5 5F CE 93 89 D7 11 9F
80 20 00 00
Diddy Kong Racing, 1080 Snowboarding, Kobe Bryant In NBA Courtside, Banjo-Kazooie, MLB Featuring Ken Griffey Jr, Ken Griffey Jr.'s Slugfest, Super Smash Bros, Paper Mario, Pokemon Snap, Excitebike 64
33 31 66 BD 04 ED E3 62 DF
80 20 04 00
Yoshi's Story, Cruis'n World, F-Zero X
56 72 19 E1 9D 62 82 28 C9
80 19 00 00
Legend of Zelda: Ocarina of Time, Legend of Zelda: Majora's Mask, Perfect Dark, Conkers Bad Fur Day, Jet Force Gemini, Mickey's Speedway, Donkey Kong 64, Banjo-Tooie
Gameshark Version 3.2
AF FA 90 67 C2 49 22 D0 12
80 18 00 00
Super Mario 64 & Others
BD B8 AF 1A E9 C2 8B 3B 30
80 20 10 00
Diddy Kong Racing, 1080 Snowboarding, Kobe Bryant In NBA Courtside, Banjo-Kazooie, MLB Featuring Ken Griffey Jr, Ken Griffey Jr.'s Slugfest, Super Smash Bros, Paper Mario, Pokemon Snap, Excitebike 64
B6 F4 6A E1 8B 0F C8 AB 67
80 20 04 00
Yoshi's Story, Cruis'n World, F-Zero X
85 87 29 C5 3A 85 F7 50 F0
80 19 00 00
Legend of Zelda: Ocarina of Time, Legend of Zelda: Majora's Mask, Perfect Dark, Conkers Bad Fur Day, Jet Force Gemini, Mickey's Speedway, Donkey Kong 64, Banjo-Tooie
Gameshark Version 3.3
8F 89 AB A0 C3 4C 26 10 A4
80 18 00 00
Super Mario 64 & Others
95 AC 21 BE 58 B0 4E F6 A8
80 20 10 00
Diddy Kong Racing, 1080 Snowboarding, Kobe Bryant In NBA Courtside, Banjo-Kazooie, MLB Featuring Ken Griffey Jr, Ken Griffey Jr.'s Slugfest, Super Smash Bros, Paper Mario, Pokemon Snap, Excitebike 64
C4 6F 1B C2 6C 6C 1F 67 1D
80 20 04 00
Yoshi's Story, Cruis'n World, F-Zero X
A9 24 53 52 5F 73 77 37 7D
80 19 00 00
Legend of Zelda: Ocarina of Time, Legend of Zelda: Majora's Mask, Perfect Dark, Conkers Bad Fur Day, Jet Force Gemini, Mickey's Speedway, Donkey Kong 64, Banjo-Tooie

PC Connection and Utilities

GS Pro: Back

GS/AR Pro versions 3.1 and higher have a DB25 connector on the back for linking up with a PC through the parallel (printer) port. A DB25 male to DB25 female cable (IEEE-1284 compliant) is required to do this, along with the N64 Version 3 Utilities released by Datel or Game Software Code Creator. With the console off, insert the GS/AR with a game a top, and hook up the cable. Boot the device with the DB25 cable connected (one end to the device, the other to the PC), and leave it at the main menu. Next, open the N64 Utils. Click the Detect button to see if everything is connected properly. If the device is not detected, there is a problem.

Troubleshooting N64 Utils: System Info Reflashing/Upgrading

After detecting the hardware to be sure it's connected properly, go to the Other Utilities tab, and click the Upgrade button. There is checkbox above that button with the option to overwrite the code list with the default (official) list or not. It will take a moment to send the upgraded software to the device.

N64 Utils: Other Utilities Reflashing a Defective Device

The "Piggyback Reflash" was something discovered by someone that was just messing around, and it has given users a chance at reviving corrupted (unbootable) devices. This is like a defibrillator for GS/AR. Beware, however, it can be hazardous to the working device used in the procedure. The authors and device manufacturers are not liable for any damage caused to devices by attempting this.

A working GS/AR is required to do this. It is advisable to backup the code list before beginning. To begin, place a working device in the N64 and connect it to the PC with the DB25 cable. Then, put the defective device on top of the working one, and put the game on top of that. Now go to the Other Utilities in the N64 utils and click the Upgrade button just like normal. The result is BOTH devices being reflashed to that version! This has even been know to work for reflashing older (pre v3.1) hardware to v3.3. Of course, there's no DB25 port on the back of an old shark to hack with the PC programs, but the code generator and code type upgrades are nice.

If a working GS/AR with a port on the back is not available, but a GS/aR without an LPT is, it's worth a shot booting the good shark once with the fried one on top. Sometimes, it brings the dead one back to life.

Altered GS/AR Software

There can be altered versions of the GS/AR rom. The only one currently known is Perfect Trainer. It has some nice enhancements over the regular GS/AR. It's mostly geared toward hacking of high resolution games (like Perfect Dark) without crashing so much. It also supports a pointer code type. Flashing it is as simple as backing up ar3.enc in the N64 utils folder, and placing the altered rom there instead. Then flash as normal. It can be flashed back to the regular software, so don't worry about being stuck with anything. This will probably be mentioned in more detail later.

Grabbing Screenshots

The remaining item on the Other Utilities tab is pretty self-explanatory. Click the Grab Video Image button to get an image of what's currently on the screen (during a game).

Code List Editing/Backup N64 Utils: Code list

Everything on the Code List tab is for use at the main menu of the GS/AR only. The code list on the device can be backed up by setting a filename (through browsing or just type it in) and clicking the Download Codes button. Editing a code list is as easy as opening a backup of it in a text editor. Just follow the basic syntax of file to add/remove codes and games. After editing is complete, the code list must be compiled before uploading to the device. Simply browse for the newly edited file in the Code List Compiler frame here, Then click the Compile Codes button. If the Compilation Results box lists errors, fix them and compile again. Once the list is compiled properly, all that's left is to hit the Upload Codes button and wait a moment for it to update the GS/AR.

Game Software Code Creator (GSCC)

Game Software Code Creator by Code Master (aka CMX) is much like the N64 Utils. It's primary function is hacking codes, but it has the ability to upload/download code lists as well. Getting GSCC connected to the GS/AR properly starts out the same as with the official utils. One of the perks of GSCC though is better Windows XP/2000 support; however, communication still times out randomly on XP. It includes a special driver called Totalio. It seems to auto-detect the operating system being run on and activate totalio on its own, but if it doesn't there's a Totalio submenu located in the Debug menu with a Start/Stop option. The program must also be configured for N64 GS/AR. Below is a picture of the Configuration Menu (File > Configuration). The only part for beginners to worry about is the System + Communication Options frame. Notice the "Auto Detect Settings" button there. With a little luck, this will work. If not, try configuring manually like below. Note that GSCC cannot be used to upgrade/reflash the cheat device.

GSCC: Configuration Menu Code List Updater

This is used basically the same as the one in the N64 Utils; however it compiles the list automatically before uploading. There are also edit boxes for viewing/editing the list within the program.

GSCC: Code List updater

Xploder64 / Xplorer64 User Guide

Xploder64: Main Menu

Detailed information about the Xploder64's functionality is currently unavailable. Documentation about the Xploder64 has been pretty hard to come by.

Boot Modes

Boot modes appear to be the equivalent of key codes on GS/AR. As with key codes, the device must be booted with an unprotected game first. Set the boot mode for the protected game of choice, power off, and power back on with that game plugged into the device.

Mode Game(s)
1 Super Mario 64 & Others (Default)
2 Diddy Kong Racing, 1080 Snowboarding, Kobe Bryant In NBA Courtside, Banjo-Kazooie, MLB Featuring Ken Griffey Jr, Ken Griffey Jr.'s Slugfest, Super Smash Bros, Paper Mario
3 Yoshi's Story, Cruis'n World, F-Zero X
4 Legend of Zelda: Ocarina of Time, Legend of Zelda: Majora's Mask, Perfect Dark, Conkers Bad Fur Day, Jet Force Gemini

Adding Codes

Xploder64: Add New Code

Gameshark / Action Replay Code Types

Type Description Version
RAM Writes
Note: Any code prefixed with numbers not listed here is interpreted by the code handler as a regular 8-Bit or 16-Bit write.
8-Bit
80XXXXXX 00??
Writes 1 byte (??) to the specified address (XXXXXX) repeatedly. All
16-Bit
81XXXXXX ????
Writes 2 bytes (????) to the specified address (XXXXXX) repeatedly. All
8-Bit GS Button
88XXXXXX 00??
Writes 1 byte (??) to the specified address (XXXXXX) each time the GS Button is pressed. All
16-Bit GS Button
89XXXXXX ????
Writes 2 bytes (????) to the specified address (XXXXXX) each time the GS Button is pressed. All
Conditional Codes
8-Bit Equal To
D0XXXXXX 00??
YYYYYYYY ZZZZ
If the byte at XXXXXXX is equal to ??, then the code on the next line is executed. All
8-Bit Equal To (GS Button)
D8XXXXXX 00??
YYYYYYYY ZZZZ
If the byte at XXXXXXX is equal to ?? and GS button is being pressed, then the code on the next line is executed. All
16-Bit Equal To
D1XXXXXX ????
YYYYYYYY ZZZZ
If the 2 bytes at XXXXXXX are equal to ????, then the code on the next line is executed. 3.0+
16-Bit Equal To (GS Button)
D9XXXXXX ????
YYYYYYYY ZZZZ
If the 2 bytes at XXXXXXX are equal to ???? and GS button is being pressed, then the code on the next line is executed. 3.0+
8-Bit Different To
D2XXXXXX 00??
YYYYYYYY ZZZZ
If the byte at XXXXXXX is NOT equal to ??, then the code on the next line is executed. 3.0+
8-Bit Different To (GS Button)
DAXXXXXX 00??
YYYYYYYY ZZZZ
If the byte at XXXXXXX is NOT equal to ?? and GS button is being pressed, then the code on the next line is executed. 3.0+
16-Bit Different To
D3XXXXXX ????
YYYYYYYY ZZZZ
If the 2 bytes at XXXXXXX are NOT equal to ????, then the code on the next line is executed. 3.0+
16-Bit Different To (GS Button)
DBXXXXXX ????
YYYYYYYY ZZZZ
If the 2 bytes at XXXXXXX are NOT equal to ???? and GS button is being pressed, then the code on the next line is executed. 3.0+
Special Codes
8-Bit Write On Boot
F0XXXXXX 00??
Writes 1 byte (??) to the uncached address (XXXXXX) only once. These are most often used to disable certain types of protection that some games use to disable cheat devices. F0/F1 only works on boot, but they are handled AFTER the CIC checksums are calculated (allowing the codes to patch the executable code without causing a checksum failure, interrupting the boot process). A maximum of 50 F0/F1 type codes can be used at one time. Hackers should also be aware that F0/F1 codes aren't added to the active codes list once the game starts. This can allow for more active codes alongside assembly hacks on some games. 3.0+
16-Bit Write On Boot
F1XXXXXX ????
Writes 2 bytes (????) to the uncached address (XXXXXX) only once. These are most often used to disable certain types of protection that some games use to disable cheat devices. 3.0+
Disable Expansion Pack
EE000000 0000
Attempts to keep the game from using the expansion pack. Can also increase code generator stability with some older games. The actual effect of the code is the same as using:
F1000318 0040
F100031A 0000
It can be helpful to know those addresses. For example, Zelda requires that you have the code generator on or use EE000000 0000, but using F0000319 0078 instead allows the game to run just fine whether the code generator is on or not.
3.2+
Additional Enable Code
20000000 0000
Clears Memory 0x80000200 - 0x80000300. This might have been added as a precaution for games that check that area on boot. To the writers' knowledge, this code has never actually been needed. 3.2+
Change Exception Handler
CC000000 0000
The GS/AR patches the exception handler in order to get the code engine running. This code type changes the default patching method, probably for a non-standard exception handler (like for a newer PSYQ lib). Another code type that slipped through the cracks. It has never been used. 3.2+
Enabler
DEXXXXXX 0000
Used to select the executable entry point (0x80XXXXXX). This is necessary with games that utilize certain protection chips. This code is typically used in conjunction with a key code. The address specified can only be 0x80000000 - 0x80100000. Any address above 0x80100000 (EG 0xDE100400 0000) will default the entry point down to 0x80000400. 1.08+
Set Store Location
FFXXXXXX 0000
Tells the device to store active codes starting at XXXXXX. This is required on some games that use the expansion pack. 3.3+
Repeater/Patch Code
5000XXYY ????
8ZZZZZZZ VVVV
Used to make extremely long, sequenced codes shorter. XX is the number of addresses to be written, YY is the offset between addresses, ???? is the amount to increment the value (VVVV). Note that this increment is signed, so values higher than 0x8000 will subtract from VVVV rather than being added. These can be preceded by any 'D' code type (EG 0xD0144604 0022) to enable them on demand. The code to be repeated is not limited to constant writes. Any 80/81/88/89 code type appearing below a '50' code should work. 3.0+

Software Hacks

Code Description
The following codes will work on a GS/AR v3.0+ with the code generator active.
81791DF6 ????
81791E02 ????
Lowest goto address (normally 0x80000400)
81791E06 ????
81791E12 ????
Highest goto address (normally 0x803FFFFF)
81791E32 ????
81791E36 ????
Lowest scroll to address (normally 0x80000400)
81791E3A ????
81791E3E ????
Highest scroll to address (normally 0x803FFFFF)
81791E42 ????
81791E4A ????
This is the address returned to when attempting to go to an invalid address (normally 0x80000400).
807FFDE7 000? Is controller active?
817FFDE8 ???? Button Pressed Data
817FFDEA ???? Joystick Data
817E9C98 ????
817E9C9A ????
Cursor X Coordinate
817E9C9C ????
817E9C9E ????
Cursor Y Coordinate
817E9CA0 ????
817E9CA2 ????
Cursor Mode
0x807E9D34 - 0x807E9D44 Text Searched For -- This can be used to turn Text Search into a string search. It will allows searching for any hex value higher than 0x1F. Anything less than 0x20 will crash it because these are special control bytes, not text. If the values are 0x41-0x5A, it will search for the value and the value + 0x20. This is due to the case insensitive searching; it searches both lowercase and uppercase.
Other Information
0x807C5C00 This is where active codes are stored when the code generator is on. See below for more info on editing the area.
0x80000204 This is where active codes are stored when the code generator is off. See below for more info on editing the area.

Code Handler Hacks

The code handler is what runs through active codes and keeps applying them. It can be altered with some assembly knowledge. The active codes list starts at 0x807C5C00 with expansion pack and 0x80000204 without it. Those who are familiar with assembly, might notice that the way the GS/AR writes each code to be handled if very inefficient. This also shows why the handler needs so much memory for active codes. The list ends when it hits a jump return to 0x80000120. If it doesn't find one, the game will crash. See Hacking Assembly (r4300i) for more information about using assembly on N64.

Opcode Arguments Comments
'80' Code Type (Constant 8-Bit Write)
LUI $K0,0xXXXX ;XXXX is the upper halfword of the address. With 0x801450D0 for example, the value would be 0x8014.
ORI $K0,$K0,0xYYYY ;YYYY is the lower halfword of the address. With 0x801450D0, that would be 0x50D0.
ADDIU $K1,$ZERO,0x00ZZ ;ZZ is the value to be written.
SB $K1,0x0000($K0) ;Writes the value ($K1) to the location specified ($K0).
'81' Code Type (Constant 16-Bit Write)
LUI $K0,0xXXXX ;XXXX is the upper halfword of the address. With 0x801450D0 for example, the value would be 0x8014.
ORI $K0,$K0,0xYYYY ;YYYY is the lower halfword of the address. With 0x801450D0, that would be 0x50D0.
ADDIU $K1,$ZERO,0xZZZZ ;ZZZZ is the value to be written.
SH $K1,0x0000($K0) ;Writes the value ($K1) to the location specified ($K0).
'88' Code Type (8-Bit Write on GS Button Press)
LUI $K0,0xBE40 ;Sets $K0 to the upper halfword of the GS button address (0xBE40).
ORI $K0,$K0,0000 ;Sets the lower halfword of the GS button address (0x0000). Those who know assembly will realize this was pointless.
LH $K1,0x0000($K0) ;Load the GS button value.
SYNC
ANDI $K1,$K1,0x0400 ;$K1 = $K1 AND 0x0400.
BNE $K1,$ZERO,0x0028 ;If GS button isn't being pressed, skip the 8-bit write.
LUI $K0,0xXXXX ;XXXX is the upper halfword of the address. With 0x801450D0 for example, the value would be 0x8014.
ORI $K0,$K0,0xYYYY ;YYYY is the lower halfword of the address. With 0x801450D0, that would be 0x50D0.
ADDIU $K1,$ZERO,0x00ZZ ;ZZ is the value to be written.
SB $K1,0x0000($K0) ;Writes the value ($K1) to the location specified ($K0).
'89' Code Type (16-Bit Write on GS Button Press)
LUI $K0,0xBE40 ;Sets $K0 to the upper halfword of the GS button address (0xBE40).
ORI $K0,$K0,0000 ;Sets the lower halfword of the GS button address (0x0000). Those who know assembly will realize this was pointless.
LH $K1,0000($K0) ;Load the GS button value.
SYNC
ANDI $K1,$K1,0x0400 ;$K1 = $K1 AND 0x0400.
BNE $K1,$ZERO,0x0028 ;If GS button isn't being pressed, skip the 16-bit write.
LUI $K0,0xXXXX ;XXXX is the upper halfword of the address. With 0x801450D0 for example, the value would be 0x8014.
ORI $K0,$K0,0xYYYY ;YYYY is the lower halfword of the address. With 0x801450D0, that would be 0x50D0.
ADDIU $K1,$ZERO,0xZZZZ ;ZZZZ is the value to be written.
SH $K1,0x0000($K0) ;Writes the value ($K1) to the location specified ($K0).
'D0' Code Type (8-Bit If Equal)
LUI $K0,0xXXXX ;XXXX is the upper halfword of the address to be checked.
ORI $K0,$K0,0xYYYY ;YYYY is the lower halfword of the address to be checked.
LB $K0,0x0000($K0) ;Loads the value from the address to be checked.
ADDIU $K1,$ZERO,0x00ZZ ;ZZ is the value to be compared to.
BNE $K0,$K1,0x0024 ;If value loaded from memory is not equal to the value specified by the code, then skip executing the following code.
'D1' Code Type (16-Bit If Equal)
LUI $K0,0xXXXX ;XXXX is the upper halfword of the address to be checked.
ORI $K0,$K0,0xYYYY ;YYYY is the lower halfword of the address to be checked.
LH $K0,0x0000($K0) ;Loads the value from the address to be checked.
ADDIU $K1,$ZERO,0xZZZZ ;ZZZZ is the value to be compared to.
BNE $K0,$K1,0x0024 ;If value loaded from memory is not equal to the value specified by the code, then skip executing the following code.
'D2' Code Type (8-Bit If Not Equal)
LUI $K0,0xXXXX ;XXXX is the upper halfword of the address to be checked.
ORI $K0,$K0,0xYYYY ;YYYY is the lower halfword of the address to be checked.
LB $K0,0x0000($K0) ;Loads the value from the address to be checked.
ADDIU $K1,$ZERO,0x00ZZ ;ZZ is the value to be compared to.
BEQ $K0,$K1,0x0024 ;If value loaded from memory is not equal to the value specified by the code, then skip executing the following code.
'D3' Code Type (16-Bit If Not Equal)
LUI $K0,0xXXXX ;XXXX is the upper halfword of the address to be checked.
ORI $K0,$K0,0xYYYY ;YYYY is the lower halfword of the address to be checked.
LH $K0,0x0000($K0) ;Loads the value from the address to be checked.
ADDIU $K1,$ZERO,0xZZZZ ;ZZZZ is the value to be compared to.
BEQ $K0,$K1,0x0024 ;If value loaded from memory is not equal to the value specified by the code, then skip executing the following code.
List End
LUI $K0,0x8000 ;$K0 = 0x80000000
ORI $K0,$K0,0x0120 ;$K0 = 0x80000120
JR $K0 ;Jump to the address stored in $K0.
ADD $ZERO,$ZERO,$ZERO ;One of the many ways to do nothing.

Xploder64 / Xplorer64 Code Types

Type Description
RAM Writes
8-Bit
80XXXXXX 00??
Writes 1 byte (??) to the specified address (XXXXXX) repeatedly.
16-Bit
81XXXXXX ????
Writes 2 bytes (????) to the specified address (XXXXXX) repeatedly.
8-Bit XP Button
88XXXXXX 00??
Writes 1 byte (??) to the specified address (XXXXXX) each time the XP Button is pressed.
16-Bit XP Button
89XXXXXX ????
Writes 2 bytes (????) to the specified address (XXXXXX) each time the XP Button is pressed.
8-Bit Write Once
F0XXXXXX 00??
Writes 1 byte (??) to the uncached address (XXXXXX) only once. These are most often used to disable certain types of protection that some games use to disable cheat devices.
16-Bit Write Once
F1XXXXXX ????
Or
2AXXXXXX ????
Writes 2 bytes (????) to the uncached address (XXXXXX) only once. These are most often used to disable certain types of protection that some games use to disable cheat devices.
Conditional Codes
8-Bit Equal To
D0XXXXXX 00??
YYYYYYYY ZZZZ
If the byte at XXXXXXX is equal to ??, then the code on the next line is executed.
16-Bit Equal To
D1XXXXXX ????
YYYYYYYY ZZZZ
If the 2 bytes at XXXXXXX are equal to ????, then the code on the next line is executed.
Special Codes
Enabler
3CXXXXXX ????
The exact effect of this code type is still a mystery.

Software Hacks

Code Description
The following codes were tested on an Xploder64 v1.000E
817527FA 0000 Change Lowest address accessible in the Memory Viewer to 0x80000000 (normally 0x80000400).
817527F2 807F Change Lowest address accessible in the Memory Viewer to 0x807FFFFF (normally 0x803FFFFF).
81757B48 XXXX
81757B4A YYYY
Set The location of the Memory Viewer to XXXXYYYY.

Code Handler Hacks

The code handler is what runs through active codes and keeps applying them. The following is a an incomplete listing of the assembly the code handler uses.

Opcode Arguments Comments
'80' Code Type (Constant 8-Bit Write)
LUI $K0,0xXXXX ;XXXX is the upper halfword of the address. With 0x801450D0 for example, the value would be 0x8014.
ORI $K1,$ZERO,0x00ZZ ;ZZ is the value to be written.
SB $K1,0xYYYY($K0) ;YYYY is the lower halfword of the address. With 0x801450D0, that would be 0x50D0.
'81' Code Type (Constant 8-Bit Write)
LUI $K0,0xXXXX ;XXXX is the upper halfword of the address. With 0x801450D0 for example, the value would be 0x8014.
ORI $K1,$ZERO,0xZZZZ ;ZZZZ is the value to be written.
SH $K1,0xYYYY($K0) ;YYYY is the lower halfword of the address. With 0x801450D0, that would be 0x50D0.

Encryption

Unlike the other devices available for cheating on N64, Xploder64 has encrypted codes. It supports some GS/AR code types, but most of the preloaded codes are encrypted for some reason. Simple encryption though...

Encryption Algorithm
A0A1A2A3 D0D1
A0 = (a0 XOR 0x68)
A1 = (a1 XOR 0x81) - 0x2B
A2 = (a2 XOR 0x82) - 0x2B
A3 = (a3 XOR 0x83) - 0x2B
D0 = (d0 XOR 0x84) - 0x2B
D1 = (d1 XOR 0x85) - 0x2B

Alternate:
A0 = (a0 XOR 0x68)
A1 = (a1 XOR 0x01) - 0xAB
A2 = (a2 XOR 0x02) - 0xAB
A3 = (a3 XOR 0x03) - 0xAB
D0 = (d0 XOR 0x04) - 0xAB
D1 = (d1 XOR 0x05) - 0xAB
Decryption Algorithm
A0A1A2A3 D0D1
A0 = (A0 XOR 0x68)
A1 = (A1 + 0x2B) XOR 0x81
A2 = (A2 + 0x2B) XOR 0x82
A3 = (A3 + 0x2B) XOR 0x83
D0 = (D0 + 0x2B) XOR 0x84
D1 = (D1 + 0x2B) XOR 0x85

Alternate Method:
A0 = (A0 XOR 0x68)
A1 = (A1 + 0xAB) XOR 0x01
A2 = (A2 + 0xAB) XOR 0x02
A3 = (A3 + 0xAB) XOR 0x03
D0 = (D0 + 0xAB) XOR 0x04
D1 = (D1 + 0xAB) XOR 0x05

Activators

Activators are used to execute codes ONLY when a particular condition is met. This can be used to prevent problems with certain effects being active at the wrong time, give the user the ability to turn a code on/off without resetting the console, etc. This is done with the D0,D1,D2, and D3 code types.

Example:
D0064F31 0020
800326E2 0001
The code "800326E2 0001" is only executed when the value at 0x00064F31 is equal to 0x20.

Button Activators

Button activators allow you to turn codes on/off by pressing a button or combination of buttons on the controller. One of the most common uses for this are moon jump codes. The user holds a button (typically L) to rise up and lets go to fall. They work by checking the location in memory where the game keeps track of what controller buttons are being pressed at any given time. This is almost always done with a halfword (16-bit) value. Each button is represented by 1 bit in this value. These activators appear on websites in 3 variations. The digits are as follows:


Value Button
Activator 1 (8-Bit) Digits
0x00 No Buttons
0x01 D-Pad Right
0x02 D-Pad Left
0x04 D-Pad Down
0x08 D-Pad Up
0x10 Start
0x20 Z
0x40 B
0x80 A
Activator 2 (8-Bit) Digits
0x00 No Buttons
0x01 C-Right
0x02 C-Left
0x04 C-Down
0x08 C-Up
0x10 R
0x20 L
Dual Activator (16-Bit) Digits
0x0000 No Buttons
0x0100 D-Pad Right
0x0200 D-Pad Left
0x0400 D-Pad Down
0x0800 D-Pad Up
0x1000 Start
0x2000 Z
0x4000 B
0x8000 A
0x0001 C-Right
0x0002 C-Left
0x0004 C-Down
0x0008 C-Up
0x0010 R
0x0020 L

To combine button values, simply add them together. Down+A would be 0x84, for example.

Control Stick Activators

Control stick activators are a little more complicated than button activators and significantly less useful. The control stick basically has X/Y coordinates, which the game keeps track of in memory. These are signed bytes or halfwords, usually found just above the button activator location in memory. The problem with using them the same as button activators is that it's so hard to duplicate exact values. However, you can use them with the D2/D3 code type to check that the stick is being pressed left/right, up/down, or both. Pushing up on the stick will be stored in memory as anything from 0x00-0x7F or 0x0000-0x7FFF in the case of games using 16-bit ones. Here's where it gets tricky. These are signed hex. Positive numbers indicate the stick is being pressed right/up, and negative values mean it's being pushed left/down. Values for commonly posted stick activators range as follows:

Range Direction
Activator 1 (8-Bit)
0x00-0x7F Right
0x80-0xFF Left
Activator 2 (8-Bit)
0x00-0x7F Up
0x80-0xFF Down
Activator 1 (16-Bit)
0x0000-0x7FFF Right
0x8000-0xFFFF Left
Activator 2 (16-Bit)
0x0000-0x7FFF Up
0x8000-0xFFFF Down
Dual Activator (16-Bit)
0x0000-0x007F Up
0x0080-0x00FF Down
0x0000-0x7F00 Right
0x8000-0xFF00 Left

Other Activators

Sometimes, a code only works on a particular level or should only be active when a certain event is happening. Using addresses other than controller data can sometimes be helpful in these cases. For example, if a user only wanted a code enabled on level 2 of a game they could use the level modifier as an activator. Say the level modifier address is 0x00024640, the value for level 2 is 0x02, and the code to enable only on that level is 0x8104856A 270F.

Code Comment
D0024640 0002 level modifier with an 8-bit equal to (D0) code type.
8104856A 270F code to be executed when level modifier is equal to 0x02.

Basic Notes on N64 Hacking

This section contains some introductory notes for new hackers to the system.

RAM

Out of the factory, the N64 has 4MB of RAM (0x00000000-0x003FFFFF). An expansion pack was later released to give the N64 an additional 4MB (0x00400000-0x007FFFFF) for a total of 8MB of RAM (0x00000000-0x007FFFFF). Games that take advantage of this extra memory are generally said be Hi-Res, while games that don't are referred to as Lo-Res.

Dynamic Addresses

Dynamic (random) addresses can be a problem on some N64 games, particularly with object/enemy hacking. This can really only be worked around with assembly hacks, but there are plenty of N64 games that are perfectly hackable using normal methods. Many N64 games will change the location of certain things on a per level basis, but the codes will always be the same for that level. Hackers should keep these things in mind.

Floating Point Values

Most N64 games use IEEE-754 float values to some extent (coordinates, timers), but some even use them for health and ammo values (100.0 for max health instead of 100). The majority of floats that normal users will have to deal with are stored as 32-bit values, however, there are a few games that use 64-bit (double precision). Star Wars Racer, for example uses a lot of double precision floats. This is good to remember in cases where a simple known value search should work and it doesn't; hopefully, it'll be remembered before the game and/or cheat device is smashed out of frustration.

Crashing

Having a game just freeze and refuse to run anymore while code searching is an all too common occurrence when hacking N64 games on the console. Some games are very hard to keep running long enough to hack more complex codes. This is one reason hacking with emulators is sometimes preferred over messing with the hardware. Games requiring a key code are especially notorious for crashing easily. Tip: Try not to break anything when theses things happen; N64 hardware is in limited supply these days.

Hacking With GS/AR Pro

Turn on the code generator in the "Start Game Options" menu of a v3.0+ GS/AR (expansion pack required) before starting a game to enable the code creation functionality of the device. While in the game, you can press the GS/AR button at any time to bring up the in-game menu. It's laid out as follows:

GS Pro: In-Game Menu

Code Generator

GS Pro: Code Generator GS Pro: Known Value Search GS Pro: Unknown Value Search GS Pro: Unknown Value Search

For those who have hacked before, this about the same as any other trainer. If hacking a value that's shown on screen, try Known Value Search. If it's a health bar or something, you'd use Unknown Value. Alright, here's the classic "health bar" example. With the health bar on the screen, press the GS button. Enter the code generator, and select Unknown Value Search. Move on down the menu and select "Start." Now return to the game, and lose some health. Press the GS button again and bring up the unknown value search menu again. This time, there's some new search options. Obviously, since health decreased, the one to choose is Less Than Last. After this, the View Results item is added to the menu. If there are a lot (and there probably are), repeat the losing health - Less Than Last combination to narrow it down. Occasionally just walking around without losing health and searching Equal To Last is a good way to drop some junk possibilities. Once the results are narrowed down (hopefully 30 or less), go into the view results menu.

View Search Results
GS Pro: View Results

The box on the left lists first 100 results found. The box on the right shows active codes, but only the ones from searching. Codes that were activated from the main GS menu before booting won't be listed here. The data displayed here is similar to actual codes, but is just a list of addresses and values. Notice the values aren't padded and the prefix is not 81 for 16-bit codes.

Controls:

Memory Editor

GS Pro: Memory Editor GS Pro: Memory Editor Options

Lets you edit RAM. Displays a typical hex editor interface (address, values, ASCII) at 8 bytes per line, 0x60 bytes per page, and usually gets cut off a little at the edges of the screen. Display starts at 0x80010000 and can go from 0x80000400 to 0x803FFFFF.

Controls:

Get Connected

See the PC Connection and Utilities section for notes on getting a GS/AR connected to the PC, if it was somehow skipped by. Remember to enable the code generator in order to utilize either of the following software trainers.

Official Hack Utilities

N64 Utils: Code Generator

This is a fairly simple, but effective, trainer that can be used while the GS/AR is connected to the PC. It should be noted that neither the trainer nor the in-game code generator can search in hi-res (0x80400000-0x807FFFFF) region. There is a patch that can allow it though. There are a few differences in this compared to the in-game code generator...

After getting a search going, the user has access to (surprise) the Results tab. This slightly resembles the one in the in-game code generator, but it's a little more user friendly. The hacker can test search results or manually enter codes to test/activate.

N64 Utils: Results

Game Software Code Creator (GSCC)

Game Software Code Creator is slightly more advanced than the N64 utils. There are some special options to tweak with in the configuration. The most notable is a checkbox that says "Treat Values As Signed." This means that all values read, whether 8-bit or 32-bit are sign extended. The typical Hex/Decimal input option is there too. There are far too many search options to try to document them all here, but the help file with the program explains most of them anyway; hence, new users should read that help file because it's actually useful. The regular Known Value search is a little hard to spot though. It's part the Advanced Searching Options frame. Check the box beside "Do," locate "Equal To" dropdown list, and enter a value in the box beneath it.

Game Software Code Creator: Dump Window Possibilities

The Possibilities window looks similiar the the N64 Utils reults window. Same basic features.

Game Software Code Creator: Possibilites Window RAM Edit

The last window for hacking is RAM Edit. The main purpose of this is to view/edit memory just like the Memory Editor in the GS/AR can. There a few nifty options.

Game Software Code Creator: RAM Edit Window

Hacking With Xploder64

Xploder64: In-Game Menu

Code Finder

Xploder64: Code Finder

Memory Viewer

Xploder64: Memory Viewer

Test Codes

Xploder64: Test Codes

Hacking With Emulators

Hacking codes with an emulator can be easier with some games, since they're so buggy on the hardware. It doesn't make the codes any easier to find, it just makes games with crap programming more stable (in most cases). Now the downside to N64 hacking with emulators is there are no good emulators with the search tools needed. Nemu has a simple known value and text search, which cannot be continued to narrow results. That makes it sort of useless for most purposes, but it comes in handy to some of us on occasion. Nemu is also important because it's currently the only N64 emulator with a debugger, a must have for assembly hackers. More on that later. No other emulators currently have anything resembling built-in search tools. So how is it done? Well, there are 3 ways right now...

Renegade

Renegade is program by itself. It can be used to grab the N64 RAM from an emulator. It can also be used to compare save state files from emulators it doesn't support. This is just the tip of the iceberg, as far as Renegade goes. It has many features that don't just apply to N64. See Renegade section of Generic Code Hacking and the program's readme file for more information.

Parasytic Cheat Search (PCS)

Parasytic Cheat Search

PCS is plugin for Project64. It shows up as a video plugin under PJ64's settings. Set it as the plugin and configure it to use an actual video plugin. Choosing Configure Graphics from the Options menu while a game is running will bring up the PCS window (shown above) instead of the PCS config.

Save State Searching/Comparing

Sometimes an emulator's memory can't be accessed for whatever reason, or it just isn't supported by programs made for doing so. Save states, which most emulators have the option for, are the equivalent of an RAM dump with a few extra bytes added. The following is some quick info about the more popular N64 emulators' save states.

Hacking Ammo - The Easy Way and the Hard Way

An Infinite Ammo type code is almost always a simple task, but some games have a few tricks...

The Typical Approach

For the majority of games, finding ammo is a simple task. Do a known value search for the current amount of ammo, cap somebody, search for the new value, repeat. Test results, and enjoy Infinite Ammo.

Complicating Things

When the typical method of finding ammo fails, this may mean the game is using a float value. Floats are 32-bit hex values, which the N64's co-processor reads as decimal numbers (like 100.0). These can be found by using a 16/32-bit unknown value search and just doing less than searches while losing ammo. This is how it was done in the old days. However, there is a shortcut, and it's called FloatConvert. Now, say the game is Star Wars Shadows of the Empire. Dash has 10 Seekers. Punch 10 (or 10.0) into FloatConvert and click Convert to Hex. It spits out 0x41200000. Now do a 32-bit search for that value, shoot something, and repeat. Results will probably be down to one or two after the second search, so try them. If the result is 0x801A7174, setting the upper 16-bits there will change Dash's ammo. Use FloatConvert to find a suitable value, like 100.0 (0x42C80000). Writing a 32-bit value on N64 requires two 16-bit codes:

811A7174 42C8
811A7176 0000
Writing the full 32-bits isn't required in most cases. The second line (lower 16-bits) can be omitted.

Hacking Enable Codes

FF Enablers

FF enablers are normally only used on games which utilize the expansion pack. They tell the device where to store active codes so that the cheating routines won't interfere with the game's normal operation. Basically, the FF code is just that address of an empty part of the memory for the GS/AR to use. This can't be found with the console. Get the game running in an emulator and save a couple of memory dumps (or just search). Search for 0 with the largest search type available in the trainer (32/64-bit recommended). Look for the biggest blocks of consecutive results that stay 0 throughout the game. The objective is to find at least 256 bytes that the game isn't using. The address where this empty area begins becomes the FF enabler (FF567890 0000 for instance).

MTC0 Enablers

Some games write to special registers in the system to disable the GS/AR. This is done by setting values to WatchLo and WatchHi, which the cheat devices require. Disabling these is done with an assembly hack, but very little assembly knowledge is actually needed to pull it off. GSCC actually has a feature to search for them automatically. The manual approach requires an emulator and some basic knowledge. Run the game long enough to boot up, and save a dump of the memory or open a search tool (like Renegade). Now use a 32-bit known value, in-range or wildcard search to find all instances of 0x40??9000 and 0x40??9800 where ?? is 0x80 to 0x9F. In a disassembler, these appear as MTC0 $xx,WatchLo and MTC0 $xx,WatchHi. Any instances of these need to be disabled by setting the address to 0x00000000 or just setting the upper half to 0x2400 as a shortcut. Say 0x80055684 is MTC0 $A0,WatchLo (0x40849000). An F1 code type is required to disable it.

Long Version
F1055684 0000
F1055686 0000
Short Version
F1055684 2400

Non-MTC0 Enablers

There are some games that attempt to disable cheat devices another way. These games write to some special parts of the memory which effect the functionality of cheat devices. Hacking these is going to seem a bit complicated to beginners, but there's not really an easier way; it's an assembly hack. See the N64 assembly or Assembly Hacking in the Generic Code Hacking section for help with these sort of hacks. Renegade has a few search options that could help locate possible enablers of this type, but that's hardly an accurate way to do it. One needs to understand what to look for and, perhaps more importantly, where to look. The basic idea here is to start at the entry point and look for opcodes storing to addresses below 0x80000400.

  1. First, the game's entry point must be located. This seems to be 0x80000400 on most games, but don't take that for granted. The correct way to find out is to open the ROM in a hex editor and go to 0x00000008. The 4 bytes there are the entry point, but they may be shown as little endian depending on the ROM format. Flip the bytes to get an actual address (0x80xxxxxx). There's the place to start in RAM. In Nemu, one can load the game and go to 0xB0000008 in the memory editor to see the bytes in the correct order without any messing around.
  2. Next, boot the game in an emulator with a debugger (Nemu > Plugins > Debugger: Commands), or get a RAM dump with another emulator and open it in Niew, LemASM, or another disassembler. Another option is to start the game in Nemu and dump use the Dump Memory feature to dump the memory as TEXT - Disassembled + PC.
  3. Now go to the entry point to see the start of an assembly routine. This routine isn't over until it reaches a JR $RA. To find the enabler, this entire routine must be searched through either by stepping with the debugger or reading through manually. When J/JAL jump opcodes appear follow those too (go to the address). When following jumps to subroutines, the hacker must follow through any jumps in the subroutines too, just as in the main one. Each one still ends the same way (JR $RA).
  4. Follow through the routine looking for ORI/ADDIU $XX,$XX,0xYYYY where YYYY is usually 0x0080, 0x0100, 0x0180, or 0x0190. When one of these is found, the hacker should then look at the previous few opcodes to see if there's an LUI $XX,0x8000. If this is the case, change the 0xYYYY to 0x120 using an F1 code type (EG F1000436 0120) and the protection will be nullified. See the example below.
Opcode Arguments Comments
Starting at 0x80000450 (each opcode is 32-bits)
LUI $V0,0x8000 ;$V0 = 0x80000000
ORI $V0,$V0,0x0180 ;$V0 = $V0 OR 0x180
SH $A1,0x0000($V0) ;Store $A1 to the address in $V0 (0x80000180) + 0x0000.
Enable Code
F1000456 0120

Forcing 4MB or 8MB Mode

Certain games need the expansion pack to be "hidden" from them to work with GS/AR. This is usually done with the EE000000 0000 code. The actual effect of that code is writing the 4 bytes at 0x80000318 to 0x00400000 the same way an "F1" code type would. That address sets the highest address the game is allowed to write. The code generator is automatically disabled when "EE" enablers are used though. This is why some people prefer to custom enablers with F1 codes and that same address. Some examples follow.

F0000319 0040 Force 4MB (low-res) mode.
F0000319 0080 Force 8MB (hi-res) mode.
F0000319 0078 Force the game into using most of the expansion pack, but 1/8th is left free for the GS/AR. It will think it's running 8MB mode. This is useful for hacking hi-res codes but should only be attempted with the PC utils, not the in-game code generator.

Other values can be used to give a game access to different amounts of memory. Some values will work better than others. Codes hacked with a game being forced to use less than the full 4MB or 8MB of memory may not work in full 4MB/8MB mode. If attempting to force 8MB mode with a value less than 0x80 causes the game to report that no expansion pack was found, the game is probably reading that location to ensure it's 0x00800000. This could be defeated by watching reads of 0x80000318 with a debugger as the game boots, and forcing or killing a conditional check. These can also be found by using the steps for Non-MTC0 Enablers (above) and looking for ORI/ADDIU $XX,$XX,0xYYYY or SB/SH/SW $XX,0xYYYY($ZZ) when YYYY is 0x0318. A conditional check shouldn't be very hard to spot. It would likely set a register (variable) to 0x00400000 or 0x00800000 and branch (jump) to another location accordingly. An example is shown below.

Opcode Arguments Comments
Starting at 0x80000420 (each opcode is 32-bits)
LUI $V1,0x8000 ;$V1 = 0x80000000
LW $A0,0x0318($V1) ;Load word from address ($V1) + 0x318 into $A0. $A0 would now contain the 32-bit value at 0x80000318.
LUI $T0,0x0080 ;$T0 = 0x00800000. This is what the value at 0x800000318 should be if the expansion pack exists.
BEQ $T0,$A0,0x800004B4 If $T0 is equal to $A0 then branch (jump) to 0x8000004B4. This means to go there if the expansion pack exists. If not, it continues on.
Change the opcode at 0x8000042C (BEQ) to force it to where it goes if the expansion pack is found.
BEQ $ZERO,$ZERO,0x800004B4 ;This says jump to 0x800004B4 if $ZERO equal $ZERO. Obviously, it does, so the game always thinks it's running 8MB mode. Notice when changing the opcode that only the upper 16-bits has changed, so the whole word need not be set.
Enable Code
F100042C 1000

Some games also try to force 8MB mode before checking for the expansion pack. To find these, walk through the whole entry point routine the same as the steps for Non-MTC0 Enablers above. This time look for ORI/ADDIU $XX,$XX,0xYYYY or SB/SH/SW $XX,0xYYYY($ZZ) where YYYY is anything from 0x0300 to 0x031F. Ignore any SB/SH/SW where $ZZ is $SP. For any others, look for an LUI $XX, 0x8000 or LUI $XX, 0xA000 just before it. NOP the opcode that's SB/SH/SW $XX,0xYYYY ($ZZ) by setting the whole 32-bits to 0x00000000 or just set the upper half to 0x2400.

Opcode Arguments Comments
Starting at 0x80000480 (each opcode is 32-bits)
LUI $V1,0x8000 ;$V1 = 0x80000000
ORI $V1,$V1,0x0318 ;$V1 = $V1 OR 0x318
SH $A0,0x0000($V1) ;Store $A0 to $V1 (0x80000318) + 0x0000.
Enable Code
F1000488 2400

Finding Activators

Button Activators

Button activators are relatively simple to hack. To do so, setup for a 16-bit known value search. Hold a button, and search for its value. Then hold a different button and search for its value. Repeat until only a few results remain. Most of these are probably button activators, as the majority of games have more than one. Testing is just a matter of using it as a 'D1' code type with an existing code. Activators for P2-P4 on multi-player games will usually appear 0x6 or 0x8 after the one for P1.

Control Stick Activators

While control stick activators could be hacked with greater/less searches with the stick pushed in a direction or centered, there's really no point. They're right beside most button activators in memory. Use a memory viewer to confirm by watching the values next to the activator address when the stick is being pressed in any direction or centered. It should be easy enough to see which bytes keep changing. Those bytes would be control stick activator 1 and 2 (or both as a 16-bit code).

Another Way To Find Activators

Another way to find button activators is to search for a special value in memory. Do a 32-bit known value search for 0xFF010401. This value appears with the main set of activators on most games, for some reason. There should only be about 4 results. If there are more, the 4 to look for are 8 bytes apart. Look at these in 16-bit form below for an easy breakdown.

0x800440B0 FF01
0x800440B2 0401
0x800440B4 0000 Player 1 button activator.
0x800440B6 0000 Player 1 control stick activator.
0x800440B8 FF01
0x800440BA 0401
0x800440BC 0000 Player 2 button activator.
0x800440BE 0000 Player 2 control stick activator.
0x800440C0 FF01
0x800440C2 0401
0x800440C4 0000 Player 3 button activator.
0x800440C6 0000 Player 3 control stick activator.
0x800440C8 FF01
0x800440CA 0401
0x800440CC 0000 Player 4 button activator.
0x800440CE 0000 Player 4 control stick activator.

N64 Assembly (R4300i)

Hacking the assembly of N64 games is no beginner task, but it's not too difficult to do some of the easier stuff. ASM hack can do a lot of things that normal codes can't. Getting around random memory in some games is the primary (and usually easiest) use though. There are cases where the ASM in a game is randomly placed in memory and some cases where a routine is always located in the same place, but only at certain times (like only while in a level). Having the GS/AR connected to the PC and using GSCC is the only way to make assembly codes with the console. On the emulation side of things, Nemu is currently the only N64 emulator that can be used to make ASM codes.

Documentation of the R4300i instruction set will be essential to new ASM hackers. The N64 Tool Kit is what most of us used to get started. There's also the R4300i Data Sheet. Each instruction in R4300i is 32-bits (aligned), but that doesn't always mean a GS/AR code will change all 32-bits. It's usually only necessary to change the bytes that are altered by whatever change the hacker is making.

Before starting any projects, hackers will need to have an R4300i assembler/disassembler at their disposal. Renegade has one. Other popular options include Niew and LemASM. Both have their limitations.

Processors and Co-Processors

R4300i utilizes two co-processors (COP0 and COP1) for special tasks. COP0 is something most hackers will never need to worry about because it's mainly for exception and virtual address handling, but COP1 is used for floating point operations. It has its own instructions that use opcodes like ADD.S/ADD.D for single and double precision math.

Registers

Regs are the variables used by the processor. Each register holds a 32-bit value. which can be sign-extended. Each co-processor has their own set of 31 registers. There are instructions to move/copy values from one set of registers to another. Most assemblers can display the main CPU registers by their names or by R0-R31. A list is provided below, with some notes.

Main CPU (GPR) COP0 COP1 (FPR)
R0/$ZERO Index FPR0/F0
R1/$AT Random FPR1/F1
R2/$V0 EntryLo0 FPR2/F2
R3/$V1 EntryLo1 FPR3/F3
R4/$A0 Context FPR4/F4
R5/$A1 PageMask FPR5/F5
R6/$A2 Wired FPR6/F6
R7/$A3 Reserved FPR7/F7
R8/$T0 BadVAddr FPR8/F8
R9/$T1 Count FPR9/F9
R10/$T2 EntryHi FPR10/F10
R11/$T3 Compare FPR11/F11
R12/$T4 Status FPR12/F12
R13/$T5 Cause FPR13/F13
R14/$T6 EPC FPR14/F14
R15/$T7 PRevID FPR15/F15
R16/$S0 Config FPR16/F16
R17/$S1 LLAddr FPR17/F17
R18/$S2 WatchLo FPR18/F18
R19/$S3 WatchHi FPR19/F19
R20/$S4 XContent FPR20/F20
R21/$S5 Reserved FPR21/F21
R22/$S6 Reserved FPR22/F22
R23/$S7 Reserved FPR23/F23
R24/$T8 Reserved FPR24/F24
R25/$T9 Reserved FPR25/F25
R26/$K0 PErr FPR26/F26
R27/$K1 CacheErr FPR27/F27
R28/$GP TagLo FPR28/F28
R29/$SP TagHi FPR29/F29
R30/$S8 ErrorEPC FPR30/F30
R31/$RA Reserved FPR31/F31

Notes:

Routines, Jumps, and Branches

Routines are like functions in PC programing languages. They can call other functions and get rather confusing to follow. Functions are called in R4300i by jumping to a specific address with a J/JAL/JR/JALR instruction. Routines usually end with JR $RA. The return location is the address in $RA. Branch instructions are conditional checks used to skip parts of a routine based on a condition being true or false. Jumps and branches all have a delay slot. This means they execute the instruction immediately following them before going to the address given.

NOPs

NOP instructions do absolutely nothing. Yes, nothing. NOP is actually pseudo instruction. On N64 it assembles as SLL $ZERO,$ZERO,0x00. However, there's a shortcut to NOP anything by only changing the upper 16-bits. 0x2400XXXX is a Short NOP. The XXXX can be anything, which is why it can be done with a single 16-bit code. What the 0x2400 does is change the instruction to ADDIU $ZERO,$ZERO,0xXXXX, essentially making it do nothing because $ZERO can't be changed. This is useful for making shorter ASM hacks in a lot of cases.

Breakpoints

Breakpoints are used to find the assembly that reads/writes to a specific memory location or to find out when an instruction is executed. When a break occurs, the game halts until the user chooses to continue. Breakpoints come in 3 types, each with a purpose. Read breakpoints (BPR) cause the game to halt when the location being watched is read from by assembly. Write breakpoints (BPW) halt the game when an address being watched is written to. When setting read/write breakpoints, a previously hacked code is needed. This is the address to watch in order to make an ASM hack. Breakpoints on execute (BPX) are used to halt the system when CPU executes the instruction at the address being watched. These are typically used once a BPR/BPW has already been done and the user wants to see what's going on at a certain point in the routine.

Setting Read/Write Breakpoints on GSCC GSCC: Set BP Dialog
  1. With the game running, open GSCC and go to RAM Edit.
  2. Click Set BP.
  3. Enter the address to breakpoint on in the box.
  4. Tick the checkbox for the type of breakpoint desired (read, write, or both), and click Set BP. Auto Resume is optional.
  5. A new dialog pops up telling the user to click Yes when the game halts.
  6. Now cause the address to change or be read. For example, if it's a BPW on the ammo address, shoot the gun so the game has to subtract a bullet.
  7. When the game halts, click Yes. A Notepad window will open showing vital information about the ASM at the time of the breakpoint. The text file is a list of the registers at the time the break occurred, as well as the location of the assembly that caused the break ("pc").
  8. Now the game should resume if Auto Resume was checked. If not, try Shift+F9 or go to Debug > Resume. Some games will crash at this point, so don't be surprised if a reboot is in order.
BPX with GCCC

GSCC lacks the ability to set breakpoints on execute, but it's still possible to get the effect of one.

  1. Halt the game and open RAM Edit. Go to the address where the BPX is wanted.
  2. Change the 8 bytes starting at that address to 0x3C1B8000AF7B0060. Keep track somewhere of what they originally were, as changing the values back might allow the routine to progress normally again.
  3. Set a BPW as the instruction above show, and resume the game.
  4. When it halts again, the BPX has occurred.
  5. After the Notepad window pops up, the user is free to restore the original values at that address and resume if needed.
Setting Read/Write Breakpoints on Nemu Nemu: Setting a BPW
  1. Open the Memory Viewer (Plugins > Debugger: Memory).
  2. Click the checkbox(es) desired for the Watch type on set.
  3. Go to the address to BPR/BPW on, then rightclick the value shown for it. The value changes color based on the watch type set.
BPX with Nemu Nemu: Setting a BPX
  1. Open the Commands window (Plugin > Debugger: Commands).
  2. There's an empty column to the left of the addresses. Click there beside an address to set BPX on that address.

TLB Mapping

Some games are difficult to ASM hack because they use virtual addresses. The virtual addresses are mapped to physical addresses through the translation lookaside buffer (TLB). Currently, the only way to work around the TLB is to view the mapped address in the memory viewer (Nemu)/RAM Edit (GSCC) to get the 32-bit hex value of the instruction where the break occurred while the game is still halted. Then search for it in the memory, checking each result in the memory viewer against the surrounding bytes at the TLB mapped address until the routine is found. Keep in mind this won't work on Goldeneye, because the physical location of most of the assembly changes randomly each time a level is loaded.

Using Niew

To Do

Using LemASM

To Do

Using Renegade's Assembly Tools

To Do

Example Assembly Hacks

Targeting Specific Players

Super Smash Brothers - Invincible/Untouchable P1

Some of the player data in SSB changes location based on what arena/mode is being played, etc. This is a problem for those of us hacking the game, but it's not a huge problem in this case. To get started, take a known location of the invincibility status modifier for P1. Peach's castle (vs mode) is 0x8025E6FF, for example. Setting a BPW on this yields 0x800E8AD8.


Looks simple enough, but BPX on it to find that it's not reading only P1. It reads ALL players. Now note the pointer (base address) it's loading from when reading P1's invincible status ($A1=0x8025E150). Do a 32-bit RAM search for that value to find possible pointers, then check other levels to verify which pointer address accurately points to P1's data all the time (0x80130D84). Now back on our routine that's reading invincible status, find a place to jump out. There's a branch right where this is taking place, so a jump would need to occur a few opcodes before this. Keeping in mind that $A1 needs to be set to a player pointer, so it can be checked by out new code. Scroll up a few opcodes to find where $A1 was set. It's at 0x800E8AC0. Also notice that ugly bit of code at 0x800E8AC8. It loads $RA there, so doing a JAL after that won't work out too well. Let's just jump from 0x800E8AC0 then. Remember to load $A1 in this subroutine first though, since we're replacing that op.


Opcode Arguments Comments
.ORG 0x000E8AC0
JAL 0x00000060
.ORG 0x00000060
LW $A1,0x001C($SP)
LUI $AT,0x8013
LW $AT,0x0D84($AT) ;Load the consistent P1 pointer.
ADDIU $A0,$ZERO,0x0002 ;Set the value to write to P1's invincibility status.
BEQL $A1,$AT,0x00000078 ;Compare the current pointer to P1's pointer. Only write invincible if this is P1.
SW $A0,0x05AC($A1) ;Write invincible.
JR $RA
NOP

That's one way to do it. Looking back on this hack, it wasn't a very good one, but it works. It can be done shorter by simply loading the P1 pointer and storing to it.


Opcode Arguments Comments
.ORG 0x000E8AC0
JAL 0x00000060
.ORG 0x00000060
LUI $AT,0x8013
LW $AT,0x0D84($AT) ;Load the consistent P1 pointer.
ADDIU $A0,$ZERO,0x0002 ;Set the value to write to P1's invincibility status.
SW $A0,0x05AC($AT)
JR $RA
LW $A1,0x001C($SP)

This ends up 14 lines of codes vs 17. It could possibly be done even shorter on some games by setting a BPR on that constant P1 pointer address (0x80130D84) and finding a routine that only reads P1. It won't work that way on this game though because there aren't any constant reads. Something to keep in mind on other games though.

810E8AC0 0C00
810E8AC2 0018
81000060 3C01
81000062 8013
81000064 8C21
81000066 0D84
81000068 2404
8100006A 0002
8100006C AC24
8100006E 05AC
81000070 03E0
81000072 0008
81000074 8FA5
81000076 001C

Jesus Mode (Walk on Water)

Here's how the original Jesus Mode code was hacked (based on a post by Parasyte). In Mario 64, the engine determines whether Mario should walk or swim based on Mario's position relative to the water level. If Mario is below the water level, he is put into swim mode.

This first thing to do is to determine how the game decides when Mario is touching the ground. The easiest way to do this is to watch the Mario's "action" (0x8033B17C). Jumping into the air, then setting a BPW on that location causes the game to break when Mario hits the ground. The break occurs at 0x80252E18. Stepping out of the routine (finding the jr $ra which is at 0x80252E54 here), and scrolling up to find that the jump (jr $t6) is part of a jump table. The table contains our 0x8026B4B0 in index 1, so that is the value we want. $t6 contains the address of a routine to jump to depending on what even is occurring. t6 is 0x8026B4B0 when Mario lands on the ground. Now we need to determine how the game chooses $t6. Scrolling upwards, $t6 is set at 0x8026B474 (LW $t6, 0x001C ($sp)), by loading from the stack. This stack location is set at 0x8026B470 (SW $v0, 0x001C($sp)). $v0 is always used as the return value for subroutines that return integers. Just above at 0x8026B468 is that routine. We want $v0 to be 1, because that is the index of the jump table we want to force. So we must look inside 0x8026B468 (JAL 0x80256B24) to see where $v0 is set to 1.

Nothing of note occurs until 0x80256CBC (LW $v0, 0x0018 ($sp)). This happens to be the last instruction before exiting (JAL 0x8037897C). The next task is to find how 0x0018($sp) is set. Scrolling up, 0x80256BD4 does this (SW $t4, 0x0018($sp)), with $t4 being set in the previous instruction (LW $t4, 0x001C($sp)). Scrolling up to determine how that is set, we find 0x80256BC0 does this (SW $v0, 0x001C (SP)). Again, $v0 is the return value of a subroutine. The previous subroutine occurs at 0x80256BB8 (JAL 0x802560AC). We must find where inside this subroutine $v0 is set.

Inside this subroutine, $v0 is set to 1 at two different places: 0x80256180 (ADDIU $v0, $r0, 0x0001) and 0x80256274 (ADDIU $v0, $r0, 0x0001). Setting a BPX on each and having Mario jump and hit the ground, 0x80256274 hits. Now the task is to figure out how the game determines when this occurs. Scrolling up to find a branch that skips this instruction we find 0x80256200 (BC1F 0x80256278). Setting a BPX on this will determine that this instruction breaks as soon as Mario jumps; it occurs when he falls. This instruction is checking to see if Mario has hit solid ground yet. Now we need to figure out how the game tells. Scrolling up we find a comparison at 0x802561f8 (C.LE.S $f8, $f10). This is the comparison used to figure out if Mario has hit the ground or not when he falls.

Set a BPX at 0x802561f8 at watch the registers that instruction is comparing. $f8 decreases as Mario falls and increases as he rises; it's his Y-coordinate. Therefore, $f10 must be the coordinate of the solid ground. The next step is to determine how $f10 is set. Backtracing, we find that at 0x802561f4, $f10 is loaded (LWC1 $f10, 0x0028($sp)) and at 0x802561D0, $f4 is stored into that same place (SWC1 $f4, 0x0028($sp)). However above this, at 0x802561C4, there is a branch (BC1F 0x802561EC), which means the stack location can be set elsewhere. Setting a BPX on this location does not break. The other possible stack write location is way up a 0x80256110 (SWC1 $f0, 0x0028($sp)). Just as $v0 is the integer return value, $f0 is the floating-point return value. Just above here is a subroutine (JAL 0x80381900).

Inside the subroutine, f0 is loaded from the stack at 0x803819B8 (LWC1 $f0, 0x002C($sp)). Scrolling up to 0x80381A84, we find that the pointer to this stack location is stored into $t6 (ADDIU $t6, $sp, 0x002C). We now know that the game stores the coordinate for solid ground below Mario to that address. The question is: how? Setting a breakpoint on 0x80381A88, we find the exact pointer that is loaded into $t6. For this example it's 0x80206BAC, but it will be different every time. Setting a watchpoint on that address leads to 0x80381764.

Now that we know where the game sets the coordinate of the solid ground, we can complete the hack. Just change the value of the coordinate if Mario's Y-coordinate is below the water-level, forcing him to land on solid ground. The hack simply involves replacing the swc1 instruction with a jump into unused RAM where the coordinate is replaced.

Opcode Arguments Comments
lui $a0, 0x8034
lh $a0, 0xB1E6($a0) ; Load water level
mtc1 $a0, $f6 ; Move it to cop1
nop
cvt.s.w $f4, $f6 ; Convert it to a floating point number
c.lt.s $f18, $f4
nop
bc1f end ; if (waterlevel > ground_y)
nop
mov.s $f18, f4 ; ground_y = waterlevel
end:
j 0x8038176C
swc1 $f18, 0x0000($t8) ; Taken from the break out location
Mario walks on water

Code:
81381764 0800
81381766 0024
81000090 3C04
81000092 8034
81000094 8484
81000096 B1E6
81000098 4484
8100009A 3000
810000A0 4680
810000A2 3120
810000A4 4604
810000A6 903C
810000AC 4500
810000AE 0002
810000B4 4600
810000B6 2486
810000B8 080E
810000BA 05DB
810000BC E712