【免费下载链接】LostOdysseyRecomp
Experimental native PC port of Lost Odyssey using static recompilation. No game assets included.
本文带你完整看懂LostOdysseyRecomp跳表(jump table / switch table)的处理流水线。LostOdysseyRecomp 是一个基于静态重编译的《失落的奥德赛》(Lost Odyssey)实验性 PC 移植项目。由于 Xenon(PowerPC)指令集中存在大量通过bctr完成的计算跳转,重编译器必须清楚"每张跳表跳到哪些地址"——自动发现、手工补全与自动化脚本三者缺一不可。
什么是跳表?为什么它对重编译器至关重要
跳表是编译器为 switch 分派生成的地址数组:CPU 以寄存器值作索引,从表中取出目标地址后再用bctr跳转过去。在这款游戏 14.3 MB 的.text代码里,共有841 张这样的表。
如果重编译器识别不出跳表,会出现两类事故:
bctr被误当成尾调用,函数边界被截短;- 被截断函数内部的
b指令变成"跳出函数"的未解析目标(项目实测首轮就有 91 个 switch 站点、96 个未解析目标)。
换句话说,跳表配置的质量直接决定重编译输出是否完整,也就决定了游戏能不能稳定运行。
自动发现:XenonAnalyse 生成 switch_tables.toml
XenonAnalyse 是项目 XenonRecomp 工具链自带的静态分析器(由 build_tools.bat 一并编译),它借助 XEX 镜像中的.pdata函数表划定函数边界,自动扫描跳表并把结果写入 switch_tables.toml(约 2 万行、841 张绝对地址表)。每张表记录 4 个字段:
| 字段 | 含义 |
|---|---|
base | 读表的跳转指令所在代码地址(索引在此处算出) |
r | 充当表索引的寄存器 |
default | 越界时的默认分支 |
labels | 表中每一项的目标地址 |
该文件通过主配置 LostOdysseyRecomp.toml 中的switch_table_file_path = "switch_tables.toml"字段被重编译器引用。
手工补全:switch_tables_manual.toml 里的漏网之鱼
自动检测不可能覆盖所有写法,XenonAnalyse 漏掉的表就手工写进 switch_tables_manual.toml。目前手工补了 2 张表:
① 战斗环 UI 跳表—— 第一张手工表(对应下面这张战斗场景):
[[switch]] base = 0x82B14808 r = 10 default = 0x82B148BC labels = [0x82B14830, 0x82B14878, 0x82B14890, 0x82B148A4]文件注释写明了后果:不补这张表,bctr会被当成尾调用,从而跳过栈恢复逻辑。
② u16 短偏移跳表—— 基址 0x82FB21AC、16 项的相对偏移表。XenonAnalyse 只识别绝对地址表,这种 16 位偏移写法它发现不了,只能人工列出全部 16 个标签。
⚠️ 一个容易踩的坑:
switch_tables.toml每次重跑 XenonAnalyse 都会重新生成,所以重新生成后必须把手工文件的内容再次 append到它末尾——文件头注释里也写明了这条规则。
自动脚本:gen_function_bounds.py 把跳表变成函数边界
gen_function_bounds.py(约 170 行)解决"带跳表的函数被截短"这一连锁问题,核心有 5 条规则:
- 累积未解析目标:重编译输出中的
// ERROR <addr>目标各自成为一个新函数,跨轮累积在config/branch_targets.txt; - 补全 .pdata 之外的表:每张
labels未被所属.pdata函数覆盖的跳表,都从表前最近符号生成一个函数,一直延伸到最远标签之后的下一个符号; - 手工条目:function_bounds_manual.txt 中目前一条(
827C39F8 18)——否则这个小桩会流进后面的 pdata 函数,"抢走"它的跳表; - 指针专属函数:只被虚表/函数指针表引用、不在
.pdata也不被bl指向的函数,边界分析完全看不见,会被并进前一个函数尾部,运行时虚函数调用直接跳到地址 0 崩溃。脚本扫描整个镜像的 4 字节对齐指针并用基线映射表(baseline_func_mapping.txt)过滤误报,最终命中 43 个; - 代码中物化的地址:
lis+addi/ori在 64 字节窗口内拼出的地址被识别为运行时写入对象的函数指针。
生成结果写入主配置的functions = [...]列表(116 项,含 47 个指针专属函数)。
协同流程:三步配合,迭代到收敛
三个环节串成一条"自动 + 手工 + 脚本"的流水线,约 8 轮迭代后收敛到 0 错误:
| 步骤 | 动作 | 验收标准 |
|---|---|---|
| 1 | 跑 XenonAnalyse,重新生成switch_tables.toml | 得到 841 张表 |
| 2 | 漏检表补进switch_tables_manual.toml,再 append 到自动文件末尾 | grep -l '// ERROR' ppc/*.cpp返回 0 |
| 3 | gen_function_bounds.py生成functions边界列表 | 未解析目标数逐轮下降 |
| 4 | python -B tools/ppc_codegen.py generate重新生成客制代码 | 0 未解析目标、0 跳表错误 |
整个过程(含invalid_instructions对异常处理描述符的跳过——不跳过它们,pass2 边界分析会把描述符当代码,在带跳表的函数上死循环)都有完整记录,可查阅专题笔记 recomp.zh-CN.md 与构建说明 BUILDING.md。
相关文件路径速查
- 自动跳表:switch_tables.toml
- 手工跳表:switch_tables_manual.toml
- 主配置(
functions、midasm_hook、invalid_instructions):LostOdysseyRecomp.toml - 手工函数边界条目:function_bounds_manual.txt
- 边界生成脚本:gen_function_bounds.py
- 工具链构建脚本:build_tools.bat
- 代码生成入口:ppc_codegen.py
- 专题笔记:recomp.zh-CN.md、BUILDING.md
📌 一句话总结:XenonAnalyse 负责"量大面广"的自动检测,手工 TOML 兜住自动化的盲区,gen_function_bounds.py再把跳表信息转化为精确的函数边界——三者协同,才能让 14 MB 的 Xenon 代码被完整、可运行地重编译到 PC 上。
【免费下载链接】LostOdysseyRecomp
Experimental native PC port of Lost Odyssey using static recompilation. No game assets included.
相关推荐
如何在10分钟内快速上手CSLA框架?新手必备指南
如何在10分钟内快速上手CSLA框架?新手必备指南 CSLA框架是.NET应用程序中业务逻辑的理想家园,它提供了一套完整的架构模式和工具,帮助开发者构建强大、可
软件架构后端TaskbarX命令行批处理脚本:多任务自动化配置指南
TaskbarX命令行批处理脚本:多任务自动化配置指南 痛点与解决方案 Windows任务栏图标默认靠左对齐,手动调整位置和样式不仅繁琐,多显示器环境下的配置同
桌面应用如何备份QQ空间?3步免费导出全部历史说说到Excel
如何备份QQ空间?3步免费导出全部历史说说到Excel 想找回大学时写的那批说说,在QQ空间里一条条往上翻,翻到手指发酸还是嫌慢。试试 GetQzonehist
网页爬虫数据分析
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考