tangosdev/sm64ds-decomp
GitHub: tangosdev/sm64ds-decomp
将《超级马里奥 64 DS》逐字节精确反编译为可编译复现原始 ROM 的 C 代码的逆向工程项目。
Stars: 84 | Forks: 12
# 超级马里奥 64 DS 反编译 (sm64ds-decomp)
[][discord]
将**超级马里奥 64 DS**从零开始反编译为匹配的 C 代码。
刚来这里?请从**[CONTRIBUTING.md](CONTRIBUTING.md)**开始,在
**[CLAIMS.md](CLAIMS.md)**中协调工作,如果你审查或合并 PR,请阅读**[MERGE.md](MERGE.md)**。
## 进度
```
Functions ███████████████████████████░░░ 90.6% 10,282 / 11,349
Code size ██████████████████████░░░░░░░░ 72.3% 1,597,736 / 2,211,124 bytes
```
游戏中的每一个 arm 模式函数,被绘制成矩形树状图。每个
矩形代表一个函数,大小由其字节数决定,绿色表示已匹配,灰色表示未匹配,
按模块分组。

如果你想查看交互式版本,将鼠标悬停在任何函数上即可看到其名称、地址、
大小和状态,请访问 [GitHub Pages 上的进度矩形树状图](https://tangosdev.github.io/sm64ds-decomp/)。
## “匹配”是什么意思
我们的目标是生成源代码,当使用原始工具链编译时,能够生成
与零售版 ROM 逐字节完全相同的二进制文件。这与 N64 的
`sm64` 项目所遵循的标准相同。每个匹配的函数都会与 ROM 进行核对,因此
可以确认源代码是正确的。
## 法律与范围
此仓库仅包含原创作品:工具、手写的 C 代码和笔记。
它不包含 ROM,也不包含提取的 Nintendo 资产。这些都是在你本地从
你自己拥有的卡带转储文件中读取的,并且被 git 忽略。不要提交任何从 ROM 的
数据或资产派生的内容,但有一个刻意且已记录的例外:`chaos-data` 分支上的
协调数据包含了仍未匹配函数的带注释反汇编文本,以便贡献者
无需完整的本地环境即可接手工作。这与反编译项目为未匹配代码
提交 `.s` 文件的做法相同。它是文本,
不是字节或资产,并且每个函数的反汇编文本一旦匹配,就会立即从已发布的数据中移除。
## 关于数字的说明
函数数量的增长速度快于代码大小的增长,因为那些小而规则的函数会
最先被匹配,而大多数剩余的字节都存在于大型的、调用频繁的
函数中。原始编译器已固定为 **mwccarm 1.2/sp2p3**,并使用以下
标志:
```
-O4,p -enum int -lang c99 -char signed -interworking -proc arm946e -gccext,on -msgstyle gcc
```
## 匹配的工作原理
每个候选者都以相同的方式进行验证:使用 mwccarm 编译它,然后
将结果与 ROM 逐字节进行比较,并具有重定位感知能力(调用和数据引用是
链接器填充的插槽,因此对它们进行结构上的比较)。在
该检查通过之前,没有任何内容会被视为匹配。工作被划分为不同的层级,以便自动方法能在任何手动工作之前清理尽可能多的内容:
1. **自动模板。** 一组规则识别常见的函数形态(常量
返回值、字段 getter 和 setter、位域读取、结构体拷贝、简单的包装器、
构造函数和析构函数),生成 C 代码,并与 ROM 进行确认。
这无需人工即可清除大部分小而规则的函数。
2. **手写。** 对于具有实际逻辑的函数,你需要自己编写 C 代码并验证
每次尝试,直到它逐字节相同。像 Ghidra 这样的反编译器
对于阅读函数很有用,尽管它的输出本身永远不会匹配。
对于已经分组的匹配,`tools/linkcheck.py` 会执行更强的重定位
目标检查:它重建每个函数的链接字节并将它们与
ROM 进行比较,从而捕获错误的被调用者或全局变量,而正常的未链接字节差异
会将这些视为通配符。请参阅 [notes/link-verification.md](notes/link-verification.md)。
## 环境设置
你需要提供自己的卡带转储文件。完整的设置(Python 依赖项、来自 DS-decomp Discord 的
专有 mwccarm 编译器、dsd 工具包以及解包你的 ROM)
在 [CONTRIBUTING.md](CONTRIBUTING.md) 和
[notes/setup-mwccarm.md](notes/setup-mwccarm.md) 中。
简短版本:
```
pip install ndspy capstone pyelftools
# 根据 notes/setup-mwccarm.md 获取 mwccarm,然后:
python tools/unpack.py "path/to/your-own-sm64ds.nds"
```
## 你能帮上什么忙
每一个匹配的函数都能推动项目的进展,而自动化层级意味着即使是
投入少量的时间也能大有裨益。请参阅 [CONTRIBUTING.md](CONTRIBUTING.md) 了解
完整的工作流程。
**贡献代码。** 挑选一个函数,为其编写 C 代码,验证它编译后是否生成与
ROM 相同的字节,然后发起 pull request。每个 PR 包含一个函数或一个
相关的小组最为理想。仅使用你自己在合法情况下转储的 ROM,切勿将其提交。
**协调工作。** 如果有疑问或想要认领工作,请在 Discord 上联系 `beansntoast`,或者开启一个 GitHub
issue,以免两个人在同一个函数上死磕。
**使用 AI 助手的最快入门方式。** 将此内容粘贴到 Claude Code 会话中,
它会拉取仓库并为你配置好环境:
```
Clone https://github.com/tangosdev/sm64ds-decomp and set up the Super Mario 64 DS
matching-decompilation toolchain on my machine. Do these in order:
1. Read CONTRIBUTING.md and notes/setup-mwccarm.md in the repo.
2. Install the Python dependencies: ndspy, capstone, pyelftools.
3. mwccarm cannot be downloaded automatically: it is in the DS-decomp
Discord (https://discord.com/invite/gwN6M3HQrA, resources channel, mwccarm.zip) and I
have to fetch it by hand. Wait for me to do that, then help me place it under
tools/mwccarm/.
4. Unpack my own SM64DS cartridge dump with tools/unpack.py. This writes the ARM9, ARM7,
and overlay binaries into extracted/ (gitignored), including both the compressed
arm9.bin and the decompressed arm9_dec.bin. Use the decompressed image for disassembly.
5. Confirm the toolchain runs: re-match a function we have already landed (any file in
src/) with tools/match.py and check that it still reports identical bytes.
6. Before matching, read CLAIMS.md and pick a module or address range that nobody has
claimed. Add a row claiming it (range, my handle, date), commit it on its own, and
push, so no one else grinds the same functions. Work only inside that claimed range.
7. Pick an unmatched function from the claimed range, help me write matching C for it,
and verify with tools/match.py that it compiles to the same bytes as the ROM.
Use only my own legally dumped ROM. Never commit the ROM or anything extracted from it.
```
**Claude 的投入度与命中率。** 如果你通过 Claude 智能体批量运行
函数,请关注**命中率**(验证通过的函数除以
尝试的函数)。早期/全新的子系统命中率可达 50% 或更高;随着一个区域内容易的
函数被匹配,
命中率会下降。Claude Code 的推理努力度设置在这里很重要:更高的努力度可以
转化更多困难的残留部分,但每次尝试会消耗更多的 token。当一批
命中率下降到**低于 25%**时的经验法则:
- **如果你不在乎成本,就继续保持原样。** 它仍然能产出真实的函数,但
大部分 token 都花在了失败的尝试上,因此效率低下。
- **提高推理努力度**(例如从中到高)。对于困难的残留部分,这可以显著
转化更多的函数,并且*每个实际产出的函数*的成本通常更低,即使
每次尝试的成本更高。
- **使用主 Claude 会话手动攻克。** 当即使是高努力度也触及瓶颈时,
剩下的函数就是真正的一次性逻辑了。放弃批量分发,让主
会话一次匹配一个(反汇编、编写 C 代码、使用 `tools/match.py` 验证),
或者如果你发现了重复的形态,就构建一个新的模板规则。
## 许可证
此仓库中的原创作品(C 代码、工具、笔记)在 MIT
许可证下发布,请参阅 [LICENSE](LICENSE)。这仅适用于该原创作品,并且不授予
任何 Nintendo 素材的权利,此处不包含任何 Nintendo 素材。
标签:Super Mario 64 DS, URL提取, 云资产清单, 任天堂DS, 反编译, 客户端加密, 游戏开发, 逆向工具, 逆向工程