Turning N64 Binaries Inside Out: Static Recompilation to Portable C
If you've ever stared at a disassembled N64 ROM and wished you could just... run parts of it on your laptop, you've probably looked at emulators and wondered if there's a faster path. N64: Recompiled takes a different route entirely: instead of interpreting instructions or dynamically recompiling at runtime, it statically translates N64 binaries into C code that you can compile for any platform.
What It Does
N64: Recompiled is a tool that accepts an N64 binary along with a list of symbols and metadata, then splits that binary into functions and recompiles each one into a corresponding C function named according to the metadata you provide. The translation is deliberately literal—every MIPS instruction gets mapped to a C equivalent as it's processed, one by one. For example, the instruction addiu $r4, $r4, 0x20 becomes ctx->r4 = ADD32(ctx->r4, 0X20); in the output. Jump-and-link instructions become direct function calls, and branches that look like tail-call optimizations get the same treatment. Branch delay slots are handled by duplicating instructions where necessary.
The output is plain C that compiles with msvc, gcc, or clang. It's designed to work alongside a runtime that provides the macros and functionality the recompiled code expects—the project points to N64ModernRuntime for that, which you can see in action in the Zelda 64: Recompiled project. The recompiler also handles overlays, both statically linked and relocatable, by emitting function lookups for jump-and-link-register instructions that the runtime can resolve through a lookup table.
Why It's Cool
-
Static recompilation means no interpreter overhead. The README notes this approach can simulate behaviors significantly faster than interpreters or dynamic recompilation. You're not paying the cost of decoding instructions at runtime—that work happens once, ahead of time, and the result is just C code.
-
It's not the first, but it's building on solid ground. The README is upfront about its lineage: jamulator did this for NES, and the IDO static recompilation project recompiled the SGI IRIX IDO compiler for matching decompilation work. That IDO project was the main inspiration here. Knowing this isn't a wild experiment but a continuation of proven techniques is reassuring.
-
The literal translation keeps complexity low. Rather than trying to be clever about optimization or pattern matching, the recompiler processes instructions one at a time and emits corresponding C. That simplicity makes the tool more predictable and easier to debug. There are exceptions for specific cases—like turning
jrinstructions into switch-case statements when a jump table is detected—but the philosophy is clearly "do the straightforward thing first." -
Flexibility in how you use the output. You can use this for full ports, for tools, or for any context where you want to run some part of an N64 binary in a standalone environment. That's a wide range of use cases, and the fact that the output is portable C means you're not locked into any particular platform.
-
Tested across multiple compilers. The recompiler has mostly been tested on binaries built with old MIPS compilers like mips gcc 2.7.2 and IDO, as well as modern clang targeting mips. The README notes that modern mips gcc may cause issues due to certain optimizations, but those can probably be avoided with specific compilation flags—an honest caveat that tells you where the rough edges are.
How to Try It
The README doesn't include a quick-start command block, but the general flow is: you'll need an N64 binary, a list of symbols and metadata, and a C compiler for the output. The project is hosted at github.com/n64recomp/n64recomp, and you'll want to check the repository for build instructions (the README has a Building section).
To actually run the recompiled output, you'll need a runtime. The project points to N64ModernRuntime as the provided runtime, and Zelda 64: Recompiled as a real-world example of it in action.
A few things to keep in mind from the README:
- Each output function currently gets its own file. The README mentions an option may be added in the future to group functions together to improve build times by reducing file I/O.
- The recompiler handles overlays and emits function lookups for indirect calls that the runtime resolves.
- RSP microcode support is mentioned in the table of contents, so there's more to explore in the full README.
Final Thoughts
This is a tool for people who already know their way around N64 binaries and aren't afraid of a build pipeline that involves metadata, symbol lists, and a separate runtime. It's not a one-click emulator replacement—it's infrastructure for porting and analysis. The honest caveats about compiler compatibility and the current one-function-per-file output tell you this is a project still being refined, but the foundation is solid and the approach is proven. If you're working on N64 ports or tools that need to run binary code outside an emulator, this is worth a serious look.
Follow @githubprojects for more developer tools and open source projects.