Decompiling a Nintendo 64 game in 84 days

Decompiling a Nintendo 64 game in 84 days

在 84 天内反编译一款任天堂 64 游戏

26 Aug, 2026 2026 年 8 月 26 日

I’m very pleased to announce that the original Snowboard Kids is now 100% decompiled! This means that all functions have matching C implementations that, when compiled, produce identical machine code to the original game. 我非常高兴地宣布,初代《滑雪小子》(Snowboard Kids)现已实现 100% 反编译!这意味着所有的函数都有对应的 C 语言实现,编译后能产生与原版游戏完全一致的机器码。

This was obviously not a one-person effort. I am particularly grateful to inspectredc, Bl00D4NGEL, and queueRAM for their significant contributions to the project. No amount of AI would have been able to replace them. I would also like to thank iFuzzle, JamesBLewis, and douglasjv for lending their tokens to the cause. 这显然不是一个人的功劳。我特别感谢 inspectredc、Bl00D4NGEL 和 queueRAM 对该项目做出的重大贡献。再多的 AI 也无法取代他们。我也要感谢 iFuzzle、JamesBLewis 和 douglasjv 为此项目贡献了他们的 Token(算力资源)。

My hope is that a full decompilation will prove useful to the Snowboard Kids community. Speedrunners in particular have long focused on the first game. Working source code can help shed light on externally observed phenomena such as CPU pathing and the exact factors contributing to player speed. A full understanding of the source code will also be useful for static recompilation and more ambitious modding efforts in the future. 我希望这次完整的反编译能对《滑雪小子》社区有所帮助。速通玩家长期以来一直关注着这款初代游戏。可运行的源代码有助于揭示一些外部观察到的现象,例如 CPU 的寻路逻辑以及影响玩家速度的具体因素。对源代码的全面理解,也将有助于未来的静态重编译和更具野心的模组(Mod)开发工作。

The speed at which the project was finished is also noteworthy. Snowboard Kids took only 84 days to decompile compared with 596 days for Snowboard Kids 2, roughly one-seventh of the elapsed time. 该项目完成的速度也值得注意。《滑雪小子》仅用了 84 天就完成了反编译,而《滑雪小子 2》则用了 596 天,耗时大约只有后者的七分之一。

What explains this difference? Well, it’s 2026, so the answer is at least partially AI. But it would be a gross oversimplification to attribute the difference entirely to LLMs. 是什么导致了这种差异?好吧,现在是 2026 年,答案至少部分归功于 AI。但如果将这种差异完全归因于大语言模型(LLM),那就太简单化了。

What Was Different

有何不同

To state the obvious, I was not starting from scratch. By this point I had already spent nearly two years on a similar project and was vastly faster than when I began. This advantage is difficult to quantify and was somewhat offset by new challenges such as working with a different compiler. 显而易见,我并非从零开始。到目前为止,我已经在一个类似的项目上花费了近两年时间,速度比刚开始时快得多。这种优势很难量化,而且在一定程度上被使用不同编译器所带来的新挑战所抵消。

Overall, roughly 4.8% of matching commits involved expert intervention. I have already credited these amazing people once, but it’s worth reiterating. This project would not have been possible without significant help from the decompilation community, particularly inspectredc, queueRAM, and Bl00D4NGEL <3. 总的来说,大约 4.8% 的匹配提交涉及专家的干预。我已经感谢过这些了不起的人,但值得再次重申:如果没有反编译社区的大力帮助,特别是 inspectredc、queueRAM 和 Bl00D4NGEL 的帮助,这个项目是不可能完成的 <3。

The difficulty generally didn’t come from trying to understand what a function did but rather how that logic was expressed in C and how the resulting code was compiled. Snowboard Kids was compiled with IDO 5.3 rather than the GCC 2.7.2 compiler used by Snowboard Kids 2. 困难通常不在于理解函数的功能,而在于理解该逻辑是如何用 C 语言表达的,以及生成的代码是如何编译的。《滑雪小子》使用的是 IDO 5.3 编译器,而不是《滑雪小子 2》所使用的 GCC 2.7.2。

Most programmers will be familiar with GCC. It is a widely used open-source compiler still in active development today. IDO, on the other hand, was a proprietary compiler developed by SGI, whose own story is closely entwined with that of the Nintendo 64. Its source was not available, and its original development environment was tied to obsolete SGI hardware and software. To use and properly understand it today, the decompilation community has had to reverse-engineer and decompile parts of the compiler toolchain as well as statically recompile the IDO 5.3 and 7.1 suites to run on modern hardware. That closed history makes IDO harder to reason about than an open compiler such as GCC. 大多数程序员对 GCC 都很熟悉。它是一个广泛使用的开源编译器,至今仍在积极开发中。而 IDO 则是由 SGI 开发的专有编译器,SGI 的历史与任天堂 64 紧密相连。IDO 的源代码并不公开,其原始开发环境也绑定在已淘汰的 SGI 硬件和软件上。为了在今天使用并正确理解它,反编译社区不得不对编译器工具链的部分内容进行逆向工程和反编译,并对 IDO 5.3 和 7.1 套件进行静态重编译,使其能在现代硬件上运行。这种封闭的历史使得 IDO 比 GCC 等开源编译器更难推断。

