Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/n64decomp/sm64/llms.txt

Use this file to discover all available pages before exploring further.

The SM64 decompilation exposes two layers of configuration. Runtime behaviour — bug fixes, hardware feature flags, screen dimensions, and stack sizes — is controlled by preprocessor defines in include/config.h. The toolchain and ROM target are controlled by Makefile variables that you pass on the make command line. This page documents both layers in full.

include/config.h

config.h is described in its own header comment as “a catch-all file for configuring various bugfixes and other settings in SM64.” Every define here is evaluated at compile time via the C preprocessor.

Bug fixes

Nintendo introduced a number of bug fixes in regional versions released after the original Japanese launch. Each fix is individually togglable via a BUGFIX_* define. The default value for each define is a logical OR expression: it evaluates to 1 (enabled) whenever the active VERSION_* token matches one of the listed versions, and 0 otherwise.
All of the bug fixes listed below were introduced in the US version and carried forward into EU, Shindou (SH), and iQue (CN). None of them are active for the JP version by default. If you are building a JP ROM and want the fixes anyway, you can override the defines in your own header or directly in config.h.
#define BUGFIX_MAX_LIVES (0 || VERSION_US || VERSION_EU || VERSION_SH || VERSION_CN)
Fixes a bug where obtaining over 999 coins sets the number of lives to 999 (or wraps to -25 depending on interpretation). Active for all non-JP versions.
#define BUGFIX_KING_BOB_OMB_FADE_MUSIC (0 || VERSION_US || VERSION_EU || VERSION_SH || VERSION_CN)
Fixes a bug where the boss music does not fade out after defeating King Bob-omb. Active for all non-JP versions.
#define BUGFIX_KOOPA_RACE_MUSIC (0 || VERSION_US || VERSION_EU || VERSION_SH || VERSION_CN)
Fixes a bug in Bob-omb Battlefield where entering a warp stops the Koopa race music prematurely. Active for all non-JP versions.
#define BUGFIX_PIRANHA_PLANT_STATE_RESET (0 || VERSION_US || VERSION_EU || VERSION_SH || VERSION_CN)
Fixes a bug where Piranha Plants do not reset their action state when the player exits their activation radius, causing them to stay in the wrong animation or attack state. Active for all non-JP versions.
#define BUGFIX_PIRANHA_PLANT_SLEEP_DAMAGE (0 || VERSION_US || VERSION_SH || VERSION_CN)
Fixes a bug where sleeping (idle) Piranha Plants can damage Mario if he bumps into them, despite appearing dormant. Active for US, SH, and CN versions. Not active for EU.
#define BUGFIX_STAR_BOWSER_KEY (0 || VERSION_US || VERSION_EU || VERSION_SH || VERSION_CN)
Fixes a bug that causes the game to display a star-collect animation when Mario grabs a key in Bowser battle stages instead of the correct key-collect animation. Active for all non-JP versions.
#define BUGFIX_DIALOG_TIME_STOP (0 || VERSION_US || VERSION_EU || VERSION_SH || VERSION_CN)
Fixes a bug that enables Mario’s time-stop state during dialog even when he is not yet ready to speak, which could cause animation glitches. Active for all non-JP versions.
#define BUGFIX_BOWSER_COLLIDE_BITS_DEAD (0 || VERSION_US || VERSION_EU || VERSION_SH || VERSION_CN)
Fixes a bug that causes Mario to still collide with Bowser in Bowser in the Sky (BitS) after Bowser has been defeated and his object removed. Active for all non-JP versions.
#define BUGFIX_BOWSER_FALLEN_OFF_STAGE (0 || VERSION_US || VERSION_EU || VERSION_SH || VERSION_CN)
Fixes a bug where Bowser would not reset his speed when falling off the stage, and adds missing boundary checks. Active for all non-JP versions.
#define BUGFIX_BOWSER_FADING_OUT (0 || VERSION_US || VERSION_EU || VERSION_SH || VERSION_CN)
Fixes a visual bug where Bowser’s render state becomes incorrect during the fade-out animation that plays after his defeat. Active for all non-JP versions.

