不用模拟器也能玩PS5游戏?拆解AnyPS5的"非模拟器魔法":relinker重链接+PRX库+RDNA到SPIR-V
【免费下载链接】AnyPS5Tool for automatic PS5 executables porting to Linux and Windows项目地址: https://gitcode.com/GitHub_Trending/an/AnyPS5
PS5 上的 x86-64 游戏,能不能不经过模拟器直接在 PC 上原生运行?开源项目 AnyPS5 给出了一个大胆且与众不同的答案:不模拟、不翻译执行,而是把 PS5 可执行文件静态移植成 Linux/Windows 原生程序。项目自称 "Tool for automatic PS5 executables porting to Linux and Windows",在 cnBeta、3DM 等游戏媒体的报道中,"直接运行 PS5 游戏"成为话题焦点;而在技术社区里,人们更关心它背后那条"relinker 重链接 + PRX 系统库 + RDNA 到 SPIR-V 着色器重编译"的三步链路。本文结合仓库源码与公开情报,拆开这层"非模拟器魔法",讲清楚它为什么不需要 CPU 模拟、如何用"可运行桩 + 真实核心"的策略把移植成本压到最低,以及它今天到底能跑到什么程度。
一个"移植器",而不是模拟器
先厘清概念。传统思路是模拟器:在 PC 上再造一个 PS5 软件环境,CPU 指令逐条解释或二进制翻译,游戏跑在模拟器进程内部。AnyPS5 完全不是这个路线——它的 README 说得直白:
Includes a relinker that converts executable to the target system's native format and implementations of system prx libraries suitable for dynamic linking.No emulation or separate runtime process.
也就是说,转换后的游戏就是一个普通的原生进程:CPU 指令直接执行,图形走 Vulkan 原生管线,系统调用和库函数链接到项目自研的 PRX 实现。所有"翻译"工作都在构建期完成,运行时没有任何中间层开销。这也是社区文章反复强调"没有进程开销、没有固件依赖"的根源。
三步核心链路
AnyPS5 的完整流水线,可以精确对应到仓库里三个核心目录:core/relinker(重链接器)、core/libs/prx(系统库实现)、core/shader/recompiler(着色器重编译器)。架构文档 docs/dev/ARCHITECTURE.md 给出了两条清晰的流程图。
第一步:relinker 重链接——把 PS5 ELF 变成原生 ELF/PE
入口在 core/relinker/main.cpp,它按固定顺序执行整个转换:
auto result = pipeline->Relink(sourceBytes); // ...应用 patch... guestArtifacts = Relinker::GuestModuleBuilder().Build(...); fileWriter.Write(absPath, executableBytes);RelinkerPipeline(声明见 RelinkerPipeline.hpp)承担了核心工作:读取 ELF、按 NID 解析导入、扫描系统调用(SyscallScanner)、过滤未使用的 NID、构建 SysV 动态节,最后由LinuxElfPatcher或WindowsPePatcher分别输出 Linux ELF 或 Windows PE。
这里的关键在于 PS5 的系统库符号不是普通名字,而是一串 11 字符的NID。NID 的算法实现在 NidCompute.cpp:对"符号名 + 16 字节固定后缀"做 SHA-1,取摘要中 8 个字节反转后,用自定义的 base64 字母表编码成 11 个字符。重链接器解析出游戏引用了哪些 NID、哪个库、哪个调用位置,然后为它们生成新的动态节;同时,GuestModuleBuilder 还会把游戏自带的sce_module/*捆绑模块一并转换,输出到app0/下。最终产物的运行布局是:
app.elf (Linux) 或 app.exe (Windows) libs/ ← 自研系统库 *.prx app0/ ← 游戏资源 + 转换后的模块值得注意的细节还有两个:一是--to-intel选项(见 docs/user/USAGE.md),PS5 的 AMD CPU 上有少数 AMD 专属指令(如VRSQRTPS、VRCPPS),在 Intel 主机上无法执行,relinker 会用 codegen 在构建期把它们降级或替换成跳板(trampoline),main.cpp里逐条打印 "Intel substitution" 日志;二是unused-filter=0/1/2三级未用符号过滤策略,从全量保留到基于 CFG/GOT 分析的严格可达性分析,粒度越细输出越小,但对输入 ELF 的合规性要求越高——这正是社区那篇"三级未用符号过滤终极对比"文章讨论的技术细节。
第二步:自研 PRX 系统库——用 C++ 重写 PS5 的 libSce*
PS5 游戏依赖一整套系统库:输入、音频、图形驱动、HTTP、字体、存档、对话框……AnyPS5 的策略不是在运行时劫持,而是为每个库编写一份原生 C++ 实现,编译成共享库(.prx),构建后由nid_patcher(core/libs/nid)把每个导出符号重命名为其 NID,这样游戏按 NID 动态链接时就能命中这些实现:
core/libs/prx/* → 编译为共享库 → nid_patcher 重命名导出 → libs/*.prx以 libScePad/Export.cpp 为例,它实现了scePadGetControllerInformation、scePadGetHandle、scePadDeviceClassParseData等 API,不仅返回结构体,连细节都很讲究:触摸板分辨率 1920×943、摇杆死区 2、连接类型LOCAL、错误码严格对齐 PS5 原生语义(如PAD_ERROR_DEVICE_NOT_CONNECTED = 0x80920007)。输入层还通过 SDL 支持手柄自动识别与键鼠映射,配置见 docs/user/INPUT_MAPPING.md。
库的覆盖面从环境列表可见一斑:libSceAgcDriver、libSceAgc、libSceAudioOut、libScePad、libSceFont、libSceVideoOut、libSceHttp、libSceAvPlayer、libSceSaveData、libSceNpTrophy2……几十个库各有 Export.cpp。社区那篇"libSceHttp HTTP 客户端移植实录"就是这类工作的一个缩影:Uri.cpp 实现了符合 RFC 3986 的sceHttpUriParse/sceHttpUriBuild/sceHttpUriEscape,包括 scheme 识别、removeDotSegments路径归并、默认端口推断,以及用掩码标志位(URI_BUILD_WITH_SCHEME、URI_BUILD_WITH_HOSTNAME…)控制拼装——严格遵循 PS5 错误码规范与"两次调用缓冲区协议"。
转换出的游戏到底缺哪些符号?relinker --registry会生成registry.json清单,配合 tools/import_audit.py 可在启动前审计:每个导入被归为implemented(已实现)、stub(桩,调用即抛错)、absent(缺失,加载失败)或module(游戏自带模块)四类,见 docs/user/USAGE.md。这构成了整个项目的"兼容性仪表盘"。
第三步:RDNA 着色器重编译——RDNA3 汇编到 SPIR-V
PS5 的 GPU 是 RDNA 架构,游戏里内嵌的是 RDNA ISA 着色器(实为 PM4 命令缓冲区中的着色器二进制)。PC 上的 Vulkan 只认 SPIR-V,所以 AnyPS5 必须自己写一个着色器重编译器。流水线在 Recompiler.cpp 中按五级串联,源码里的 include 顺序就是执行顺序:
- RdnaDecoder:解码 RDNA 指令(
RdnaInstructionDecoder::Decode); - ControlFlow:用
GraphBuilder建 CFG,再用Structurizer结构化; - Translation:RDNA 指令逐条翻译到项目自研的中间表示(IR);
- Optimization:SSA 构建、常量折叠、死代码消除、描述符绑定分配等一连串优化 pass;
- SpirvBackend:由
SpirvEmitter最终发射 SPIR-V,构建时开启ANYPS5_ENABLE_SPIRV_TOOLS还会用 SPIRV-Tools 做校验与优化。
图形链路的前端由 libSceAgcDriver 承担:游戏提交的 DCB/ACB 命令缓冲区先被解析成 PM4 包(状态、draw、dispatch,解析逻辑见 Pm4.cpp),命中的着色器经重编译后进入 Vulkan pipeline,编译产物由ShaderDiskCache缓存到磁盘,后续运行直接复用。
这条链路里最有技术含量的是执行语义映射。RDNA 的 wave 是 32/64 线程一组的执行单位,而主机 Vulkan 的 subgroup 宽窄因硬件而异(见仓库测试 Wave32WideSubgroup.cpp)。重编译器在RecompileRequest里携带目标 subgroup 大小,HostSubgroupSize()还会读取APS5_SINGLE_LANE环境变量做单车道调试。此外还有s_saveexec/s_swappc等标量指令语义、VK_KHR_fragment_shader_barycentric缺失时的回退路径(TechnicalDebt.md 中诚实记录了这些已知边界)。社区那篇"wave32 移植实录:32 宽波语义如何映射到 Vulkan 子组"讲的正是这块,仓库里 BdaShader.cpp、Structurizer.cpp 等测试专门验证映射正确性。
为什么 CPU 不需要模拟:构建期完成一切转换
模拟器最大的性能杀手是 CPU 翻译。AnyPS5 能绕开它,源于一个结构性的巧合:PS5 和 PC 都是 x86-64。游戏里的 CPU 代码本身就是 x86-64 机器码,无需翻译、无需 JIT,只要做两件事:
- 重定位:把 PS5 的内存布局(地址、重定位、TLS、动态节)改写成目标系统的 SysV 布局,让加载器能正确装载——这正是 relinker 干的事;
- 重定向系统调用与导入:游戏调用的内核 syscall 和 libSce* 函数,被重写为指向自研 PRX 实现。
这两步全部发生在构建期的一次relinker调用里。运行期呢?游戏就是一个普通原生进程,CPU 指令直接执行,只有对系统库的调用会进入自研 PRX。这意味着:没有解释器、没有二进制翻译、没有模拟进程,运行期开销趋近于零——这是社区文章"运行期零翻译开销、纯原生进程布局"说法的代码级依据。唯一例外的 CPU 层面工作是对 AMD 专属指令的降级(--to-intel),但同样是在构建期一次性完成,而且只针对 Intel 主机。
"可运行桩 + 真实核心"策略:降低移植成本的关键
从零实现几十个 PS5 系统库的每一个函数,工作量是天文数字。AnyPS5 的解法可以概括为一句工程哲学:每个函数要么做它该做的事,要么明确地失败。
机制很硬核:未实现的函数统一调用NotImplemented_nid_no_patch,抛std::runtime_error并终止进程。见 libSceAgcDriver/Unimplemented.cpp:
int APS5_VABI sceAgcDriverGetShaderDebuggingStatus() { NotImplemented_nid_no_patch(__func__); return 0; }README 明确写道:"Unsupported or unexpected states strictly throwstd::runtime_error。what()is printed to stderr and the process terminates." 这种"宁可崩,不可错"的哲学,让兼容性边界完全可定位——任何未覆盖的函数都会立刻暴露,而不是静默产生错误行为。
而在函数已实现的路径上,则是尽量完整的"真实核心"。以 libScePad/Export.cpp 为例,错误码、设备信息、触控板分辨率都按真实语义返回;Uri.cpp 把 URI 解析做成符合 RFC 3986 的完整实现;libSceAgcDriver 更是把 PM4 解析、绘制、present、纹理格式、DCC 元数据等一整套图形栈都搬进了 CMakeLists.txt 的上百个源文件里。
技术债文档 docs/dev/TechnicalDebt.md 则毫不遮掩地记录了"静默桩"清单:部分对话框只跑状态机不显示 UI、libSceHttp2 请求不出网、libSceAudio3d 不出声、libSceHmd2 直接失败让游戏跳过 VR 初始化……这些"可运行桩"不是糊弄,而是精心设计的降级路径:让游戏能走完启动序列、进到主循环,把稀缺的工程资源集中在真正决定"能不能玩"的库上。这正是"可运行桩 + 真实核心"策略的完整面貌——桩负责不阻塞运行,核心负责给出正确结果。
现状与边界:跑起来有多远
任何宣传都要回到数据。兼容性列表 docs/user/COMPATIBILITY.md 目前只有一款完成验证的游戏Dreaming Sarah(PPSA02929):Windows 平台"可玩",在 GTX 1050 Ti / i5-7500 上稳定 60 FPS,核显 Intel HD Graphics 620 上 36 FPS。这个数字本身就说明了项目定位:3D 大作还远,但 2D 平台游戏已经可以在中低端硬件上原生流畅运行,且 README 明确指出着色器重编译产物已通过 SPIRV-Tools 校验。
社区的讨论也相当理性:3DM 报道指出项目"目前尚无法完整运行游戏";关于 GPL v2 许可与商业游戏的法律边界,项目在 README 的 Disclaimer 里做了明确声明——仅面向互操作、研究、保存与兼容性目的,不包含也不分发任何受版权保护的软件或固件。技术上,项目通过 docs/dev/PROGRESS.md 的进度地图、库覆盖率和着色器指令覆盖 badge 动态呈现"还有多少路要走"。
回到标题的问题:不用模拟器能玩 PS5 游戏吗?AnyPS5 的答案是——不是"玩 PS5 游戏",而是"把 PS5 游戏变成 PC 游戏"。relinker 在构建期完成格式转换,PRX 库在运行期提供原生系统服务,RDNA 重编译器把 GPU 代码翻译成 Vulkan 生态的 SPIR-V,三者缺一不可。这条路牺牲了"打开即玩"的通用性,换来了原生进程的性能与简洁。当游戏库的覆盖率和 RDNA 指令集支持度继续爬升时,这条"非模拟器"路线会走多远,值得整个开源生态持续关注。
【免费下载链接】AnyPS5Tool for automatic PS5 executables porting to Linux and Windows项目地址: https://gitcode.com/GitHub_Trending/an/AnyPS5
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考