
1. 从“Madeira”这个名字说起它到底想解决什么问题第一次看到“Madeira”这个项目标题加上FEX-Emu、Wine、DXMT、iOS、x86-64这一串关键词我脑子里第一反应是这又是一个在“跨架构运行Windows应用”这条路上折腾的方案。Madeira大概率是一个把x86-64 Windows程序搬到ARM设备尤其是iOS/iPadOS这类封闭环境上跑起来的整合项目。它不是一个单一工具而是把几块拼图拼在一起FEX-Emu负责指令翻译Wine负责Windows API转译DXMT负责把DirectX调用翻译成Metal最终目标是在iOS设备上跑起原本为x86-64 Windows编译的游戏或应用。为什么我会这么判断因为这几个关键词的组合太有指向性了。FEX-Emu是目前ARM平台上比较活跃的x86-64用户态模拟器Wine是Windows兼容层的老牌选手DXMT是把D3D翻译到Metal的新兴项目而iOS则是那个“什么都想跑但什么都不让你跑”的封闭平台。把这四样东西凑在一起目标就很明确了在iOS设备上通过一层层的翻译和模拟让x86-64 Windows程序跑起来。这个方向的价值在于iOS设备尤其是iPad Pro、iPhone 15 Pro之后的机型的硬件性能已经强到离谱M系列和A系列芯片的GPU性能足以应付不少PC游戏但系统封闭性让这些性能很难被充分利用。Madeira这类项目就是在尝试打破这层壁垒。它适合谁来关注一是喜欢在移动设备上折腾模拟器的玩家二是对跨架构翻译技术感兴趣的技术人员三是想了解Wine、FEX-Emu、DXMT这些工具如何协同工作的开发者。我接下来会从整体设计思路、核心组件拆解、实操流程、常见问题几个角度把这个项目拆开来讲清楚。需要说明的是部分细节是基于这类项目的常见实践做的合理推断因为原始信息里没有给出完整的配置和代码。2. 整体架构与设计思路拆解2.1 为什么是“多层翻译”而不是“单层模拟”在ARM设备上跑x86-64 Windows程序最直接的想法是做一个完整的x86-64模拟器把CPU指令、系统调用、图形API全部模拟一遍。但这样做性能损耗太大尤其是图形部分纯软件模拟DirectX到Metal的转换效率极低。Madeira的思路是分层处理CPU指令层用FEX-Emu做动态二进制翻译系统API层用Wine做转译图形层用DXMT做DirectX到Metal的映射。每一层只负责自己最擅长的事整体效率比单层全模拟高得多。这个设计思路的核心逻辑是“能转译就不模拟能映射就不转译”。FEX-Emu虽然是模拟器但它做的是用户态的动态二进制翻译把x86-64指令翻译成ARM64指令而不是逐条解释执行性能损耗在可接受范围内。Wine把Windows的PE文件加载、注册表、DLL调用等转译成POSIX调用这部分是API级别的兼容不是硬件模拟。DXMT则把D3D11/D3D12的调用翻译成Metal的调用直接利用iOS设备的GPU。三层各司其职整体开销比纯模拟小一个数量级。2.2 FEX-Emu在其中的角色与配置要点FEX-Emu是这个方案里最底层的一环负责把x86-64的机器码翻译成ARM64的机器码。它的工作方式是在程序运行时动态翻译基本块翻译结果会缓存起来下次执行到同一块代码时直接复用。这种JIT式的翻译对游戏这种热点集中的负载比较友好因为游戏的主循环和渲染循环会被反复执行翻译一次就能一直用。在Madeira的语境下FEX-Emu需要配置成支持64位x86-64程序并且要开启多线程翻译和块缓存。常见的配置项包括FEX_APP_CONFIG里的TSOEnabled开启x86内存序模拟对多线程程序很重要、Multiblock开启多块翻译提升翻译效率、SMCChecks自修改代码检查部分游戏会动态生成代码。这些配置在FEX-Emu的官方文档里有说明但实际调优需要根据具体游戏来试。注意FEX-Emu的TSO模拟会带来额外开销如果目标程序是单线程或者对内存序不敏感可以关掉TSO来提升性能。但很多Windows游戏是多线程的关掉TSO可能导致崩溃或数据竞争。2.3 Wine层的适配与DXMT的图形翻译Wine在Madeira里承担的是Windows API转译的工作。它需要把Windows的PE可执行文件加载起来把kernel32、user32、gdi32这些DLL的调用转译成POSIX调用。在ARM64 Linux环境下Wine本身可以原生运行但要让x86-64的Windows程序跑起来Wine需要和FEX-Emu配合FEX-Emu负责翻译x86-64指令Wine负责提供Windows API的实现。DXMT是图形部分的关键。它把D3D11和D3D12的调用翻译成Metal的调用直接利用iOS设备的GPU。DXMT的实现方式是在Wine的D3D模块里做替换把原本走OpenGL或Vulkan的路径改成走Metal。这样做的好处是Metal在iOS上是原生API性能损耗比OpenGL转译小得多。DXMT目前对D3D11的支持比较成熟D3D12的支持还在完善中所以Madeira跑D3D11游戏的成功率会比D3D12高。2.4 iOS环境的特殊限制与应对iOS和普通的ARM64 Linux环境不一样它的沙盒限制、代码签名、内存管理策略都会影响这类项目的运行。比如iOS不允许JIT编译而FEX-Emu和Wine都依赖JIT。这就需要在越狱环境下运行或者利用iOS的开发者模式配合特定的签名方式。另外iOS的GPU驱动是封闭的Metal的调用需要通过系统框架DXMT需要处理好和Metal驱动层的交互。还有一个问题是内存。iOS设备的内存虽然大但单个应用的内存上限是有限制的。Wine和FEX-Emu加上游戏本身内存占用很容易超过限制。常见的做法是开启内存压缩、调整Wine的堆大小、关闭不必要的后台进程。这些在越狱环境下可以通过调整系统参数来缓解但在非越狱环境下基本无解。3. 核心组件深度解析与实操要点3.1 FEX-Emu的编译与配置细节FEX-Emu的编译在ARM64 Linux上比较直接但在iOS环境下需要交叉编译或者用越狱环境里的工具链。编译时需要开启ENABLE_JIT因为FEX-Emu的核心就是JIT翻译。如果目标环境不支持JITFEX-Emu会退化成解释器模式性能会差很多。配置方面FEX-Emu的配置文件通常放在~/.fex-emu/Config.json。关键配置项包括RootFS指定一个x86-64的根文件系统路径Wine和Windows程序需要的库文件放在这里。ThunkHostLibs指定宿主库的路径用于把x86-64的库调用转发到ARM64的宿主库。TSOEnabled是否开启x86内存序模拟默认开启对多线程程序必要。Multiblock是否开启多块翻译默认开启提升翻译效率。SMCChecks自修改代码检查策略可选none、mtrack、full游戏一般用mtrack。实操心得FEX-Emu的块缓存默认放在~/.fex-emu/Cache如果磁盘空间紧张可以定期清理。但清理后第一次运行会重新翻译启动会变慢。建议保留缓存除非遇到缓存损坏导致的崩溃。3.2 Wine的ARM64编译与Windows程序加载Wine在ARM64上的编译需要先配置好FEX-Emu的环境因为Wine的PE加载器需要调用FEX-Emu来执行x86-64代码。编译Wine时需要开启--enable-archsi386,x86_64这样Wine才能加载32位和64位的Windows程序。如果只跑64位程序可以只开x86_64。Wine的配置里WINEPREFIX是每个Windows程序独立的目录里面包含注册表、DLL、驱动等。在Madeira里建议为每个游戏单独建一个WINEPREFIX避免DLL冲突。创建WINEPREFIX的命令是WINEPREFIX~/.wine-madeira winecfg这会启动Wine的配置工具可以设置Windows版本、显卡、音频等。DXMT的集成需要在Wine的D3D模块里做替换。具体做法是把DXMT编译出的d3d11.dll和dxgi.dll放到WINEPREFIX的system32目录下覆盖Wine自带的版本。DXMT的配置通过环境变量控制比如DXMT_ENABLE_D3D121开启D3D12支持DXMT_METAL_DEVICE0指定使用的Metal设备。3.3 DXMT的Metal翻译机制与性能调优DXMT的核心是把D3D11的调用翻译成Metal的调用。它的实现方式是在Wine的D3D11模块里做拦截把ID3D11Device、ID3D11DeviceContext这些接口的调用转成Metal的MTLDevice、MTLCommandQueue等。翻译过程中需要处理资源绑定、着色器编译、状态管理等细节。着色器编译是DXMT的一个难点。D3D11的着色器是DXBC格式Metal的着色器是MSL格式DXMT需要把DXBC反编译成中间表示再生成MSL最后用Metal的运行时编译成GPU机器码。这个过程有开销但可以缓存编译结果。DXMT会把编译好的Metal库缓存到磁盘下次加载同一着色器时直接读缓存。性能调优方面DXMT有几个关键参数参数作用建议值DXMT_MAX_FRAME_LATENCY最大帧延迟2-3太低会卡顿太高会增加输入延迟DXMT_SHADER_CACHE着色器缓存路径放在高速存储上避免每次重新编译DXMT_METAL_DEVICE使用的Metal设备默认0多GPU时指定DXMT_ENABLE_D3D12是否开启D3D120或1D3D12支持还不完善建议先关注意DXMT的着色器缓存如果损坏会导致游戏启动崩溃。遇到这种情况删除缓存目录重新编译即可。缓存目录一般在WINEPREFIX/drive_c/users/用户名/Temp/DXMT下。3.4 iOS环境下的部署与签名问题在iOS上部署Madeira这类项目最大的障碍是代码签名和JIT限制。iOS不允许应用在运行时生成可执行代码而FEX-Emu和Wine都依赖JIT。解决办法通常有两种一是越狱越狱后可以关闭JIT限制二是利用iOS的开发者模式配合特定的签名工具但这种方式限制较多不一定能稳定运行。越狱环境下需要安装AppSync之类的补丁来允许未签名应用运行还需要JIT Enabler之类的工具来开启JIT权限。然后通过scp或Filza把编译好的FEX-Emu、Wine、DXMT和游戏文件传到设备上设置好环境变量用bash脚本启动。非越狱环境下可以尝试用AltStore或Sideloadly签名安装但JIT权限需要额外的工具来开启比如Jitterbug。这种方式稳定性差系统更新后可能失效适合折腾但不适合日常使用。4. 完整实操流程从零跑起一个Windows游戏4.1 环境准备与依赖安装假设你有一台越狱的iPad ProM1或M2芯片系统版本在iOS 15到iOS 16之间越狱支持较好的版本。首先需要安装Procursus或Sileo作为包管理器然后安装以下依赖fex-emu可以从Procursus源安装或者自己编译。wine需要ARM64版本可以从Procursus源安装或者用wine-crossover的ARM64构建。dxmt需要自己编译或者从社区获取预编译的d3d11.dll和dxgi.dll。bash、coreutils、wget、unzip基础工具。安装完成后验证FEX-Emu是否能运行FEXInterpreter /usr/bin/true如果没有报错说明FEX-Emu工作正常。然后验证Winewine --version应该输出Wine的版本号。4.2 创建Wine前缀与DXMT集成创建一个新的WINEPREFIXexport WINEPREFIX~/.wine-madeira export WINEARCHwin64 winecfgwinecfg会弹出配置窗口设置Windows版本为Windows 10显卡为默认音频为默认。然后关闭窗口WINEPREFIX就创建好了。接下来集成DXMT。把DXMT编译出的d3d11.dll和dxgi.dll复制到WINEPREFIX/drive_c/windows/system32/覆盖Wine自带的版本。然后设置环境变量export DXMT_ENABLE_D3D120 export DXMT_MAX_FRAME_LATENCY2 export DXMT_SHADER_CACHE~/.wine-madeira/dxmt-cache4.3 安装与运行Windows游戏把Windows游戏的安装包比如setup.exe放到WINEPREFIX/drive_c/下然后用Wine运行wine ~/.wine-madeira/drive_c/setup.exe安装过程可能会遇到乱码问题这是因为Wine的字体配置不对。解决办法是把Windows的字体比如simsun.ttc、msyh.ttf复制到WINEPREFIX/drive_c/windows/Fonts/然后在winecfg里设置字体替换。安装完成后找到游戏的exe文件用Wine运行wine ~/.wine-madeira/drive_c/Program\ Files/Game/game.exe如果游戏依赖D3D11DXMT会自动接管图形调用。如果游戏启动崩溃可以查看Wine的日志WINEDEBUGd3d11 wine game.exe看看是哪个环节出了问题。4.4 性能调优与参数调整游戏跑起来后如果帧率不理想可以调整以下参数FEX-Emu的TSOEnabled如果游戏是单线程的关掉TSO可以提升性能。但很多游戏是多线程的关掉会崩溃。FEX-Emu的Multiblock确保开启否则翻译效率会下降。DXMT的DXMT_MAX_FRAME_LATENCY降低到1可以减少输入延迟但可能增加卡顿。Wine的WINEDEBUG关掉所有调试输出WINEDEBUG-all减少日志开销。另外iOS设备的热管理很重要。长时间跑游戏会导致降频建议加散热背夹或者在空调房里玩。电池模式下性能会受限插电玩会好一些。5. 常见问题与排查技巧实录5.1 Wine乱码问题的根源与解决Wine乱码是最常见的问题表现是菜单、对话框里的中文显示成方块或乱码。根源是Wine默认的字体配置里没有中文字体或者字体替换规则不对。解决办法分两步第一步是把中文字体文件复制到WINEPREFIX/drive_c/windows/Fonts/第二步是在注册表里设置字体替换。注册表设置可以用wine regedit打开注册表编辑器找到HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes添加以下键值MS Shell DlgSimSunMS Shell Dlg 2SimSunTahomaSimSun然后重启Wine程序乱码应该就解决了。如果还有个别地方乱码可能是那个程序用了特殊的字体需要单独替换。5.2 FEX-Emu崩溃与块缓存问题FEX-Emu在翻译过程中可能会崩溃尤其是遇到自修改代码或者不常见的指令时。常见的崩溃原因和解决办法问题现象可能原因解决办法启动时崩溃块缓存损坏删除~/.fex-emu/Cache重新翻译运行中崩溃自修改代码检查失败调整SMCChecks为full多线程崩溃TSO模拟不完整确保TSOEnabled1性能突然下降块缓存满了清理缓存或增大缓存上限实操心得FEX-Emu的日志可以通过FEX_LOG_LEVELdebug开启日志会输出到stderr。如果崩溃先看日志里最后翻译的指令地址再对照游戏的代码段能大致定位问题。5.3 DXMT图形问题与Metal调试DXMT的图形问题表现多样黑屏、花屏、纹理丢失、帧率骤降。排查思路是先确认是D3D层的问题还是Metal层的问题。可以用DXMT_LOG_LEVELdebug开启DXMT的日志看看D3D调用是否正常翻译成了Metal调用。如果D3D调用正常但画面不对可能是Metal着色器编译出了问题可以检查着色器缓存目录里是否有编译失败的日志。黑屏问题常见于D3D12游戏因为DXMT的D3D12支持还不完善。解决办法是强制游戏用D3D11模式运行很多游戏支持-dx11命令行参数。如果游戏不支持可以尝试用d3d12.dll的替代方案但成功率不高。5.4 iOS环境特有的坑与应对iOS环境下有几个特有的坑一是JIT权限越狱后需要确认JIT是否真的开启了可以用FEXInterpreter跑一个简单的x86-64程序来验证二是内存限制iOS对单个应用的内存限制比较严格Wine加游戏很容易超限可以通过launchctl limit调整内存上限但需要越狱权限三是签名问题非越狱环境下签名容易失效建议用越狱环境。还有一个坑是iOS的音频延迟。Wine的音频输出走的是coreaudio在iOS上延迟比较高玩节奏游戏会很难受。可以尝试用PulseAudio的替代方案但配置比较复杂效果也不一定好。6. 这套方案还能怎么扩展Madeira这个思路其实不限于iOS。同样的架构可以搬到Android上Android的ARM64设备更多而且没有iOS那么多限制。FEX-Emu和Wine在Android上已经有社区在做DXMT也可以把Metal换成Vulkan。另外如果只是想跑一些老游戏不一定需要DXMTWine自带的D3D到OpenGL的转译也能用虽然性能差一些但兼容性更好。还有一个方向是把FEX-Emu换成Box64Box64是另一个x86-64到ARM64的翻译层在某些场景下性能比FEX-Emu好。Wine和Box64的配合也有社区在做可以对比试试。我个人在实际操作中的体会是这类项目的瓶颈往往不在翻译层而在图形驱动和系统限制。iOS的Metal驱动虽然性能强但封闭性导致调试困难很多问题只能靠猜和试。如果只是想玩Windows游戏用Windows掌机或者串流方案可能更省心。但如果你喜欢折腾想看看ARM设备到底能跑多少x86-64程序Madeira这条路值得走一遍。