Hardware feature flags

ENABLE_RUMBLE

#define ENABLE_RUMBLE (0 || VERSION_SH || VERSION_CN)
Enables Rumble Pak support. The Shindou (SH) and iQue (CN) versions of the game were the only official releases to include rumble support. This define gates all rumble-related code paths. Set it to 1 explicitly if you want to add rumble support to a JP, US, or EU build.

Screen dimensions

#define SCREEN_WIDTH  320
#define SCREEN_HEIGHT 240
These constants define the N64 framebuffer resolution in pixels. They are used throughout the rendering code wherever pixel coordinates are calculated — scissor rectangles, viewport setup, text positioning, and so on. Do not change these values unless you are targeting a non-standard video mode, as they are deeply embedded in the renderer.

Stack sizes

#define IDLE_STACKSIZE   0x800    // 2 KB  — idle thread stack
#define STACKSIZE        0x2000   // 8 KB  — main game thread stack
#define UNUSED_STACKSIZE 0x1400   // 5 KB  — unused thread stack
These control the stack sizes allocated for the N64 OS threads. STACKSIZE (8 KB) is the stack for thread5_game_loop, the main game thread. IDLE_STACKSIZE (2 KB) is for the idle thread. UNUSED_STACKSIZE (5 KB) is allocated but not actively used by any thread in the shipped code.
Increasing STACKSIZE reduces the amount of memory available for other allocations. Decreasing it risks stack overflow crashes in deeply nested call paths. Only change these values if you have a specific, measured need.

Border height

#ifdef TARGET_N64
  #ifndef VERSION_EU
    #define BORDER_HEIGHT 8   // NTSC top/bottom border (non-EU N64)
  #else
    #define BORDER_HEIGHT 1   // PAL border (EU N64)
  #endif
#else
  #define BORDER_HEIGHT 0     // No border (PC ports and non-N64 targets)
#endif
BORDER_HEIGHT controls the number of blank scanlines added at the top and bottom of the screen. On NTSC hardware (JP, US, SH, CN) this is 8 pixels; on PAL hardware (EU) it is 1 pixel. When building for a non-N64 target (TARGET_N64 = 0), the border is removed entirely since there is no hardware blanking requirement.

Makefile build variables

These variables are passed on the make command line. For example:
make VERSION=eu GRUCODE=f3dex2 NON_MATCHING=1
Run make clean before changing any build variable that affects code generation to avoid stale objects.

VERSION

VERSION ?= us
Selects which regional release of the game to build. The VERSION token controls which VERSION_* preprocessor define is set, which in turn gates version-specific code in config.h and elsewhere.
ValueRegionYearNotes
jpJapan1996Original release. Most BUGFIX_* defines are inactive.
usNorth America1996Default. All major bug fixes active.
euPAL / Europe1997Adds multilingual text support (English, German, French).
shJapan (Shindou)1997Includes Rumble Pak support.
cnChina (iQue)2003iQue Player port. Includes Rumble Pak support. Uses a different linker and compiler for some files.
The build target is named sm64.<VERSION>.z64, placed in build/<VERSION>/.

GRUCODE

GRUCODE ?= f3d_old   # jp, us default
GRUCODE ?= f3d_new   # eu, sh, cn default
Selects which RSP microcode (graphics binary) to embed in the ROM. The microcode determines which GBI (Graphics Binary Interface) macros are available at runtime.
ValueNameDefault forNotes
f3d_oldFast3D (original)jp, usSets F3D_OLD=1.
f3d_newFast3D 2.0Heu, sh, cnSets F3D_NEW=1.
f3dexFast3DEXSets F3DEX_GBI=1 and F3DEX_GBI_SHARED=1.
f3dex2Fast3DEX2Sets F3DEX_GBI_2=1 and F3DEX_GBI_SHARED=1.
f3dzexFast3DZEXExperimental. Used in Animal Crossing (Dōbutsu no Mori). Sets F3DZEX_GBI_2=1.
f3dzex is explicitly experimental. The Makefile prints a warning when it is selected: “Fast3DZEX is experimental. Try at your own risk.”
Choosing a non-default GRUCODE for a given VERSION disables COMPARE automatically, since the resulting ROM will not match the original SHA-1 hash.

