libretro API 架构解读 为什么 RetroArch 能跨 100+ 平台
libretro 是什么
libretro 是一套轻量级的 C API 接口规范。它定义了"前端"和"核心"之间的交互契约:前端负责视频输出、音频输出、输入采集、存档管理;核心负责模拟逻辑本身。
RetroArch 是 libretro API 的参考前端实现——就像 Qt 有 KDE、GTK 有 GNOME,libretro 有 RetroArch。其他遵循 libretro API 的前端也存在,但 RetroArch 是功能最全、生态最成熟的那个。
为什么要设计成这样
模拟器本身(核心)和运行环境(前端)分开后,两边可以独立进化:
- 核心开发者不需要关心 Windows 和 Android 的屏幕输出差异、不需要管手柄驱动——只管实现 libretro API 定义的那几个回调函数
- 前端开发者不需要关心 FC 和 PS1 的模拟逻辑差异——只管正确调用核心的接口、正确渲染核心输出的帧
- 平台差异(Windows vs Linux vs Android vs Switch vs PS Vita)全部被前端吸收,核心可以"一次开发到处运行"
这就是 RetroArch 能跨这么多平台的根本原因——不是 RetroArch 一个程序写了 100 个平台,而是核心和前端解耦了。
核心的技术形态
每个 libretro 核心是一个动态库(.dll / .so / .dylib),导出一组标准函数:
retro_init— 初始化retro_load_game— 加载 ROMretro_run— 执行一帧模拟retro_save_state/retro_load_state— 即时存档retro_cheat_reset/retro_cheat_set— 金手指
RetroArch 运行时按主机加载对应的核心动态库,通过这些接口驱动核心工作。这也是为什么"下载核心"在 RetroArch 里就是下载一个动态库文件。
序列化:倒带和联机的基础
libretro API 有一个关键能力叫序列化(serialization)——核心可以在任意时刻把完整的模拟状态序列化成字节流(存到 .state 文件),也可以从字节流恢复到那个时刻。
RetroArch 的两个杀手级功能都依赖这个能力:
- 实时倒带(Rewind):每帧序列化一次,你按倒带键时往前翻几帧、重放这几帧,就实现了"回到过去"
- GGPO 式联机:每帧序列化后发给对端,网络延迟时双方各自回退几帧到最后同步点、重放到当前帧,实现低延迟联机
没有序列化能力的核心(早期少数核心)也能跑联机和存档,但体验会差很多。
架构对使用者意味着什么
理解了这个架构,很多使用上的困惑就能自己解释了:
| 困惑 | 解答 |
|---|---|
| 为什么 RetroArch 自己不带模拟器? | 因为核心是独立动态库,按需下载 |
| 为什么同一个核心在不同平台上通用? | 核心只依赖 libretro API,平台差异由前端吸收 |
| 为什么一个游戏换个核心可能玩不了? | 不同核心的实现严格度和兼容性不同 |
| 为什么即时存档换了核心就读不出来? | 因为存档是序列化的核心内部状态,和核心绑定 |
| 为什么 shaders 是跨核心通用的? | shaders 运行在前端的渲染管线里,核心只管输出帧 |
可以不用深究
对于日常使用者来说,理解到这里就够了。libretro API 的具体函数签名、序列化格式、音频同步算法等底层细节不需要掌握——碰到具体问题时回来查"这是前端的问题还是核心的问题"即可。