IDO splits optimisation and code generation across several different passes, transforming code quite aggressively along the way. Tiny changes to the C can then ripple through those passes and produce a completely different register allocation. IDO 将优化和代码生成拆分为几个不同的阶段(Pass),并在过程中对代码进行非常激进的转换。C 代码中的微小改动可能会在这些阶段中产生连锁反应,从而导致完全不同的寄存器分配结果。

The community has made great strides in understanding IDO and its quirks, but this remains more of an art than a science. LLMs and I are not particularly good at reproducing its output. The usual workflow, for both me and the agents, was to figure out what a function did and then write C that approximated that purpose. From there, small tweaks assisted by the permuter could catch any remaining differences. But you can’t permute yourself into a match in all cases, particularly when the underlying structure is wrong. IDO’s behaviour made this workflow far less predictable. 社区在理解 IDO 及其特性方面取得了巨大进步,但这仍然更像是一门艺术而非科学。我和 LLM 在复现其输出方面并不特别擅长。我和 AI 代理通常的工作流程是:先弄清楚函数的功能,然后编写近似的 C 代码。在此基础上,通过 permuter(置换工具)进行微调,以消除剩余的差异。但你不能在所有情况下都通过置换来达成匹配,尤其是当底层结构错误时。IDO 的行为使得这种工作流程的可预测性大大降低。

A motivated human team with the right expertise and intuition can match or even exceed the pace of the Snowboard Kids decompilation. The Pilotwings 64 decompilation was completed in only 74 days. Pilotwings 64 had 16% fewer functions than Snowboard Kids, but more compiled code overall, so this is not a clean comparison either. 一个有动力且具备专业知识和直觉的人类团队,可以达到甚至超过《滑雪小子》的反编译速度。《飞行俱乐部 64》(Pilotwings 64)的反编译仅用了 74 天就完成了。《飞行俱乐部 64》的函数数量比《滑雪小子》少 16%,但编译后的代码总量更多,所以这并不是一个完全对等的比较。

Snowboard Kids was also smaller than its sequel, containing 2,145 functions compared with 2,995 in Snowboard Kids 2. Function count is a crude measure of difficulty, but there were simply fewer functions to decompile. 《滑雪小子》也比其续作规模更小,包含 2,145 个函数,而《滑雪小子 2》则有 2,995 个。函数数量是衡量难度的一种粗略指标,但简单来说,确实有更少的函数需要反编译。

Where Agents Did Help

AI 代理在哪些方面提供了帮助

I’ve already written elsewhere about using agents to decompile functions. The same basic process was used here, so I’ll focus on what changed. Unlike the previous project, this one began with access to frontier models and a capable agent harness. 我已经在其他地方写过关于使用 AI 代理进行函数反编译的内容。这里使用了相同的基本流程,所以我将重点介绍有哪些变化。与之前的项目不同,本项目从一开始就能够使用前沿模型和功能强大的代理框架。

Library Code and Other Low-Hanging Fruit

库代码及其他“低垂的果实”

I was interested to see how agents would fare during the early stages of a project. One area where they thrived was matching standard-library code. In theory, this is the most obvious chunk of almost any Nintendo 64 decompilation. The code is not unique to the game, and versions of it are available online. Snowboard Kids contains more than a hundred source segments from Nintendo’s libultra, alongside functions from the libmus audio library. Tools such as N64Sym can identify probable library functions in the ROM. 我很好奇 AI 代理在项目初期表现如何。它们表现出色的一个领域是匹配标准库代码。理论上,这是几乎所有任天堂 64 反编译中最显眼的部分。这些代码并非游戏独有,网上可以找到它们的版本。《滑雪小子》包含了一百多个来自任天堂 libultra 的源代码片段,以及来自 libmus 音频库的函数。像 N64Sym 这样的工具可以识别 ROM 中可能的库函数。

This pass was fairly successful. The main stumbling block was convincing agents to rely on the existing library source rather than decompile the same functions again from scratch. This required stronger prompting. Once a likely library function was identified, agents were instructed to treat the corresponding source as their starting point and exhaust plausible SDK versions, compiler options, and conditional compilation paths before attempting their own implementation. 这一阶段相当成功。主要的障碍在于如何说服 AI 代理依赖现有的库源代码,而不是从零开始重新反编译这些函数。这需要更强的提示词(Prompting)。一旦确定了可能的库函数,就会指示代理将相应的源代码作为起点,并在尝试自行实现之前,穷尽所有可能的 SDK 版本、编译器选项和条件编译路径。

Another optimisation was to have an agent write a script that ran m2c against every unmatched function and automatically integrated any exact matches, rather than relying on agents to attempt it. 另一个优化是让 AI 代理编写一个脚本,对每个未匹配的函数运行 m2c,并自动集成任何完全匹配的结果,而不是依赖代理去手动尝试。