3DS游戏格式转换实战:3dsconv 把 CCI 镜像一键变成可安装 CIA
【免费下载链接】3dsconvPython script to convert Nintendo 3DS CCI (".cci", ".3ds") files to the CIA format项目地址: https://gitcode.com/gh_mirrors/3d/3dsconv
当你把 3DS 卡带转储成.3ds镜像,兴冲冲拷进主机却发现根本装不上时,卡住的往往就是格式转换这一步。3dsconv是一个专注解决该痛点的 Python 工具:它能把 CCI(.3ds/.cci)卡带镜像转换为 3DS 可直接安装的 CIA 格式,全程一条命令,加密检测、密钥查找、哈希校验全部自动完成。
想装却装不上?先搞懂 .3ds 与 .cia 的差别
在动手之前,花一分钟认清三种常见格式,你会更容易理解这个工具到底在做什么:
| 格式 | 全称 | 常见来源 | 能否直接安装 |
|---|---|---|---|
.3ds/.cci | CTR Cart Image(卡带镜像) | GodMode9、Decrypt9WIP 转储 | ❌ 不能 |
.cia | CTR Importable Archive(可导入归档) | 数字商店抓取、转换生成 | ✅ 能 |
.cci(NAND 转储) | 机身存储镜像 | 系统 NAND 备份 | ❌ 不能,且会被拒收 |
一句话概括:.3ds是"卡带的完整快照",.cia是"主机认识的安装包"。两者内部都藏着 NCSD/NCCH 分区结构,但 CIA 额外包含 ticket、TMD、证书链与元数据,这正是转换工具要替你补齐的部分。
顺带一提:现在 GodMode9 等工具已经能直接把卡带转储为 CIA,但如果你手里有存量镜像(早些年转储的
.3ds文件),3dsconv依然是最高效的补救方案——官方 README 也明确说明了这一点。
为什么 3dsconv 是处理存量镜像的最省事选择
不吹不黑,它最打动人的地方是把"手工流程"压缩成了"一条命令"。具体拆开看:
- 自动识别加密状态——未加密、原始 NCCH 加密、zerokey 加密,三种情况无需你手动判断;
- 智能寻找密钥——boot9 文件按预设顺序逐个探测,找不到再向你求助;
- 天然支持批量——一次传入多个文件甚至通配符,逐个转换;
- 内置完整性校验——每个分区写入前都会核对 SHA-256,坏文件会被拦下而不是悄悄产出废包;
- MIT 协议纯 Python——想改想学都自由,单文件脚本极易阅读。
和手工方案放在一起对比更直观:
| 环节 | 手工处理 | 使用 3dsconv |
|---|---|---|
| 判断加密类型 | 逐字节读标志位 | 自动完成 |
| 准备密钥文件 | 手动指定路径 | 按顺序自动探测 |
| 处理多个文件 | 一个个跑 | 一次传参批量处理 |
| 文件完整性 | 不可见 | 内置哈希校验 |
三分钟跑通第一次转换:从装依赖到出包
环境要求只有一条:Python 3 及以上,外加一个加密依赖pyaes。按下面三步走,最快三分钟就能看到第一个.cia出炉。
第一步:克隆并安装依赖
git clone https://gitcode.com/gh_mirrors/3d/3dsconv cd 3dsconv pip install pyaes第二步:确认工具就绪
python3 3dsconv/3dsconv.py --help看到版本号3dsconv.py ~ version 4.21和 "Convert Nintendo 3DS CCI (.3ds/.cci) to CIA" 的帮助信息,就说明一切正常。也可以顺手把脚本安装成全局命令,之后直接敲3dsconv即可:
python3 setup.py install第三步:执行转换
python3 3dsconv/3dsconv.py my_game.3ds --output=converted/不指定--output时,转换结果默认输出到当前目录;命令执行时你会看到实时进度条和分区写入日志,结束后在同目录拿到my_game.cia。对于未加密的镜像,到这里就已经全部完成了。
加密不是拦路虎:三种加密状态如何被自动识别
加密检测是 3dsconv 最核心的自动化能力。它读取 CCI 中 Game Executable 分区头部的加密标志位,用两个位即可区分三种状态,逻辑精简到十几行(核心转换脚本 中可找到完整实现):
# 简化自 3dsconv/3dsconv.py 的加密判断逻辑 rom.seek(game_cxi_offset + 0x18F) encryption_bitmask = rom.read(1)[0] encrypted = not (encryption_bitmask & 0x4) # bit2 = 1 表示未加密 zerokey_encrypted = encryption_bitmask & 0x1 # bit0 = 1 表示 zerokey对应到运行时的输出,你会看到工具明确告诉你正在处理哪种镜像:
Converting my_game (encrypted)... # 原始 NCCH 加密,需要 boot9 Converting demo (zerokey encrypted)... # zerokey 加密,密钥为全零 Converting homebrew (decrypted)... # 未加密,直接转换针对不同状态,工具会采取不同的解密策略:
- 未加密:直接读取分区,无需任何密钥;
- zerokey 加密:使用全零密钥解密,同样不需要 boot9;
- 原始 NCCH 加密:从 boot9 中提取 slot 0x2C 密钥,结合标题 ID 推导会话密钥,这一路才真正依赖密钥文件。
如果你的镜像明明未加密,却被错误地按加密处理,可以使用--ignore-encryption强制按未加密镜像转换;如果文件哈希对不上又确定镜像没问题,--ignore-bad-hashes可以放行转换。
解密钥匙 boot9.bin:查找顺序与真伪校验
处理原始 NCCH 加密镜像时,工具需要一个ARM9 bootROM来提取密钥。它不会让你手动去翻路径,而是按固定顺序自动探测:
| 查找顺序 | 查找位置 | 说明 |
|---|---|---|
| 1 | --boot9=<file>参数 /BOOT9_PATH环境变量 | 显式指定,优先级最高 |
| 2 | 当前目录boot9.bin | 完整版 bootROM |
| 3 | 当前目录boot9_prot.bin | 保护版 bootROM |
| 4 | ~/.3ds/boot9.bin | 用户目录完整版 |
| 5 | ~/.3ds/boot9_prot.bin | 用户目录保护版 |
想一劳永逸,可以用环境变量固定密钥位置:
export BOOT9_PATH="$HOME/keys/boot9.bin"拿到 boot9 之后,建议先校验哈希确认文件完整:
| 文件 | SHA-256 |
|---|---|
boot9.bin | 2f88744feed717856386400a44bba4b9ca62e76a32c715d4f309c399bf28166f |
boot9_prot.bin | 7331f7edece3dd33f2ab4bd0b3a5d607229fd19212c10b734cedcaf78c1a7b98 |
小知识:boot9 需要你在 3DS 上通过 boot9strap 引导转储,开机时按住 START+SELECT+X 即可得到
sdmc:/boot9strap/boot9.bin。工具在校验密钥时还会比对密钥的 MD5 指纹,发现文件损坏会直接提示 "Corrupt file",而不是带着坏密钥硬跑。
幕后拆解:一个 CIA 文件是如何被拼装出来的
转换不是简单"换个容器",背后是一套严格的拼装流程。3dsconv 按以下步骤完成重构:
- 校验文件身份——检查偏移
0x100处的NCSD魔数与 Game Executable 分区的NCCH魔数,非 CCI 文件(包括 NAND 转储)直接拒绝; - 读取元信息——提取 Title ID、Game Executable CXI、Manual CFA、Download Play 子容器 CFA 的偏移与大小;
- 判断加密状态——按上一节逻辑确定解密策略与密钥;
- 解密并校验 ExtHeader——比对头部 SHA-256,随后打补丁将其标记为 SD 标题;
- 提取图标——从 ExeFS 中定位
icon文件(SMDH),解密后放入 CIA 的 Meta 区域; - 流式写入内容——以 8MB 为块单位读取各分区,边读边写边累计 SHA-256;
- 回填哈希并收尾——更新 TMD 中的内容记录哈希、证书链签名与 Meta 区。
每个分区写完后,工具都会打印对应的 SHA-256 摘要并回填进 TMD,保证生成的 CIA 在结构上自洽。这也解释了为什么输出文件是"可直接安装"的:它不只是数据搬家,而是把 ticket、TMD、证书链、图标全部按规范补齐了。
一次喂一整批:批量转换镜像的正确姿势
命令行参数天然支持多个文件,只要文件名或通配符对得上,就能批量开工:
# 显式列出多个文件 python3 3dsconv/3dsconv.py game1.3ds game2.3ds game3.3ds --output=cia_files/ # 使用通配符一次吃进整个目录 python3 3dsconv/3dsconv.py ./roms/*.3ds --output=cia_files/批量场景下有两个细节值得注意:
- 已存在文件的处理:默认情况下,如果同名
.cia已存在,工具会跳过并提示,需要强制覆盖时加--overwrite; - 通配符自动展开:脚本内部用 glob 解析参数,所以
*.3ds、*.cci这类模式可以直接用,不存在的文件也会被明确报错。
如果想按批次节奏处理(比如分目录、分批跑,避免一次积压太多),用一段简单的循环即可:
for f in ./roms/*.3ds; do python3 3dsconv/3dsconv.py "$f" --output=./cia --overwrite done面向开发者的隐藏开关:--dev-keys 与证书链
如果你是自制软件开发者,需要转换开发机(dev-unit)专用镜像,就要用到--dev-keys:
python3 3dsconv/3dsconv.py system_updater.3ds --dev-keys开启后,工具会寻找开发版证书链文件certchain-dev.bin(依次检查当前目录与~/.3ds/),其 SHA-256 应为7921ae82c9dcf411351314f2fe2c67378c6a872d2524f71b3c002b4d4a56846f。它可以从一份开发版 CIA 中提取,例如通过ctrtool --certs=certchain-dev.bin title.cia导出。
这里要特别提醒一个边界:--dev-keys并不会改变输出的加密状态。转换出的 CIA 依然使用开发密钥加密,只能在开发机上安装。如果你拿零售版镜像硬套开发密钥,工具会明确拒绝或产出无法使用的包——这是设计使然,不是 bug。
四个高频翻车现场与急救方案
实战中最常遇到的报错,基本都集中在下面四类:
| 症状 | 常见原因 | 处置方案 |
|---|---|---|
pyaes not found, encryption will not be supported | 未安装加密依赖 | 执行pip install pyaes |
bootROM not found, encryption will not be supported | 没找到 boot9 | 放入boot9.bin/boot9_prot.bin,或用--boot9=显式指定 |
This file may be corrupt (invalid ExtHeader hash) | 镜像被改动,或加密判断出错 | 确定镜像没问题时,用--ignore-bad-hashes放行;未加密镜像误判则加--ignore-encryption |
"xxx" already exists | 目标 CIA 已存在 | 追加--overwrite强制覆盖 |
还有一类常见误操作是把NAND 转储当卡带镜像传入——工具会以 "missing NCSD magic" 或 "missing NCCH magic" 直接拒绝,这是保护机制在工作,换个正确的.3ds文件即可。
如果转换中途卡住,优先检查磁盘剩余空间(建议预留输出文件体积的两倍),大文件场景下把镜像放到 SSD 上也能明显提速。
让转换更快更稳的五个小习惯
最后分享几个我实际用下来觉得值得养成的习惯:
- 固定密钥位置——把 boot9 统一放到
~/.3ds/或通过BOOT9_PATH指定,避免每次临时找文件; - 转换前先
--help确认选项——参数拼写是最高频的翻车点; - 批量时善用通配符与
--overwrite——重跑一遍也不用先手动清理旧文件; - 怀疑结果时加
--verbose——会输出密钥、哈希、分区等完整调试信息,定位问题一目了然; - 在 Windows 上做成免 Python 的 exe——项目支持用 py2exe 打包,运行
py -3.4 -m py2exe.build_exe 3dsconv.py -b 0后即可在dist目录拿到3dsconv.exe,把.3ds文件直接拖到 exe 上就能转换。
从镜像到上机:完整工具链与进阶学习方向
3dsconv 只是整条链路中的一环,把它放进更大的生态里看,脉络更清晰:
- 转储——在 3DS 上用 GodMode9 或 Decrypt9WIP 把卡带转成
.3ds; - 转换——用 3dsconv 把存量镜像转成
.cia; - 分析——需要深挖内部结构时,可用
ctrtool查看分区与证书; - 安装——把
.cia拷贝到 SD 卡,通过 FBI 等工具安装到主机。
想深入理解工具原理,建议从这几个概念入手:NCSD(卡带容器格式)、NCCH(加密分区)、CIA 四段式结构(ticket/TMD/证书链/Meta)以及AES-CTR 模式在 3DS 加密中的应用。3dsconv本体是 MIT 协议的单文件脚本,直接读 3dsconv/3dsconv.py 就是最好的入门教材;完整的参数说明与已知限制写在 README.md,打包与安装细节见 setup.py。
作为开源项目,它也欢迎你参与:遇到问题可以提交 Issue 描述复现步骤,有想法可以提功能建议,修复了 bug 或完善了文档,别忘了回馈一个 Pull Request。
写在最后
格式转换从来不该是折腾人的事。3dsconv用最直白的方式把"检测加密 → 找到密钥 → 重构容器"这条复杂链路收敛成一条命令,让存量.3ds镜像重获新生。无论你是在整理多年收藏的老备份,还是为自制软件准备开发环境,都值得把它放进工具箱。克隆下来,跑一次--help,然后从你硬盘里那张最旧的.3ds开始——出包的那一刻,你会觉得这三分钟花得很值。
【免费下载链接】3dsconvPython script to convert Nintendo 3DS CCI (".cci", ".3ds") files to the CIA format项目地址: https://gitcode.com/gh_mirrors/3d/3dsconv
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考