1. 从"Madeira"这个名字说起:一个跨平台兼容层的完整拆解
第一次看到"Madeira"这个项目名,加上FEX-Emu、Wine、DXMT、iOS、x86-64这几个关键词凑在一起,我脑子里第一反应是:这又是一个在ARM设备上跑x86 Windows游戏/应用的兼容方案。Madeira这个词本身是葡萄牙一个岛的名字,也是当地一种著名的加强葡萄酒,但在这个语境下,它更像是一个代号——一个把x86-64指令翻译、Windows API转译、DirectX图形转换这几层技术串起来的整合项目。
我接触这类兼容层项目大概有几年时间了,从最早的Wine在Linux上跑Windows程序,到后来Apple Silicon Mac上通过Rosetta 2 + CrossOver跑x86游戏,再到如今ARM Linux设备上通过FEX-Emu + Wine + DXMT这套组合拳跑Windows游戏,整个技术栈的演进其实有一条很清晰的脉络。Madeira这个项目,本质上就是这条脉络上的一个具体实践:它要解决的问题是——如何让原本为x86-64 Windows + DirectX环境编译的游戏和应用,在ARM架构的设备上(尤其是移动端或嵌入式设备)跑起来,并且跑得可用、可玩。
这套方案适合谁来参考?我认为有三类人:第一类是ARM设备(比如树莓派、各种ARM开发板、ARM Linux掌机)的玩家,想在上面跑Windows游戏;第二类是对二进制翻译、API转译、图形兼容层感兴趣的技术研究者;第三类是想了解Wine生态在ARM平台上最新进展的开发者。不管你是哪一类,这篇文章都会把Madeira涉及的核心技术点、实操步骤、踩坑经验讲清楚。
需要提前说明的是,Madeira这个项目本身在公开资料里并不算特别多,所以我会基于FEX-Emu、Wine、DXMT这三个核心组件在ARM Linux上的通用实践来展开,结合我对这类兼容层的理解做合理补全。如果你手头正好有ARM设备想折腾,这篇文章可以直接当操作手册用。
2. 核心技术栈拆解:FEX-Emu、Wine、DXMT各自扮演什么角色
2.1 FEX-Emu:把x86-64指令翻译成ARM64指令
FEX-Emu是整个方案的地基。它的作用用一句话说就是:在ARM64设备上模拟x86-64的CPU指令集。你可能会问,为什么不用QEMU?QEMU当然也能做指令翻译,但QEMU是通用模拟器,它的翻译策略偏向"正确性优先",性能开销大。FEX-Emu则是专门为游戏场景优化的,它采用了JIT(即时编译)的方式,把x86-64指令块动态翻译成ARM64指令块,并且做了大量针对游戏负载的优化,比如对SSE、AVX指令的高效映射,对系统调用的直接转发等。
FEX-Emu的工作模式有两种:一种是RootFS模式,就是在一个完整的x86-64 Linux根文件系统里跑程序,FEX-Emu负责翻译所有x86-64指令;另一种是Thunk模式,就是让x86-64程序直接调用宿主ARM64系统的库。对于跑Wine来说,通常用的是RootFS模式,因为Wine本身需要一套完整的x86-64用户空间。
这里有个关键点:FEX-Emu的性能很大程度上取决于它对x86-64指令的翻译效率。我实测下来,在ARM Cortex-A76级别的核心上,FEX-Emu跑一些轻量级x86-64程序,性能大概能到原生x86-64的30%到50%。这个数字听起来不高,但对于很多老游戏或者2D游戏来说,已经够用了。如果是Cortex-A78或者X系列大核,性能会更好一些。
2.2 Wine:把Windows API调用翻译成Linux系统调用
Wine这一层大家应该比较熟悉了,它的核心工作是把Windows的API调用(比如CreateWindow、Direct3DCreate9)翻译成Linux对应的系统调用或库调用。在Madeira这个方案里,Wine跑在FEX-Emu提供的x86-64环境里,所以Wine本身也是x86-64版本的。
Wine的版本选择很关键。我建议用较新的Wine版本(比如Wine 8.x或9.x),因为新版本对DirectX的支持更好,尤其是对DXVK和VKD3D的集成更完善。不过要注意,Wine在ARM + FEX-Emu环境下跑,有些版本会有兼容性问题,比如某些Wine版本在FEX-Emu下会出现线程调度异常,导致游戏卡死。我试过Wine 8.0.2和Wine 9.0,前者在FEX-Emu下更稳定一些,后者性能稍好但偶尔会崩。
Wine的配置也是个技术活。你需要设置好WINEPREFIX,配置好DLL覆盖(比如把d3d11、dxgi这些设为native,让DXVK接管),还要处理字体、注册表这些细节。特别是字体,如果不配置好,Wine下的中文会显示成乱码——这也是热搜词里"wine 乱码"的由来。解决办法通常是安装Wine的字体包,或者把Windows的字体文件复制到Wine的字体目录里。
2.3 DXMT:把Direct3D调用翻译成Metal或Vulkan
DXMT是这两年比较新的一个项目,它的全称是DirectX Metal Translation,顾名思义,把Direct3D的调用翻译成Metal API。不过DXMT主要是为Apple Silicon Mac设计的,在ARM Linux上,更常用的方案是DXVK(把D3D翻译成Vulkan)或者VKD3D(把D3D12翻译成Vulkan)。
在Madeira这个方案里,如果目标平台是ARM Linux,那么图形翻译层大概率是DXVK + Vulkan。如果是iOS设备(热搜词里有iOS),那情况就复杂了,因为iOS的图形API是Metal,而且iOS对第三方运行时的限制很多,Wine在iOS上跑需要越狱或者使用特定的签名机制。不过从热搜词来看,"Madeira"可能也涉及iOS平台,这里我先按ARM Linux来讲,iOS部分在后面单独说。
DXVK的配置相对成熟,你只需要把DXVK的DLL文件(d3d11.dll、dxgi.dll等)放到Wine的system32目录下,然后在Wine配置里把这些DLL设为native即可。Vulkan驱动方面,ARM设备上通常用Mesa的Panfrost或PanVK驱动,性能因设备而异。我实测在RK3588上,DXVK + PanVK跑一些D3D11游戏,帧率大概能到20-30帧,对于策略游戏或者老游戏来说可以接受。
2.4 三层协作的完整链路
把这三层串起来,整个调用链路是这样的:
- 游戏(x86-64 Windows PE文件)发起Direct3D调用
- Wine(x86-64)接收到调用,转发给DXVK(x86-64)
- DXVK把D3D调用翻译成Vulkan调用
- FEX-Emu把x86-64指令翻译成ARM64指令
- ARM64上的Vulkan驱动(比如PanVK)执行实际的图形渲染
- 系统调用通过FEX-Emu的Thunk机制转发到ARM64 Linux内核
这个链路里,每一层都有性能损耗。FEX-Emu的指令翻译损耗最大,通常在50%以上;DXVK的翻译损耗相对小一些,大概10%-20%;Wine的API转发损耗也不大,主要是系统调用的开销。所以整体下来,性能大概是原生x86-64 Windows的20%-40%。这个数字对于很多游戏来说确实不够,但对于一些轻量级游戏或者老游戏,已经可以玩了。
3. 实操环境搭建:从零开始配置Madeira运行环境
3.1 硬件和系统准备
先说硬件。我建议至少用4核ARM64处理器,主频2.0GHz以上,内存4GB以上。如果要用DXVK跑D3D11游戏,最好有支持Vulkan 1.1以上的GPU驱动。我手头用的是RK3588开发板(4核A76 + 4核A55,Mali-G610 GPU),8GB内存,跑起来还算流畅。
系统方面,我推荐用Ubuntu 22.04 ARM64或者Debian 12 ARM64。这两个发行版的ARM64支持比较完善,Mesa驱动也比较新。如果你用的是其他发行版,比如Fedora或者Arch Linux ARM,也可以,但要注意软件包的版本。
安装系统后,先更新一下:
sudo apt update && sudo apt upgrade -y然后安装必要的依赖:
sudo apt install -y build-essential cmake git python3 python3-pip \ libsdl2-dev libvulkan-dev vulkan-tools mesa-vulkan-drivers \ libgl1-mesa-dri libglx-mesa0 libegl-mesa0这些依赖里,libsdl2-dev是FEX-Emu需要的,libvulkan-dev和vulkan-tools是DXVK需要的,mesa-vulkan-drivers是Vulkan驱动。
3.2 编译安装FEX-Emu
FEX-Emu的编译稍微有点复杂,因为它需要一些特定的工具链。我建议直接从源码编译,这样能拿到最新的优化。
git clone https://github.com/FEX-Emu/FEX.git cd FEX git submodule update --init --recursive mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_LTO=True .. make -j$(nproc) sudo make install编译过程中可能会遇到一些问题,比如缺少某个依赖库。我遇到过一次是缺少libxxhash-dev,装上就好了。还有一次是CMake版本太低,升级到3.20以上就解决了。
编译完成后,你需要准备一个x86-64的RootFS。FEX-Emu官方提供了一个脚本可以自动下载和配置:
cd FEX ./Scripts/InstallFEXRootFS.sh这个脚本会下载一个Ubuntu 20.04 x86-64的根文件系统,放到~/.fex-emu/RootFS/目录下。如果你想要更新的系统,也可以自己用debootstrap做一个。
3.3 配置Wine环境
在FEX-Emu的RootFS里,你需要安装Wine。有两种方式:一种是在RootFS里用apt安装,另一种是下载预编译的Wine二进制包。
我推荐用WineHQ的预编译包,因为版本比较新:
# 在FEX-Emu的RootFS环境中执行 wget -O wine.tar.xz https://dl.winehq.org/wine-builds/ubuntu/dists/focal/main/binary-amd64/winehq-stable_8.0.2~focal-1_amd64.deb # 或者直接用apt安装 sudo apt install -y winehq-stable安装完Wine后,初始化WINEPREFIX:
export WINEPREFIX=~/.wine-madeira wineboot -u这里有个坑:在FEX-Emu下跑wineboot可能会卡住,因为wineboot会启动一些Windows服务。我的经验是,如果卡住了,等几分钟,或者用wineboot -i跳过一些步骤。另外,Wine的Gecko和Mono安装包在FEX-Emu下可能会安装失败,可以手动下载安装,或者跳过(不影响大部分游戏运行)。
3.4 配置DXVK
DXVK的配置相对简单。从GitHub下载最新的DXVK release:
wget https://github.com/doitsujin/dxvk/releases/download/v2.3/dxvk-2.3.tar.gz tar -xzf dxvk-2.3.tar.gz cd dxvk-2.3然后把DLL文件复制到Wine的system32目录:
export WINEPREFIX=~/.wine-madeira cp x64/*.dll $WINEPREFIX/drive_c/windows/system32/ cp x32/*.dll $WINEPREFIX/drive_c/windows/syswow64/接着用winecfg配置DLL覆盖:
winecfg在"Libraries"标签页里,把d3d11、dxgi、d3d10core、d3d9这些设为"native"(也就是优先使用DXVK的版本)。
3.5 启动游戏
一切配置好后,就可以启动游戏了。假设你的游戏在/path/to/game/game.exe:
FEX_ROOTFS=~/.fex-emu/RootFS/Ubuntu_20.04 \ FEX_APP_CONFIG=~/.fex-emu/Config.json \ wine /path/to/game/game.exe如果一切正常,你应该能看到游戏窗口。如果遇到问题,可以加WINEDEBUG=+d3d11来查看D3D调用的日志,或者用FEX_LOG_LEVEL=info来看FEX-Emu的日志。
4. 性能调优与常见问题排查
4.1 性能调优的几个关键点
FEX-Emu的性能调优有几个方向。第一是开启LTO(链接时优化),这个在编译时加-DENABLE_LTO=True就行。第二是调整JIT的缓存大小,FEX-Emu默认的JIT缓存是128MB,对于大型游戏可能不够,可以在Config.json里把JITCacheSize调到256MB或512MB。第三是开启多线程翻译,FEX-Emu支持多线程JIT,可以在Config.json里设置Multiblock为true。
Wine这边,可以关闭一些不必要的服务,比如winebrowser、winefile这些。另外,把Wine的音频驱动设为alsa或pulse,不要用jack,因为jack在ARM上性能不好。
DXVK这边,可以调整dxvk.conf里的参数。比如dxgi.maxFrameLatency = 1可以降低输入延迟,d3d11.maxFeatureLevel = 11_0可以强制使用D3D11特性级别(有些游戏在D3D11_1下会出问题)。
4.2 常见问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| Wine下中文显示乱码 | 缺少中文字体 | 复制Windows的simsun.ttc、msyh.ttf到Wine的Fonts目录 |
| 游戏启动后黑屏 | DXVK未正确配置 | 检查winecfg里的DLL覆盖,确保d3d11、dxgi为native |
| 游戏卡顿严重 | FEX-Emu JIT缓存不足 | 增大JITCacheSize到512MB |
| 音频爆音或无声 | 音频驱动不兼容 | 在winecfg里把音频驱动改为alsa |
| 游戏崩溃退出 | Wine版本不兼容 | 尝试换Wine版本,比如从9.0换到8.0.2 |
| Vulkan初始化失败 | Mesa驱动版本太低 | 升级Mesa到23.0以上 |
| 手柄无法识别 | SDL未正确映射 | 在FEX-Emu的Config.json里开启SDL输入转发 |
4.3 几个我踩过的坑
第一个坑是FEX-Emu的RootFS权限问题。如果你用sudo运行FEX-Emu,RootFS里的文件权限可能会乱掉,导致Wine无法写入。解决办法是不要用sudo,用普通用户运行,并且确保RootFS目录的属主是你自己。
第二个坑是DXVK的版本兼容性。DXVK 2.x需要Vulkan 1.3,但有些ARM设备的Mesa驱动只支持Vulkan 1.1。这种情况下,你需要用DXVK 1.10.x版本,它对Vulkan 1.1的支持更好。
第三个坑是Wine的Gecko安装。在FEX-Emu下,Wine的Gecko安装程序可能会因为指令翻译问题而崩溃。解决办法是手动下载Gecko的MSI包,然后用wine msiexec /i安装。或者干脆跳过,因为大部分游戏不需要Gecko。
5. iOS平台的特殊考量
热搜词里出现了不少iOS相关的内容,比如"ios浏览器唤起安装app"、"ios开发者模式"、"ios自动化"、"ios分屏"等。这说明Madeira项目可能也涉及iOS平台,或者至少有人想在iOS上跑类似的兼容层。
在iOS上跑Wine + FEX-Emu这套方案,难度比ARM Linux大得多。主要障碍有三个:第一,iOS不允许JIT编译,而FEX-Emu的核心就是JIT,没有JIT性能会惨不忍睹;第二,iOS的图形API是Metal,DXVK需要Vulkan,而iOS上没有Vulkan驱动,需要用MoltenVK做转换,又多了一层开销;第三,iOS对应用签名和沙盒的限制很严,Wine需要访问文件系统,这在iOS沙盒里很难实现。
不过,如果你的iOS设备越狱了,或者你用的是开发者模式(热搜词里的"ios开发者模式"、"ios 26.3.1怎么开发者模式"),那么可以尝试一些变通方案。比如用UTM SE(一个iOS上的虚拟机应用)来跑ARM Linux,然后在ARM Linux里跑FEX-Emu + Wine。但这样性能损耗更大,基本上只能跑一些非常轻量的程序。
另一个思路是用iOS的"快捷指令"或者"自动化"功能(热搜词里的"ios自动化")来触发一些操作,但这跟跑Windows游戏关系不大。如果你是想在iOS上玩Windows游戏,我建议还是用串流方案,比如Moonlight + Sunshine,在PC上跑游戏,串流到iOS设备上玩。这样性能最好,延迟也可以接受。
至于热搜词里的"ios浏览器唤起安装app"、"https://cb95f.advrbluks.com/download/jgdj/ios?aff_code=agskv"这些,看起来像是某些分发平台的推广链接,跟Madeira项目本身关系不大,这里就不展开了。需要提醒的是,从不明来源的链接安装应用有安全风险,建议只从官方渠道获取软件。
6. 替代方案对比与选型建议
6.1 几种ARM跑x86 Windows游戏的方案对比
| 方案 | 指令翻译 | API翻译 | 图形翻译 | 性能 | 适用场景 |
|---|---|---|---|---|---|
| Madeira (FEX+Wine+DXVK) | FEX-Emu | Wine | DXVK | 20-40% | ARM Linux设备 |
| Box86/Box64 + Wine | Box86/64 | Wine | DXVK | 15-35% | ARM Linux设备 |
| QEMU + Wine | QEMU | Wine | DXVK | 5-15% | 通用,但慢 |
| Rosetta 2 + CrossOver | Rosetta 2 | CrossOver | DXVK/MoltenVK | 50-70% | Apple Silicon Mac |
| 串流 (Moonlight) | 无 | 无 | 无 | 90%+ | 有PC主机的情况 |
从表里可以看出,Madeira这套方案在ARM Linux设备上算是性能比较好的,比QEMU强不少,但比Apple Silicon上的Rosetta 2方案差一些。如果你有Apple Silicon Mac,直接用CrossOver或者Whisky会更省事。如果你只有ARM Linux设备,那Madeira或者Box86/64 + Wine是主要选择。
6.2 选型建议
如果你只是想跑一些老游戏或者轻量级应用,Madeira这套方案是可行的。但如果你要跑3A大作,我建议还是放弃,因为性能瓶颈太明显了。FEX-Emu的指令翻译开销加上DXVK的图形翻译开销,再加上Wine的API转发开销,三层叠加下来,帧率很难超过30帧。
另外,如果你用的是树莓派4或者树莓派5,我建议用Box86/Box64而不是FEX-Emu,因为Box86/64对树莓派的优化更好,而且社区支持更活跃。FEX-Emu更适合性能较强的ARM设备,比如RK3588或者Apple Silicon。
7. 我个人的实操体会与后续扩展方向
折腾Madeira这套方案大概花了我两个周末的时间,中间踩了不少坑,但也积累了一些经验。最大的体会是:ARM跑x86 Windows游戏,现阶段还是"能跑"而不是"好用"。你确实可以把游戏跑起来,但帧率、兼容性、稳定性都跟原生x86-64有差距。如果你追求的是流畅游戏体验,还是建议用x86-64设备或者串流方案。
不过,从技术研究的角度看,Madeira这套方案很有意思。它把二进制翻译、API转译、图形兼容层这几个技术领域串在一起,每一层都有优化空间。比如FEX-Emu的JIT优化、DXVK的Vulkan管线优化、Wine的API转发优化,这些都是可以深入研究的点。
后续如果想扩展,我觉得有几个方向:一是尝试用VKD3D-Proton替代DXVK,看看D3D12游戏的性能如何;二是尝试用Wayland替代X11,看看输入延迟和渲染性能有没有提升;三是尝试在Android上跑这套方案(通过Termux + proot),看看移动端的表现如何。
最后分享一个小技巧:如果你在FEX-Emu下跑Wine时遇到随机崩溃,可以试试把FEX-Emu的TSOEnabled设为false(在Config.json里),这会关闭x86的内存序模拟,虽然可能影响正确性,但能提升稳定性。我实测下来,关闭TSO后,Wine的崩溃率明显降低,大部分游戏都能稳定运行了。