The Melee decompilation, and what a matching build does and does not settle
A decompilation of Super Smash Bros Melee brought to you by a bunch of clever folks.
At a glance
- What is it?
- This repository rebuilds Super Smash Bros Melee from C source into a main.dol that matches the original byte for byte, and it verifies that claim with a graphical diff against the compiled data from your own disc. It is one of the most complete reverse engineering efforts ever attempted, it has no licence file at all, and the artefact it produces can be modified, which in a tournament game is a fact every reader needs stated plainly.
- Who is it for?
- Adopt this project if you are working on decompilation, on tooling for verified binary reconstruction, or on a GameCube or Wii game you want to study at source level, and treat the objdiff workflow as the part worth stealing for your own reverse engineering work. Do not build a modified version for competitive play, because Melee is a tournament game and any code change makes a build ineligible regardless of how small it is.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 3 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 September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What a matching decompilation is, and why it needs your own disc
A matching decompilation is a specific technical achievement with a specific definition. The README states that the repository contains a matching decompilation of Super Smash Bros Melee for the US release, and that it builds `main.dol`. A matching build means the compiled output is byte-for-byte identical to what Nintendo shipped, which is a far stronger claim than source that behaves the same way.
That claim requires a reference, and this is where most people find the project surprising. The build cannot be verified against anything in the repository, because the repository does not contain the original game. Instead you supply it. The README's instruction is to use Dolphin Emulator, find your own ISO, open its Properties, go to the Filesystem tab, right-click the disc and select Extract System Data, choosing the `orig/GALE01` directory of the repository as the destination. It also notes that to save space only `main.dol` and a placeholder file are necessary, and everything else in the extracted set can be deleted.
So the verification model is a comparison, and the comparison happens locally on your machine. The extracted system data is the original compiled object code. Your build produces object code from C. A diff between the two is the proof, and the tool that performs it is described later in the README.
The build sequence itself is three commands, and the first uses a shallow clone because the history is large and a full clone buys nothing for someone who wants to build rather than study:
git clone https://github.com/doldecomp/melee.git --depth=1
python configure.py
ninjaThe build system is Ninja, driven by a Python configuration script, and both are described in the README's own tooling section rather than by a build system of its own. There is no makefile in the conventional sense and no package to install before the first build.
The target is specific and pinned in a table at the top of the README: game ID `GALE01`, version 1.02, with a SHA-1 of `08e0bf20134dfcb260699671004527b2d6bb1a45`. Pinning the exact revision is what makes the goal well defined. A matching decompilation of an unspecified version of a game is not a target, it is an aspiration.
GALE01, the toolchain, and a 32-bit Windows binary wrapper on Linux
The dependency list is where this project becomes unusual, because building GameCube and Wii code requires tools that did not exist for the platforms people now build on.
The original console compilers are Windows host binaries for PowerPC targets, and running them on Linux or macOS means Wine. The README's per-platform instructions reflect that and the different ways people end up with a working Wine.
On Linux, Wine is installed from the package manager, but only for non-x86 platforms. On x86 and x86_64 something else happens: a project called WiBo, described as a minimal 32-bit Windows binary wrapper, is downloaded automatically and used instead. The reason is practical rather than ideological. The console build tools are 32-bit, and a 32-bit Windows binary on a 64-bit Linux system needs a compatibility layer that a general-purpose Wine install is not always the right tool for. Building a small purpose-made wrapper for exactly that case is the kind of decision a decompilation project makes after months of friction and then documents in one line.
On macOS the route is a third-party Wine build installed from a custom Homebrew tap, with a cask and the quarantine flag disabled. The README also documents the specific post-upgrade problem that follows, where macOS complains that the application is unverified, and gives the `xattr` command that clears the quarantine attribute. That is the kind of note that only exists because someone hit it twice.
On Windows the advice is to use native tooling and that WSL or msys2 are not required, with a specific reason given: under WSL, the diffing tool is unable to get filesystem notifications for automatic rebuilds. That is worth noticing as a design constraint. The development loop depends on a tool noticing that a file changed, and a cross-boundary filesystem does not deliver those notifications reliably. Rather than work around it, the project tells Windows developers not to use WSL.
The common requirements are Python and Ninja on the path, with Ninja installable through pip. Continuous integration is different again: most of it runs under Nix, containerisable through the Nix Docker image or a tool called nix-toolbox, and the README says the intent is to migrate the whole pipeline to Nix, with a tracking issue for it.
So the toolchain is Python for configuration and tooling, Ninja for the build, Wine or a purpose-built wrapper for the original compilers, and Nix for reproducibility. That is a lot of moving parts, and each one is there for a reason that the README states.
configure.py, --non-matching, and the shiftable DOL
The most consequential thing in this README is a tip box near the top, and its consequences run through the whole project.
It says the DOL the repository builds can be shifted, meaning you are able to add and remove code as you see fit, for modding or research purposes. Everything else the project does follows from that being true, so it is worth being precise about what a DOL is in this context and why it can be changed.
A DOL is the executable format the GameCube and Wii load. Unlike a statically linked binary on a desktop system, it is loaded at a fixed base address determined by the game format rather than chosen at link time, and code compiled expecting a particular layout can be shifted within the file without breaking it. That is the technical reason the artefact is editable, and it is why a decompilation that matches the original byte for byte is also a modding platform.
The build system makes the distinction explicit rather than leaving it implicit. The default configuration produces a build that must match. Modding requires an explicit opt-in:
python configure.py --non-matchingThe README's modding section then describes the process. Dump the full game disc, not just the system files, to a folder. Add new source files or folders under `src`. Enable the non-matching build. Add each new file to `configure.py`, where the order determines when the files are linked, though in most cases it does not matter, and new files must be marked `Equivalent`:
MeleeLib(
"My Custom Library",
[
Object(Equivalent, "my-cool-mod/helloworld.c"),
],
),The `Equivalent` marker is a claim about the code rather than a flag, and it deserves attention. It says the file is equivalent to the original rather than a replacement for it, which is a distinction that matters for a project whose entire claim is fidelity. A file marked `Equivalent` is expected to compile to the same bytes as what it replaced; a file that changes behaviour is something else, and the build system has a way to express the difference.
After building, the resulting DOL goes from `build/GALE01/main.dol` into the `sys` folder of the game directory you created, and Dolphin is configured to look there so the modified file can be launched from the Games list.
Here is the point that has to be said directly, because the README does not put it this way. Super Smash Bros Melee is a competitive tournament game with rules about what hardware and software are permitted in tournament play. A build produced with `--non-matching` has modified code in it, and modified code in a game where a single frame of difference decides a match is not a build anyone should bring to a bracket. The README frames the capability as being for modding or research, and both are legitimate. What the capability is not is a way to gain an edge over people who are playing the game as it shipped, and the fact that a change can be as small as one instruction is exactly why the distinction has to be made rather than assumed.
The default matters here. A contributor who runs the documented build gets a matching build, and the route to a modified one requires typing a flag. A project that made modification the default would be a different project, and this one is not that.
objdiff, and the two files that define where functions begin and end
Verification has its own tool and its own section in the README, and it is the part of this project most worth borrowing.
The README says that once the initial build succeeds, an `objdiff.json` configuration file should exist in the project root. You download the latest release of a tool called objdiff, and under project settings you set the project directory; the configuration loads automatically, which means the build system has already written everything objdiff needs. You then select an object from the left sidebar to begin diffing.
That is the whole workflow, and it is the workflow that makes the matching claim checkable rather than asserted. You are not comparing two builds. You are comparing your compiled object against the original compiled object, function by function, and the original object is the data you extracted from your own disc in the previous step.
The README also describes what triggers a rebuild in the diffing tool: changes to source files, headers, `configure.py`, `splits.txt` or `symbols.txt`. Those last two are the decompilation's data model and they are worth a paragraph each.
`splits.txt` records where each function begins and ends in the original binary. Before any decompilation can begin, somebody has to work out the boundaries of every function in a retail GameCube executable, and that work is not automated, it is painstaking, and it is the reason decompilation of a project this size takes years rather than weekends. A wrong boundary produces a function that will never match, and the failure is in the data rather than the code.
`symbols.txt` records the names. And this repository has a specific contribution history here, because the README says most of the project's current efforts are directed to naming and cleanup, with a published to-do list and a cleanup index. The original binary has function names in its debug strings, assert messages and game data, and the game code is organised into two-letter folders that the README says were left behind by HAL in assert messages and game data on the original disc. So even the folder names are evidence recovered from the retail game rather than a choice made by the decompilers.
The practical consequence is that contributing to this project is not only about writing C. If the current focus is naming and cleanup, then the highest-value contributions are identifying a function's real name, and matching a function that already compiles but under a placeholder name. That is a different contribution model from most open source projects, and it is described explicitly rather than left for a newcomer to infer.
The diffing tool is a separate project, and it is not Melee-specific. Anything that rebuilds a retail binary from source faces the same verification problem, and the pattern here, extract the original, build, diff per object, is the general solution.
m2c, decomp.py, a virtual environment, and decomp.me
The tooling section describes how the decompiled source is produced, and it is a workflow rather than a single tool.
The project uses Python for its command line tooling and recommends a virtual environment. The setup is four commands:
python -m venv --upgrade-deps '.venv'
. .venv/bin/activate
pip install -r reqs/decomp.txt
python tools/decomp.py my_function_nameThe activation command differs by platform, with a `Scripts` path on Windows and a `bin` path elsewhere, and the README notes you need to activate it whenever you open a new shell. The requirements file is the whole dependency set, which is the right shape for a tool that people install in a hurry.
The last command is the one that matters. `decomp.py` decompiles a named function, and the README says it uses m2c, with a `-h` flag for the options. m2c is a decompiler that takes machine code and produces C, and the reason a project like this builds its own workflow around it rather than running a general decompiler over the whole binary is granularity. You decompile one function, you read the output, you rewrite it into something that compiles to the same bytes, and you verify with objdiff. A general decompiler producing a million lines of plausible C is not a decompilation; it is a starting point for one.
The project name appears in the tooling as `decomp.py`, and the tool it wraps is named in the README as m2c with a link to its own repository. That separation is deliberate and it is how this kind of work gets organised: the decompiler is general, the function-level workflow is project-specific, and the verification is a third thing again.
The third route is the most interesting, because it involves no local tooling at all. The contributing section says that if you are new to Git and do not know how to create a pull request, the project encourages you to create an issue with your decomp.me link, and a maintainer will add your code to the repository. decomp.me is a web platform for collaborative decompilation, where a contributor works on a function in the browser, using the tooling in a hosted environment, and submits the result.
That is a genuinely clever solution to the real bottleneck in decompilation projects, which is not the reverse engineering but the contributor pipeline. Most people who could decompile a function cannot operate Git comfortably, and a project that insists on the Git route loses them. Routing them through an issue and a maintainer keeps the work and lowers the barrier, at the cost of the maintainer doing the integration.
Taken together, the tooling story is: a hosted path for people who cannot use Git, a local path with a virtual environment for people who can, and a diffing tool for everyone to prove the result.
The linting and build tooling behind a C project, and a Rust workspace doing the heavy lifting
The top-level entries show a project with more tooling discipline than most projects of a hundred times its contributor count.
For a C codebase there is `.clang-format` and `.clang-tidy` for formatting and static analysis, `.editorconfig` and `.gitattributes` for whitespace and line endings, and `.clangd` which configures the clangd language server that an editor uses for completion and inline diagnostics. The presence of `.clangd` specifically is a sign the project expects people to work in an editor with the compiler's own understanding loaded, rather than in a bare setup.
For Python there is `.flake8` and a `.pre-commit-config.yaml`, so style and basic errors are caught before a commit rather than in review. For Rust there is `.rustfmt.toml`, and for containers `.dockerignore`.
And there is a Rust workspace, declared in a `Cargo.toml` whose members are three tools under a `tools` directory, with a lock file checked in. The project is primarily C, with Python for configuration and tooling, and a Rust workspace for three specific purposes, which is worth pausing on. In a decompilation project, the tools that matter most are the ones that manipulate binary formats and symbol tables, and those are exactly the kind of program where Rust is a good fit. A formatter that rewrites a `splits.txt` with a hundred thousand entries, or a symbol replacement pass, has to be fast, correct and run over the whole file set on every invocation.
The Nix support is at the same level of seriousness, with a `flake.nix`, a lock file, a `default.nix` and a `.nix` directory, given that most of the continuous integration already runs under Nix and the stated plan is to move all of it.
There is a `Doxyfile` as well, so the source is set up to generate documentation, and separate `docs/` and `config/` directories alongside `libs/`, `orig/`, `reqs/`, `src/` and `tools/`.
The `orig/` directory deserves one more note, because its role is the verification reference. It is where the extracted system data goes, and the README's instruction that only `main.dol` and a placeholder file are needed means the reference itself is one binary. Everything else in the project, the hundred thousand lines of C, the Python, the Rust, the Nix, exists to produce something that equals that one file.
Editor configuration is committed too, with both `.idea/` and `.vscode/` directories present, which for a project with a large contributor base is a deliberate choice to support two editor families rather than impose one.
No licence file, and what that means for the people doing the work
The licence situation is the most significant gap in this project, and it needs stating without hedging.
The repository's licence field is recorded as unknown, and there is no licence file among the top-level entries. The listing contains the expected set of tooling and source directories and no licence document of any kind. For a project that has absorbed an enormous amount of volunteer reverse engineering work, that is a significant omission, and it is one that exists for an understandable reason rather than by accident.
The reason is that the output is a byte-for-byte reproduction of a commercial game. Whatever the position on fair use or on the legality of reverse engineering for interoperability and preservation, the project cannot grant rights in a compilation that is identical to Nintendo's copyrighted binaries, and a permissive licence claiming otherwise would be false. So the absence is defensible as a position. What is not defensible is leaving it implicit for the people doing the work, because a contributor who writes a decompiled function for this repository has no granted rights and no stated terms, and that is a question they cannot answer for themselves.
The practical guidance follows from that. If you want to contribute, the licence question is one to raise with the maintainers before you write code, not after. If you want to use the tooling, the tooling is separable from the game content and the questions are different. And if you are considering this as a model for your own work, the tooling story, the diff-driven verification, the data files, the hosted contribution path and the exhaustive linting, is all reusable in a project where the licence situation is not ambiguous.
The second boundary is the one discussed earlier and it is not a licensing question. This is a tournament game, the project supports building a modified artefact, and modified code in a competitive title is not a legitimate competitive build. The default configuration produces a matching build and modification requires an explicit flag, which is the right design, and the README's framing of the capability as being for modding and research is accurate. A reader should still come away understanding that the two uses are not comparable.
What this project is, in the end, is a decade-scale reverse engineering effort with a verification system rigorous enough to prove its own claim, a contribution pipeline designed around the people who want to help rather than the tools they already know, and an unresolved question about who owns the result. That is an honest description of an unusual and impressive piece of work.
Editorial conclusion
Adopt this project if you are working on decompilation, on tooling for verified binary reconstruction, or on a GameCube or Wii game you want to study at source level, and treat the objdiff workflow as the part worth stealing for your own reverse engineering work. Do not build a modified version for competitive play, because Melee is a tournament game and any code change makes a build ineligible regardless of how small it is. Verify first by running a default configure and build to confirm the match against the extracted system data, and settle the licensing question with the maintainers before you contribute code, since the repository declares no licence and no licence file appears in its top level.
Frequently asked questions
What is the doldecomp/melee repository?
It contains a matching decompilation of Super Smash Bros Melee for the US release, which builds main.dol. The target is pinned in the README as game ID GALE01, version 1.02, with a specific SHA-1, and the project verifies the build by diffing it against the original compiled data.
Why do I need my own copy of the game to build the Melee decompilation?
Because the build is verified against the original. The README instructs you to use Dolphin Emulator, open the Properties of your own ISO, go to the Filesystem tab, right-click the disc and select Extract System Data, choosing the orig/GALE01 directory of the repository. Only main.dol and a placeholder file are needed from that extraction.
How do I verify that my Melee build matches the original?
After a successful build an objdiff.json file appears in the project root. Download the latest objdiff release, set Project directory under its project settings so the configuration loads automatically, and select an object from the left sidebar. Changes to source files, headers, configure.py, splits.txt or symbols.txt trigger rebuilds automatically.
What does python configure.py --non-matching do?
It relaxes the requirement that the build match the original byte for byte, which is what you need to add or remove code. The README notes the resulting DOL can then be shifted for modding or research, and that new source files must be added to configure.py and marked Equivalent, as in the MeleeLib and Object(Equivalent, ...) example.
What tools does building the Melee decompilation require?
Python and Ninja on the path, plus Wine to run the original console build tools. On x86 and x86_64 Linux a minimal 32-bit Windows binary wrapper called WiBo is downloaded and used automatically, other architectures need wine from the package manager, macOS uses a third-party Wine cask, and Windows developers are advised to use native tooling because WSL breaks the diffing tool's filesystem notifications. Most continuous integration runs under Nix.
How is decompilation work actually contributed to the Melee project?
Locally, with a Python virtual environment, pip install -r reqs/decomp.txt and python tools/decomp.py on a named function, which uses m2c. The README also says that if you are new to Git you can create an issue with a decomp.me link and a maintainer will add your code, and that current efforts are directed to naming and cleanup.
Official sources
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.
[](https://hysenlabs.com/projects/doldecomp-melee)