打造专属复古游戏主机:手把手教你从零构建 Batocera 定制镜像
你是否厌倦了反复下载别人打包的 Batocera 整合包,却不知道里面藏了什么?是否希望拥有一套完全由自己掌控、开机即用、风格独特的家庭游戏系统?如果你的答案是“想,但不知道从哪开始”,那么这篇文章就是为你准备的。
我们不讲空话,也不复制粘贴官方文档。本文将带你从一张空白 SD 卡的概念出发,一步步实现一个真正属于你的Batocera 游戏整合包镜像——不仅能烧录使用,还能随时迭代、安全合规、高度个性化。
这不是简单的“复制 ROM”教程,而是一次深入嵌入式 Linux 系统底层的实战之旅。
为什么非要“自己做”?第三方整合包真不行吗?
先泼一盆冷水:市面上大多数所谓的“Batocera 游戏整合包”,本质上是一个“高风险黑箱”。
- 来源不明:ROM 从哪来?BIOS 是什么版本?有没有后门程序?
- 无法更新:一旦发布,基本冻结。新游戏加不进,Bug 修不了。
- 千篇一律:UI 主题、按键映射、音频输出全固定,改起来费劲。
- 法律隐患:直接打包受版权保护的内容,分发即侵权。
而你自己做的整合包呢?
✅ 全程透明可控
✅ 只导入你合法拥有的 ROM
✅ 随时可升级、可调试
✅ 支持自动化部署和批量分发
这才是真正的“我的游戏我做主”。
核心思路:理解 Batocera 的“两层架构”
要定制 Batocera,首先要明白它的设计哲学:系统与数据分离。
你可以把它想象成一台“只读光盘 + 可写 U 盘”的组合:
| 层级 | 内容 | 是否可写 | 作用 |
|---|---|---|---|
| 只读层(rootfs.sqsh) | 操作系统内核、模拟器、EmulationStation 前端 | ❌ 否 | 提供运行环境,保证稳定 |
| 可写层(/userdata) | ROM、BIOS、配置文件、主题、截图 | ✅ 是 | 存放所有个性化内容 |
🧠 关键洞察:我们定制的核心,就是替换只读层的
rootfs.sqsh,并在其中预置对/userdata的初始化逻辑。
这意味着:哪怕你换设备、重烧卡,只要 userdata 分区存在,你的游戏库和设置就还在。
第一步:拆解并重建系统镜像
1. 下载官方镜像,别急着烧!
以 Raspberry Pi 4 版本为例:
wget https://github.com/batocera-linux/batocera.linux/releases/download/rpi4/batocera-rpi4.x86_64.img.gz gunzip batocera-rpi4.x86_64.img.gz得到batocera-rpi4.img,这是个完整的磁盘镜像,包含多个分区。
2. 查看分区结构
fdisk -l batocera-rpi4.img你会看到类似输出:
Device Boot Start End Sectors Size Id Type batocera-rpi4.img1 2048 34815 32768 16M c W95 FAT32 (LBA) batocera-rpi4.img2 34816 1277951 1243136 607M 83 Linux- 分区1(FAT32):
/boot,存放启动文件和rootfs.sqsh - 分区2(ext4):保留或备用,某些版本用于持久化配置
我们的目标是修改第一个分区里的rootfs.sqsh。
3. 挂载 BOOT 分区并提取 squashfs
mkdir /mnt/bat_boot sudo mount -o loop,offset=$((2048*512)) batocera-rpi4.img /mnt/bat_boot cp /mnt/bat_boot/rootfs.sqsh ./rootfs.sqsh.orig sudo umount /mnt/bat_boot🔍 偏移量计算公式:
Start Sector × 512 bytes
第二步:解压、修改、重新打包 rootfs
为什么要用 SquashFS?
SquashFS 是一种高压缩、只读的文件系统,特别适合嵌入式场景。Batocera 用它来打包整个操作系统,好处显而易见:
- 启动快:一次性解压到内存
- 占用小:ZSTD 压缩下体积减少 40%+
- 安全强:用户无法误删系统文件
开始操作
# 解压原始镜像 unsquashfs rootfs.sqsh.orig # 进入解压后的目录 cd squashfs-root现在你看到的就是 Batocera 的完整根文件系统。可以自由添加:
- 自定义启动动画(
/usr/share/batocera/splash/) - 预装工具脚本(如网络诊断、备份脚本)
- 修改默认配置模板
- 移除不需要的模拟器(节省空间)
示例:注入一个开机自启脚本
创建/etc/init.d/custom-startup:
#!/bin/sh echo "[Custom] Running post-boot setup..." # 设置默认音量 echo 'audio_volume = "30"' >> /userdata/system/configs/retroarch.cfg # 如果检测到特定U盘,自动同步ROM if blkid | grep -q 'LABEL="GAMES"'; then mkdir /tmp/roms && mount -L GAMES /tmp/roms rsync -av --ignore-existing /tmp/roms/* /userdata/roms/ umount /tmp/roms && rmdir /tmp/roms fi # 开启SSH便于调试(生产环境建议关闭) touch /userdata/enable/ssh赋予执行权限:
chmod +x etc/init.d/custom-startup重新打包为新的 rootfs.sqsh
sudo mksquashfs squashfs-root ../new_rootfs.sqsh \ -comp zstd \ -e boot \ -keep-as-directory \ -wildcards参数说明:
| 参数 | 作用 |
|---|---|
-comp zstd | 使用 ZSTD 压缩算法,速度与压缩比均衡 |
-e boot | 排除 boot 目录,避免重复打包引导文件 |
-keep-as-directory | 保留符号链接和特殊文件属性 |
-wildcards | 支持通配符匹配 |
第三步:合成最终可烧录镜像
我们需要把修改后的new_rootfs.sqsh写回到原始镜像的 BOOT 分区中。
方法一:直接挂载修改(推荐新手)
# 挂载原镜像的 BOOT 分区 sudo mount -o loop,offset=1048576 batocera-rpi4.img /mnt/bat_boot # 替换 rootfs sudo cp new_rootfs.sqsh /mnt/bat_boot/rootfs.sqsh # 卸载 sudo umount /mnt/bat_boot搞定!这个batocera-rpi4.img已经是你自己的定制版了。
方法二:创建更大容量的新镜像(高级玩家)
如果你想预分配 userdata 空间,可以用以下方式扩容:
# 创建一个更大的空白镜像(例如 8GB) truncate -s 8G custom_batocera.img # 使用 sfdisk 复制原分区表并调整大小 sfdisk --dump batocera-rpi4.img > part_table.txt sfdisk custom_batocera.img < part_table.txt # 格式化并挂载,手动复制文件 # ...(略,适用于需要精细控制的场景)第四步:规范组织你的游戏库
再强大的系统,没有好内容也白搭。记住 Batocera 的三大铁律:
✅ 正确路径结构
/userdata/roms/<platform>/xxx.<ext>常见平台名对照表:
| 平台 | 对应目录名 |
|---|---|
| 超级任天堂 | snes |
| 红白机 | nes |
| PS1 | psx |
| 街机 | arcade |
| 世嘉MD | megadrive |
| Game Boy | gb |
✅ BIOS 文件必须到位
路径:/userdata/bios/
常见必需 BIOS:
scph1001.bin(PS1)sgb.bios(SGB)mpr-18933.bin(Neo Geo)sega_101.bin(MD)
⚠️ 缺少 BIOS = 对应游戏无法运行
✅ ROM 命名尽量标准
推荐使用 No-Intro 或 Redump 标准命名,这样 EmulationStation 才能自动匹配封面、描述和发行信息。
比如:
Super Mario World (USA).sfc Final Fantasy VII (USA) (Disc 1).cue第五步:让一切“自动化”——这才是高手的做法
真正的“整合包”,不是静态镜像,而是智能系统。
实现“插电即用”的魔法
设想这样一个场景:
- 用户拿到一张烧好的卡,插入树莓派;
- 第一次开机,系统自动创建 userdata;
- 检测到外接 U 盘名为 “ROMS”,自动同步游戏;
- 设置默认主题和音量;
- 启动 EmulationStation,满屏游戏列表出现。
这一切都可以通过脚本完成。
在custom-startup中加入判断逻辑
# 判断是否首次启动(userdata刚创建) if [ ! -f /userdata/.first_boot_done ]; then # 同步ROM if [ -d "/tmp/roms" ]; then rsync -av /tmp/roms/* /userdata/roms/ fi # 应用默认主题 mkdir -p /userdata/system/configs/emulationstation/ echo 'gamelist_style = "full"' > /userdata/system/configs/emulationstation/es_settings.cfg # 标记已完成 touch /userdata/.first_boot_done fi更进一步:支持网络挂载 NAS
# 尝试挂载局域网NAS mount -t cifs //nas.local/games /tmp/nas_games -o username=guest,password=,vers=2.0配合 cron 定时任务,甚至可以实现“每日自动拉取新增游戏”。
常见坑点与避坑指南
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 替换 rootfs 后无法启动 | 压缩参数不兼容或损坏 | 用file rootfs.sqsh检查类型,确保与原版一致 |
| ROM 不显示 | 目录名错误或权限问题 | 检查/userdata/roms/下是否有对应文件夹 |
| 游戏黑屏 | 缺少 BIOS 或核心不匹配 | 查看日志/var/log/messages |
| 启动慢 | SD 卡性能差或镜像过大 | 使用 Class 10 以上卡,精简不必要的模拟器 |
| SSH 无法开启 | 忘记创建 enable 文件 | touch /userdata/enable/ssh |
最终成果:你得到了什么?
你现在拥有的不再只是一个“游戏系统”,而是一个可复制、可扩展、可持续演进的技术资产:
- 一个私有的
.img镜像文件,可用于批量烧录; - 一套完整的构建流程,未来可一键更新;
- 一份清晰的文档,告诉家人如何合法导入游戏;
- 一套自动化机制,让每次新增游戏都变得简单。
更重要的是:你知道它每一行代码从哪里来,每一个文件为什么存在。
下一步还能怎么玩?
这套体系只是起点。有了基础框架,你可以继续深挖:
🔧接入 CI/CD 流水线
用 GitHub Actions 实现“提交配置 → 自动生成镜像 → 发布下载链接”的全自动流程。
🎨集成 AI 元数据补全
编写脚本调用 TheGamesDB API 或 Steam Grid DB,自动下载缺失的封面图和简介。
🌐开发 Web 管理后台
基于 Flask + Bootstrap 做个轻量网页,远程管理 ROM 库、查看运行状态、推送更新。
💾对接云存储
通过 rclone 挂载 Google Drive 或 OneDrive,实现跨设备同步游戏进度。
写在最后
复古游戏的魅力,从来不只是“玩老游戏”那么简单。
它是对技术的好奇,是对经典的致敬,更是对“掌控感”的追求。
当你亲手打造出一台从内到外都属于自己的游戏主机时,那种成就感,远超任何现成整合包带来的便利。
所以,别再等了。
下载镜像,打开终端,敲下第一行命令吧。
你的专属 Batocera 世界,就此开启。
如果你在实现过程中遇到问题,欢迎留言交流。我们一起把这台“时光机”造得更完美。