COMPILER

COMPILER ?= ido
Selects the C compiler used to build the game code.
ValueCompilerEffect
idoSGI IRIS Development Option (IDO 5.3)Default. Required to produce a matching ROM. Uses -mips2.
gccGNU C Compiler (cross-compiled for MIPS)Forces NON_MATCHING=1, uses -mips3 and -O2.
When COMPILER=ido, the build can use either qemu-irix (USE_QEMU_IRIX=1) or a statically recompiled IDO binary (USE_QEMU_IRIX=0, the default). The MIPS cross-compiler prefix is detected automatically from whichever of mips-linux-gnu-, mips64-linux-gnu-, or mips64-elf- is found on PATH.

NON_MATCHING

NON_MATCHING ?= 0
Controls whether the build attempts to produce a byte-for-byte identical copy of the original ROM.
ValueBehaviour
0Matching build. Requires COMPILER=ido. Enables COMPARE=1 by default.
1Non-matching build. Enables AVOID_UB=1 and forces COMPARE=0. Automatically set when COMPILER=gcc or TARGET_N64=0.
When NON_MATCHING=1, the preprocessor defines NON_MATCHING=1 and AVOID_UB=1 are passed to the compiler.

AVOID_UB and the BAD_RETURN macro

When NON_MATCHING=1, the AVOID_UB=1 preprocessor define is enabled. This activates portable replacements for code that relies on undefined behaviour present in IDO’s code generation. The primary example is the BAD_RETURN macro used in certain functions where the original IDO compiler happened to produce correct output from technically undefined C. The BAD_RETURN macro is defined in the codebase to emit a return value in a way that avoids UB under GCC while still matching the IDO output when AVOID_UB is not set.

COMPARE

COMPARE ?= 1
When 1, the build system verifies the SHA-1 hash of the generated ROM against the known-good hash for the selected version after linking. A mismatch prints a warning but does not abort the build. COMPARE is automatically set to 0 when:
  • NON_MATCHING=1 is active
  • A non-default GRUCODE is selected for the current VERSION
  • TARGET_N64=0
To suppress the comparison message while still building a matching ROM, pass COMPARE=0 explicitly.

TARGET_N64

TARGET_N64 ?= 1
When 1 (the default), the build targets real N64 hardware. This enables -DTARGET_N64, -D_LANGUAGE_C, and -DTARGET_N64 in the compiler flags, and adds include/libc to the include path. Setting TARGET_N64=0 is the entry point for PC ports and other non-N64 targets. It automatically forces NON_MATCHING=1 and sets BORDER_HEIGHT to 0.

CROSS

The MIPS toolchain prefix is auto-detected in this order:
  1. mips-linux-gnu-
  2. mips64-linux-gnu-
  3. mips64-elf-
If none are found, the Makefile aborts with an error. You can override the prefix explicitly:
make CROSS=mips64-elf-

Summary table

VariableDefaultValid valuesDescription
VERSIONusjp us eu sh cnGame region to build
GRUCODEversion-dependentf3d_old f3dex f3dex2 f3d_new f3dzexRSP microcode
COMPILERidoido gccC compiler
NON_MATCHING00 1Allow non-matching output
COMPARE10 1Verify ROM SHA-1 after build
TARGET_N6410 1Build for N64 hardware
CROSSauto-detectedany MIPS toolchain prefixMIPS toolchain prefix
USE_QEMU_IRIX00 1Use qemu-irix for IDO compiler
VERBOSE00 1Print full build commands
COLOR10 1Colorize build output

Build docs developers (and LLMs) love