Self-hosted service
n64decomp/banjo-kazooie avatar
n64decomp/banjo-kazooie

banjo-kazooie is a Nintendo 64 decompilation judged by one number: how close the rebuild is to the original

A decompilation of Banjo Kazooie. (MIRROR of https://gitlab.com/banjo.decomp/banjo-kazooie)

658 stars62 forksCCC0-1.0

At a glance

What is it?
n64decomp/banjo-kazooie reconstructs the Banjo-Kazooie source in C so that the rebuilt ROM matches the original byte for byte, currently at 100.0000 percent. Getting there needs an IDO 5.3 static recompiler, a MIPS cross toolchain, four supported ROM versions and either a Linux checkout, a Docker image or a GitLab pipeline.
Who is it for?
Use this project if you want to study how a shipped Nintendo 64 game was written or want a byte exact rebuild of Banjo-Kazooie that you can diff against the original, and if you already have a legally obtained copy of the ROM to supply as the baserom. Do not expect a readable game codebase, since the goal is matching output rather than readable source, and do not expect it to build natively on Windows, which the Makefile refuses with a request to use WSL.
Can I use it commercially?
Yes. CC0-1.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 25 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The headline number is a match percentage, not a completion estimate

The title of the project is its goal: Banjo-Kazooie at 100.0000 percent. That figure is a matching score, which measures how much of the rebuilt ROM is identical to the original, and it is the only metric that counts in a decompilation.

The repository layout shows how that number is produced and kept honest. There is a progress/ directory with a progress_total.svg image for the badge, decompressed.us.v10.yaml and decompressed.pal.yaml files that describe the decompressed layout, and per-version symbol and address tables in symbol_addrs.us.v10.txt, manual_syms.us.v10.txt, level_symbols.us.v10.txt and rzip_dummy_addrs.us.v10.txt, with matching pal variants. There is also a diff/ directory and a first_diff.py script, which is how a mismatch gets localised when the build stops matching.

That machinery is the real content of the repository. The C source under src/ and the headers under include/ are the output of the work, but the tools that verify them are what let a project of this size stay at 100 percent.

For a reader, this is a documentation of method as much as of code. A decompilation that reaches a perfect match has demonstrated that the behaviour of the original binary is fully explained by the reconstructed source, which is the strongest possible statement that the reconstruction is faithful.

This repository is a mirror of the project hosted at gitlab.com/banjo.decomp/banjo-kazooie, and the GitLab side is the main one, as the build instructions below make clear.

A Linux build needs a package list, Rust, submodules and a Python venv

The local Linux path is documented for Ubuntu 18.04 or higher on x86_64, and the dependency step is a single block of commands.

sh
sudo apt-get update && sudo apt-get install -y $(cat packages.txt)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
git submodule update --init --recursive
python3 -m venv .venv
.venv/bin/python3 -m pip install -r requirements.txt

Three things in that list are worth understanding. The apt install reads its package list from packages.txt in the repository root, so the system dependencies are declared in the repository rather than in prose. Rust is installed through rustup, which is needed by the recompiler tooling. The submodule update is recursive, which matters because the tools/ directory contains the n64splat toolchain, and the Python virtual environment installs the analysis scripts.

Those Python requirements are a good map of what the verification pipeline needs:

code
-r tools/n64splat/requirements.txt
ansiwrap
anybadge
capstone
colorama
cxxfilt
pycparser
pylibyaml
pypng
python-Levenshtein
python-ranges
pyyaml
watchdog
rabbitizer
mapfile_parser
spimdisasm==1.35.0

capstone and rabbitizer are the disassembly and MIPS instruction decoding libraries, spimdisasm is pinned exactly at 1.35.0, cxxfilt demangles C++ symbol names, anybadge generates the progress badge, and watchdog watches for changed files so the build can react. The first line pulls in the requirements of the n64splat tool, which lives under tools/.

The one dependency with no version pin among the important ones is spimdisasm, which is pinned, and the rest are unpinned, so a fresh environment will pull current releases of the analysis libraries.

The baserom is the only binary input, and its checksum is published

A decompilation needs the original binary to compare against, and this project calls that file the baserom. Four regional versions are supported, and the README publishes the SHA1 of each:

sh
sha1sum baserom.us.v10.z64

The expected values are given for baserom.us.v10.z64, baserom.us.v11.z64, baserom.jp.z64 and baserom.pal.z64, and the instruction is that the output should match the checksum specified above. The file for US v1.0 goes into the project folder under the name baserom.us.v10.z64.

Publishing those checksums is the right engineering decision, because it lets a builder confirm in one command that the input is the expected image before spending time on a build that would fail on a byte difference. The build then compares the reconstructed ROM against that input, and any mismatch is reported down to the address.

The Makefile confirms which versions are wired in. VERSION defaults to us.v10, and each of us.v10, pal, us.v11 and jp sets an internal C_VERSION value of 0, 1, 2 or 3 respectively, which is how a single source tree produces different regional builds.

The region is chosen at build time:

sh
make VERSION=us.v11

The other consideration is that this is the one input you have to supply yourself, and that the original game is copyrighted. The decompiled code in this repository is released under CC0, and the game's own assets and music are not, so the useful and lawful framing for a reader is that this is a study of the game's implementation, with the original binary used locally as the comparison target.

One make target builds everything, and named module targets build parts

The build itself is short. To extract and build everything, the instruction is:

sh
make

To build a single module instead, you pass a module id:

sh
make <module_id>

The supported values are a list of the game's code modules: core1, core2, MM, TTC, CC, BGS, FP, lair, GV, CCW, RBB, MMM, SM, fight and cutscenes. Those names are the game's own internal abbreviations, which tells you something about the structure of the original source before you read a line of the reconstruction.

The split is not cosmetic. A decompilation this size is not built and debugged as one unit. Each module is compiled, compared against the corresponding region of the original ROM, and only when it matches does it count. A module that does not match fails, and the diff/ directory plus first_diff.py let you see exactly which address diverged.

Two Makefile settings are worth noticing. ANTI_TAMPER and ANTI_PIRACY both default to 1, so the built output includes the original's tamper and anti-piracy checks rather than stripping them. A decompilation that removed them would not match the original bytes, so the flags exist to keep the comparison honest; they are not a policy statement about the built artefact.

The Makefile also detects the host operating system and architecture, mapping Linux on ARM to linux-arm, Linux to linux, and Darwin to macos, and it refuses to build natively on Windows with an explicit error telling you to use WSL instead.

Docker is the path for macOS and for ARM machines

The documentation states that the instructions work on Ubuntu 18.04 or higher with Docker only on Linux and macOS, for both x86_64 and ARM.

If the published image is available you can pull it from GitLab, which requires being logged in to the registry:

sh
docker login registry.gitlab.com
docker pull registry.gitlab.com/banjo.decomp/banjo-kazooie:latest

Otherwise you build the image yourself from the Dockerfile in the repository root:

sh
docker build -t banjo-kazooie .

For ARM hardware, including Windows on ARM, Raspberry Pi and Apple Silicon, the documented variant pins the platform explicitly:

sh
docker build --platform linux/amd64 -t banjo-kazooie .

The container is run with the working directory mounted at /banjo, so the baserom you drop into the directory is visible to the build:

sh
docker run -it --rm -v $(pwd):/banjo banjo-kazooie 

with the same platform flag variant for ARM machines. To leave the container, you type exit.

The Dockerfile explains why the build environment is heavier than it looks. It starts from ubuntu:25.04, installs the same packages.txt driven dependency set, and then installs Rust and Cargo. The Rust install is patched on the way: the script replaces /proc/self/exe with /bin/sh, and the comment explains that this avoids issues inside Docker. The entrypoint is a shell rather than a fixed command, which is what lets you run make interactively inside the container.

The image is essentially a reproducible Linux build environment, which is the right tool when your own machine is a Mac or an ARM box that cannot run the MIPS toolchain natively.

CI runs against an encrypted baserom fetched at build time

The GitLab CI path exists because the baserom cannot be committed to a repository, and the solution is to encrypt it and host it somewhere the pipeline can fetch.

The encryption step is done with openssl, using AES-256-CBC with a salt:

sh
openssl enc -aes-256-cbc -salt -in baserom.us.v10.z64 -out baserom.us.v10.enc.z64

You upload that encrypted file to a server and get a direct download link. The documentation warns that sharing services like Google Drive, Dropbox or OneDrive might not work, since they require manual interaction to download a file, which is exactly what a CI job cannot do.

Three CI variables are then set per version in the GitLab project settings. BASEROM_<VER>_URL holds the direct download URL for the encrypted baserom, BASEROM_<VER>_KEY holds the AES key used to encrypt it, and BASEROM_<VER>_SHA1 holds the SHA1 checksum, which the documentation says to simply take from the published list.

The version placeholder takes one of four values: US10, US11, JP or PAL. Setting them per version is what lets one pipeline definition build every regional variant.

A final trigger is anticlimactic and effective: push a commit and a new pipeline appears under CI/CD, Pipelines. The README also notes that these instructions apply to the main repository, and that if you have a fork you need to follow the same steps, which tells you the CI configuration is not inherited by forks.

The toolchain reality: IDO 5.3 static recompilation and MIPS prefix hunting

Underneath the friendly instructions sits a Makefile that tells you what this kind of project really requires.

The recompiler configuration pins RECOMP_VERSION to v1.2 and builds the archive name from the detected platform, fetching ido-5.3-recomp-<os>.tar.gz from the decompals ido-static-recomp releases. The fetch happens automatically if the compiler binary is not already present, and it is cached under tools/ido-recomp/<detected_os>, with the compiler itself at tools/ido-recomp/<os>/cc.

That is the core of the technique. The original game was compiled with IRIX-era tools from Nintendo, and reproducing its exact output requires the same compiler. A modern GCC cannot produce matching code. The static recompiler rebuilds the original compiler from the code it generated, which is why a Rust tool is needed to do it and why the archive is platform specific.

The MIPS toolchain detection is the other half. The Makefile searches a list of candidate prefixes, including mips64-elf, mips-n64, mips64, mips-linux-gnu, mips64-linux-gnu, mips64-none-elf, mips and mips-suse-linux, and it fails the build with an error if none of them is found on the path. In practice you install one of those cross compilers yourself.

The repository is not archived and the last push was on 2026-09-28, with no GitHub releases because the real releases live on GitLab. The licence file covers the decompiled source under CC0, while the original game assets remain the property of their rights holders.

Editorial conclusion

Use this project if you want to study how a shipped Nintendo 64 game was written or want a byte exact rebuild of Banjo-Kazooie that you can diff against the original, and if you already have a legally obtained copy of the ROM to supply as the baserom. Do not expect a readable game codebase, since the goal is matching output rather than readable source, and do not expect it to build natively on Windows, which the Makefile refuses with a request to use WSL. Before starting, verify the SHA1 of your baserom against the four published checksums, confirm your MIPS cross compiler is one of the prefixes the Makefile searches for, and read the anti-tamper and anti-piracy flags before you ship anything you build.

Frequently asked questions

What is n64decomp/banjo-kazooie?

It is a decompilation of Banjo-Kazooie, a reconstruction of the original source in C that rebuilds to a ROM matching the original byte for byte, currently listed at 100.0000 percent. The repository is a mirror of the project hosted at gitlab.com/banjo.decomp/banjo-kazooie.

What do I need to build the Banjo-Kazooie decompilation?

On Ubuntu 18.04 or higher you install the packages listed in packages.txt, install Rust through rustup, update the git submodules recursively, create a Python virtual environment and install requirements.txt. You also need to supply the baserom yourself.

How do I verify my baserom file?

Run sha1sum baserom.us.v10.z64 and compare the output with the checksum published in the README. Checksums are given for the US v1.0, US v1.1, Japanese and PAL files.

Can I build on macOS or an ARM machine?

Yes, through Docker. Build the image with docker build -t banjo-kazooie ., or pull the published GitLab image, and on ARM hardware add --platform linux/amd64 to both the build and the run command.

How do I build a different regional version?

Name the baserom file for the version you want and pass VERSION to make, for example make VERSION=us.v11. The Makefile maps us.v10, pal, us.v11 and jp to internal C_VERSION values of 0, 1, 2 and 3.

Does the build work on Windows?

Not natively. The Makefile detects Windows_NT and stops with an error saying native Windows is currently unsupported and that WSL should be used instead.

Official sources

  1. Issues
  2. License: CC0-1.0
  3. n64decomp/banjo-kazooie on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/n64decomp-banjo-kazooie.svg)](https://hysenlabs.com/projects/n64decomp-banjo-kazooie)

Was this useful?