业余操作系统 Astral 移植 Wine:多款游戏运行测试,Steam 成下一步目标!

业余操作系统 Astral 移植 Wine:多款游戏运行测试,Steam 成下一步目标!

将 Wine 移植到 Astral

几个月前,有人发布了一篇关于 Astral 的文章,Astral 是其多年来一直在开发的一个业余操作系统,当时它已经能够运行 Minecraft。从那以后,其他人也让现代版本的 Minecraft 以及《异星工厂》(Factorio,使用兼容 glibc 的 libc)在上面成功运行。不过,很多游戏是闭源的,并且是为 Windows 编译的,这使得 Wine 这样的工具成为运行它们的必要条件。

其最喜欢的游戏之一《机械心智》(Cogmind)就属于这种情况。它是一款仅支持 32 位 Windows 的 Roguelike 游戏,目标就是让它在 Astral 上运行。虽然已经有一个现有的 Wine 移植版本,但它极其不完善,甚至连 `notepad.exe` 都无法正常工作。为了运行《机械心智》,必须完成 Wine 的移植,这也意味着要在原本仅支持 64 位的操作系统上添加运行 32 位代码的能力。

Wine 基本功能实现

让 Wine 启动并运行的第一步是下载 MinGW 并在 Wine 构建中启用它,因为编译 PE DLL 需要用到它。启用后,`notepad.exe` 可以正常工作,选择“另存为”也不会再导致崩溃。

编译 libEGL.so

还有一个大问题:Wine 编译时没有 OpenGL 支持。虽然 Astral 本身支持 OpenGL,但 Wine 明确需要 EGL 才能正常工作,而 Astral 的 Mesa 移植版本并未提供 EGL。EGL 可以将 OpenGL 等渲染 API 与窗口系统连接起来,Wine 需要它来正确初始化图形。起初,这似乎是个简单的修复,只需在 Mesa 中启用它即可。然而,Mesa 在 xlib 后端不支持 EGL,这迫使切换到 DRI 后端。

DRI(直接渲染基础设施)允许应用程序直接与 GPU 通信,而无需通过 X 服务器。这让人陷入了一个麻烦的问题,不得不对 Mesa 打补丁,以便让 X.org 服务器在没有 `/dev/dri` 的情况下启动。最终,成功了,还让一款真正的游戏《三角符文》(Deltarune)启动了。

WoW64 与 32 位 Windows 程序

由于《机械心智》是 32 位的,而 Astral 是 64 位的,因此需要更多的基础设施支持。这通过 Wine 的 WoW64 模式实现,该模式不需要任何 32 位 Unix 库。它通过在 64 位进程中运行 32 位 Windows 二进制文件,根据需要在 32 位和 64 位系统调用及数据结构之间进行转换,从而避免了完整 32 位用户空间的需求。

要让它正常工作,主要是在内核中实现 LDT(局部描述符表)支持,因为 x86 - 64 允许使用 32 位段描述符在长模式下运行 32 位代码。这些描述符规定了如何访问内存,对于代码段,还规定了处理器如何执行这些指令。LDT 是用于定义这些段描述符的机制之一,允许为每个进程配置它们。此外,还需要在 Wine 的信号和系统调用处理代码中添加一些精细的胶水代码。

《机械心智》成功运行!

在 Astral 移植版中实现了 WoW64 支持并修复了内核中的一些其他 bug 后,《机械心智》可以正常运行了!这款游戏可以正常游玩,除了游戏新闻和成绩表上传功能无法正常工作外,没有其他明显问题。

成绩表上传问题

这个 bug 表现为与《机械心智》服务器的 TCP 连接打开后立即关闭,没有传输任何数据。起初,以为这是网络栈的问题,但事实并非如此。

让怀疑是其他问题的原因是,Wine 调试日志函数 `__wine_dbg_write` 在 WoW64 模式下根本无法工作。深入研究 Wine 代码后,最终发现自己在 `__wine_unix_call_dispatcher` 函数中忘记保存一个寄存器。这破坏了 PE 到 Unix 的转换,导致了未定义行为。修复这个问题后,成绩表上传功能恢复正常。

更多游戏和程序测试

还尝试在 Wine 下运行其他一些应用程序:《FTL:超越光速》(FTL)正常,可完全正常游玩;Steam 部分正常,可以安装和更新,在启动 Chromium 时崩溃,原因是 `GetInterfaceAddresses()` 函数出错;iexplore.exe 部分正常,简单网站可以渲染,复杂页面崩溃,原因与 Steam 相同;《异星工厂》(Factorio)部分正常,窗口可以打开,但无法完成加载;《幽灵的惊吓豪宅》(Spooky's Jumpscare Mansion)部分正常,可以启动,但运行速度太慢,无法正常游玩;《诺伊塔》(Noita)部分正常,可以启动,但运行速度太慢,无法正常游玩;《植物大战僵尸》(Plants vs. Zombies)无法运行,在进入主菜单前被 Steam DRM 阻止;《半条命》(Half - Life)无法运行,Wine 的 C++ 运行时出现断言失败,可能是移植版本中缺少某些实现;Firefox / Chromium 无法运行,安装程序失败,无法进入可运行状态;《SCP:收容失效》(SCP: Containment Breach)无法运行,无法启动,原因尚未查明;一般 Unity 游戏无法运行,Astral 上的 wine - mono 似乎存在问题,Unity 游戏会卡在 `MonoManager ReloadAssembly` 处。

总结与展望

移植 Wine 是一次有趣的挑战,也证明了业余操作系统可以运行比最初想象更多的游戏,这是业余操作系统迈向成为可行日常使用系统的一步。虽然仍存在一些小问题、性能问题和奇怪的崩溃,但核心功能已经可以正常工作。这也让人对 Wine 的内部工作原理有了更深入的了解,尤其是在修复 PE 到 Unix 转换问题时。

目前与 Wine 移植相关的一个重要目标是让 Steam 正常工作,这也意味着 Chromium 能够正常运行。至于 Astral,计划在近期更多地关注优化、新驱动程序开发和 bug 修复。内核方面还有很大的改进空间。