news 2026/10/1 16:40:47

在ARM设备上运行Windows程序:Wine、FEX-Emu与DXMT兼容层实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在ARM设备上运行Windows程序:Wine、FEX-Emu与DXMT兼容层实战

1. 从"Madeira"这个名字说起:一个跨平台兼容层的真实需求

第一次看到"Madeira"这个项目名,加上关键词里那一串 Wine、FEX-Emu、DXMT、x86-64、iOS,我脑子里第一反应是:这又是一个想在非 Windows 平台上跑 Windows 程序的兼容层项目。Wine 本身是"Wine Is Not an Emulator"的递归缩写,而 Madeira 是葡萄牙的一座岛屿,盛产葡萄酒——这个命名逻辑其实挺直白的,就是围绕 Wine 生态做文章。

但真正让我感兴趣的是关键词里同时出现了 FEX-Emu 和 DXMT。FEX-Emu 是一个用户态的 x86-64 到 ARM64 的指令翻译层,DXMT 则是把 D3D 调用翻译成 Metal 的图形层。这两个东西加上 Wine,组合起来指向一个非常明确的技术目标:在 ARM 架构的设备上(尤其是 Apple Silicon 的 Mac 和 iOS 设备),运行原本为 x86-64 Windows 编译的应用程序和游戏。

这个需求是真实存在的。Apple 从 M 系列芯片开始全面转向 ARM,Rosetta 2 虽然能翻译 x86-64 的 macOS 程序,但它管不了 Windows 的 PE 可执行文件。而 Wine 在 macOS 上长期依赖 CrossOver 这类商业方案,底层还是靠 Rosetta 2 做指令翻译。一旦你想在 iOS 或者纯 ARM 的 Linux 环境里跑 Windows 程序,就需要自己搭一套完整的翻译链路:PE 加载 → Windows API 实现 → x86-64 指令翻译 → 图形 API 转换 → 系统调用映射。

Madeira 要解决的,就是把这套链路整合成一个可用的整体。它不是一个从零开始的新轮子,而是把 Wine、FEX-Emu、DXMT 这几个成熟组件粘合起来,处理它们之间的接口对接、版本匹配、性能调优问题。这类"胶水项目"看起来不如底层组件光鲜,但实际落地时踩的坑一点不少——组件之间的 ABI 兼容、线程模型的冲突、图形上下文的生命周期管理,每一个都能让人调上好几天。

这篇文章我会从实际搭建和调试的角度,把这条技术链路拆开讲清楚。适合两类人看:一是想在 ARM 设备上跑 Windows 程序、被各种兼容性问题折磨过的开发者;二是对 Wine 生态、指令翻译、图形 API 转换这些底层机制感兴趣,想搞明白它们怎么协同工作的技术爱好者。不管你是哪一类,我都会尽量把"为什么这么设计"讲透,而不是只丢一堆命令让你照抄。

2. Wine 在 ARM 上的真实处境:为什么光有 Wine 不够

2.1 Wine 到底做了什么,又没做什么

很多人对 Wine 的理解停留在"能在 Linux 上跑 exe"这个层面,但具体它负责哪一段、不负责哪一段,往往说不清楚。我用一个类比来解释:把 Windows 程序想象成一个只会说中文的人,Linux/macOS 系统是一个只会说英文的环境。Wine 做的事情是当翻译,把 Windows API 调用(中文)翻译成 POSIX 系统调用(英文)。它翻译的是"语言",不是"口音"。

问题在于,Windows 程序编译出来的是 x86 或 x86-64 的机器码,这是"口音"层面的东西。Wine 本身不做指令翻译,它假设你的 CPU 能直接执行这些机器码。在 x86 的 Linux 上这没问题,CPU 原生就能跑。但到了 ARM 设备上,CPU 根本听不懂 x86-64 的指令,Wine 翻译出来的 API 调用再正确也没用,因为程序本身的代码就跑不起来。

这就是为什么在 Apple Silicon Mac 上,Wine 必须依赖 Rosetta 2。Rosetta 2 负责把 x86-64 指令翻译成 ARM64 指令,Wine 负责把 Windows API 映射到 macOS 的系统调用。两者配合,程序才能跑起来。但 Rosetta 2 是 Apple 的私有技术,只在 macOS 上可用,iOS 上虽然底层有类似机制,但苹果不开放给第三方应用调用。所以在 iOS 或者非 Apple 的 ARM Linux 设备上,你需要一个开源的 x86-64 翻译层——这就是 FEX-Emu 登场的地方。

2.2 FEX-Emu 的定位和它带来的新问题

FEX-Emu 最初是为 Linux ARM 设备设计的,目标是在 ARM64 Linux 上运行 x86-64 的 Linux 程序。它的工作方式是动态二进制翻译:程序运行时,FEX-Emu 把 x86-64 指令块翻译成 ARM64 指令块,缓存起来,下次执行到同一块代码时直接复用。这跟 QEMU 的用户态模拟类似,但 FEX-Emu 针对游戏场景做了大量优化,比如对 SSE/AVX 指令的高效模拟、对系统调用的直接透传。

把 FEX-Emu 和 Wine 组合起来,链路就变成了:Windows PE 程序 → Wine(API 翻译)→ FEX-Emu(指令翻译)→ ARM64 Linux 系统调用。听起来很清晰,但实际组合时会遇到几个硬骨头。

第一个是线程本地存储(TLS)的冲突。Wine 有自己的 TLS 机制来模拟 Windows 的线程环境,FEX-Emu 也需要 TLS 来管理翻译缓存和 CPU 状态。两者如果对 TLS 的使用方式不兼容,就会出现线程崩溃或者数据错乱。这个问题在单线程程序上可能不明显,一旦程序开多线程(现代游戏几乎没有单线程的),就会频繁触发。

第二个是信号处理的嵌套。Wine 用信号来实现 Windows 的异常处理机制(比如 SEH),FEX-Emu 也用信号来处理翻译过程中的异常和中断。当两层信号处理嵌套在一起时,信号掩码的管理、栈的切换、上下文的保存恢复,任何一个环节出问题都会导致程序莫名其妙地挂掉,而且这种崩溃往往没有明确的错误信息,调试起来非常痛苦。

第三个是内存模型的差异。x86-64 是强内存模型,ARM64 是弱内存模型。FEX-Emu 需要在翻译过程中插入适当的内存屏障指令来保证语义正确,但这会带来性能开销。Wine 内部的一些同步原语如果假设了强内存模型,在 ARM 上就可能出现竞态条件。这类问题在测试时不一定能复现,但在实际使用中会偶发。

2.3 版本匹配:一个容易被低估的坑

Wine、FEX-Emu、DXMT 这三个组件的版本兼容性,是我踩过的最大的坑之一。它们各自独立开发,发布节奏不同,接口也在不断变化。Wine 的某个版本可能修改了底层的内存分配接口,而 FEX-Emu 的对应适配还没跟上,结果就是编译能过、启动就崩。

我的经验是:不要盲目追新。如果你看到某个组合能跑通,先把这套版本号记下来,不要随便升级其中任何一个组件。等社区确认新版本组合稳定了再整体升级。具体来说,Wine 建议用 8.x 的稳定分支,FEX-Emu 用最近半年内的 release,DXMT 则要跟 Wine 的版本对应——DXMT 的 README 里通常会写明它适配的 Wine 版本范围,这个信息一定要看。

另外,编译顺序也有讲究。FEX-Emu 需要先编译安装,因为它提供了 RootFS 和工具链;然后编译 Wine 时要指定使用 FEX-Emu 的编译器包装器;最后编译 DXMT 时要链接 Wine 的开发库。顺序错了,链接阶段就会报找不到符号。

3. DXMT 的角色:把 D3D 翻译成 Metal 的得与失

3.1 为什么不用 DXVK 或 VKD3D

在 Linux 上跑 Windows 游戏,大家熟悉的方案是 DXVK(D3D9/10/11 → Vulkan)和 VKD3D-Proton(D3D12 → Vulkan)。这两个项目非常成熟,性能也很好。但在 macOS 和 iOS 上,Vulkan 的支持是个问题。macOS 原生不支持 Vulkan,只能通过 MoltenVK 把 Vulkan 转成 Metal,多一层转换就多一层开销和兼容性问题。

DXMT 的思路更直接:跳过 Vulkan,直接把 D3D 调用翻译成 Metal。这样做的好处是链路更短,理论上延迟更低,而且能更好地利用 Metal 的特性(比如 Metal 的 argument buffer、heap 管理)。坏处是 DXMT 的成熟度远不如 DXVK,很多 D3D 的特性支持不完整,遇到复杂的游戏就容易出问题。

我实测下来,DXMT 对 D3D11 的支持还算可用,大部分独立游戏和部分 3A 游戏能跑起来,但帧率波动比较大。D3D12 的支持就更初级了,很多依赖高级特性的游戏直接黑屏或者崩溃。如果你主要想跑 D3D9 的老游戏,DXMT 的表现反而比较稳,因为 D3D9 的 API surface 小,翻译起来简单。

3.2 Metal 命令行队列的提交时机

DXMT 里有一个设计细节值得单独说:Metal 的命令队列提交时机。D3D 的 Present 调用和 Metal 的 presentDrawable 不是一一对应的。D3D 程序可能在一帧内多次调用 Present(比如某些 UI 渲染逻辑),而 Metal 的 drawable 数量有限,如果每次 Present 都去获取新的 drawable,很快就会耗尽,导致卡顿。

DXMT 的处理方式是维护一个命令缓冲队列,把多次 D3D 的绘制调用合并到较少的 Metal 命令缓冲里,在合适的时机统一提交。这个"合适的时机"的判断逻辑很关键:提交太早,合并效果差;提交太晚,输入延迟高。DXMT 默认的策略是基于帧边界和队列深度来触发提交,但在实际使用中,我发现对于快节奏的动作游戏,手动调低队列深度阈值能明显改善操作手感,代价是帧率可能略微下降。

这个参数在 DXMT 的配置里通常叫maxFrameLatency或者类似的名称,具体取决于版本。调的时候建议从默认值开始,每次减 1,观察手感和帧率的平衡点。我自己的经验是,大部分游戏设在 2 到 3 之间比较合适,再低就容易出现画面撕裂。

3.3 着色器编译卡顿的缓解

D3D 游戏的着色器是在运行时编译的,DXMT 需要把 D3D 的 HLSL 字节码翻译成 Metal 的着色器语言,再交给 Metal 编译器编译。这个过程的耗时在 ARM 设备上比 x86 桌面明显更长,导致游戏首次遇到新场景时会出现严重的卡顿。

缓解办法有几个。一是开启 DXMT 的着色器缓存,把编译好的 Metal 着色器存到磁盘,下次直接加载。这个功能默认可能是关的,需要在配置里显式打开。二是预编译,有些游戏支持在加载界面预编译所有着色器,虽然加载时间变长,但游戏过程更流畅。三是降低着色器复杂度,比如关闭一些后处理效果,减少需要编译的着色器变体数量。

需要提醒的是,着色器缓存和 Wine 的版本、DXMT 的版本是绑定的。升级任何一个组件后,旧缓存可能失效甚至导致崩溃,这时候要手动清掉缓存目录重新生成。缓存目录的位置通常在~/Library/Caches或者 Wine prefix 的drive_c下面,具体路径看 DXMT 的文档。

4. 从零搭建 Madeira 环境的完整链路

4.1 基础依赖的安装顺序

搭建这套环境,顺序很重要。我推荐的顺序是:先装 FEX-Emu,再装 Wine,最后装 DXMT。原因前面提过,Wine 编译时需要 FEX-Emu 提供的工具链,DXMT 编译时需要 Wine 的开发头文件和库。

FEX-Emu 的安装有两种方式:用预编译的二进制包,或者从源码编译。预编译包省事,但可能跟你的系统库版本不匹配;源码编译耗时(在 ARM 设备上可能要一两个小时),但兼容性更好。如果你用的是比较新的 ARM Linux 发行版,建议先试预编译包,跑不通再自己编。

编译 FEX-Emu 时有一个关键配置:ENABLE_LTO。链接时优化能提升翻译后代码的性能,但会显著增加编译时间和内存占用。在内存小于 8GB 的设备上,建议关掉 LTO,否则编译过程可能因为 OOM 被杀掉。另外,CMAKE_BUILD_TYPE要设成Release,Debug 版本的性能差很多,不适合实际使用。

Wine 的编译配置里,--enable-archs参数要包含i386,x86_64,因为很多 Windows 程序还是 32 位的,只编译 64 位会跑不了。--with-fex或者类似的参数用来指定 FEX-Emu 的路径,具体名称看 Wine 的版本。编译 Wine 是个体力活,在 ARM 设备上可能要三四个小时,建议用make -j$(nproc)并行编译,但要注意内存占用,核心数多的机器可能反而因为内存不足而变慢。

4.2 Wine prefix 的创建与配置

Wine prefix 是 Wine 模拟的 Windows 环境,每个 prefix 相当于一个独立的 Windows 安装。创建 prefix 用wineboot命令,但直接跑wineboot可能会因为默认配置不适合 ARM 环境而失败。我建议先设置几个环境变量:

export WINEARCH=win64 export WINEPREFIX=~/madeira-prefix export FEX_ROOTFS=~/fex-rootfs

WINEARCH=win64创建 64 位 prefix,虽然也能跑 32 位程序(通过 WoW64),但配置更简单。FEX_ROOTFS指向 FEX-Emu 的根文件系统,里面包含了 x86-64 的基础库,Wine 在翻译指令时需要用到。

创建完 prefix 后,第一件事是装winetricks,然后用它安装一些基础组件:corefonts(字体)、vcrun2019(Visual C++ 运行库)、dotnet48(.NET Framework,很多游戏需要)。这些组件在 ARM 上安装可能会失败,因为它们的安装程序本身也是 x86 代码,需要 FEX-Emu 正确翻译。如果安装失败,可以试试用winetricks -q的静默模式,或者手动下载组件的离线安装包放到 prefix 里安装。

4.3 图形驱动的对接

DXMT 编译出来后,需要把它的 DLL 放到 Wine prefix 的对应目录里,通常是drive_c/windows/system32。然后要用winecfg或者注册表把 D3D 的 DLL 重定向到 DXMT 的版本。这一步如果没做对,Wine 会用自己的 D3D 实现(WineD3D),性能差很多,而且很多游戏跑不起来。

注册表的关键项是HKEY_CURRENT_USER\Software\Wine\DllOverrides,把d3d11、dxgi、d3d10core这些键的值设成native,表示优先使用 DXMT 提供的 DLL。改完注册表后要重启 Wine 才生效。

Metal 的验证层在调试时很有用,可以通过环境变量MTL_DEBUG_LAYER=1开启。开启后,Metal 的 API 调用会被检查,不合法的调用会打印警告或直接报错。这个功能在排查黑屏、花屏问题时特别有用,因为很多图形问题根源是 API 使用不当,而不是翻译逻辑错误。但验证层会拖慢性能,正式使用时记得关掉。

5. 实测中遇到的典型问题与排查思路

5.1 程序启动即崩溃,没有任何错误信息

这是最常见也最难查的问题。程序双击后闪一下就没了,终端里也没有输出。遇到这种情况,我的排查顺序是这样的:

第一步,用WINEDEBUG=+all跑一遍,把 Wine 的所有调试输出打到日志文件里。日志会非常大,但能看出程序走到哪一步挂的。重点看最后几行,通常是某个 DLL 加载失败或者某个 API 调用返回了错误。

第二步,如果 Wine 的日志看不出问题,用 FEX-Emu 的调试模式跑。FEX-Emu 有FEX_LOG_LEVEL环境变量,设成debug或者trace能看到指令翻译的详细过程。如果程序在翻译阶段就崩了,日志会停在某条指令上,那条指令就是嫌疑对象。

第三步,检查是不是缺少依赖。用ldd看 Wine 的二进制依赖是否都满足,用wine的+loaddll调试通道看程序加载了哪些 DLL,有没有加载失败的。很多崩溃是因为某个 Windows 系统 DLL 在 Wine 里没有实现或者实现不完整,程序调用到那个 DLL 的某个函数时就挂了。

5.2 画面渲染异常:黑屏、花屏、纹理错乱

图形问题通常跟 DXMT 和 Metal 的对接有关。排查时先确认 DXMT 是否真的被加载了:在终端里跑程序,看有没有 DXMT 的初始化日志。如果没有,说明 DLL 重定向没生效,回去检查注册表。

如果 DXMT 加载了但画面还是不对,开启 Metal 验证层看有没有 API 错误。常见的错误包括:纹理格式不支持(Metal 对某些 D3D 的纹理格式没有直接对应,DXMT 需要做转换)、渲染目标尺寸不匹配(D3D 允许渲染目标比窗口大,Metal 的 drawable 尺寸是固定的)、着色器编译失败(HLSL 到 Metal 的翻译有 bug)。

纹理格式的问题比较隐蔽,因为程序不会崩溃,只是画面颜色不对或者纹理显示为纯色。这时候要对比 D3D 的纹理格式和 Metal 的纹理格式,看 DXMT 的转换逻辑是否正确。如果某个格式转换有问题,可以在 DXMT 的源码里找到对应的转换函数,手动修正映射关系。

5.3 音频断续或延迟

音频问题往往跟线程调度有关。Wine 的音频实现(通常是 PulseAudio 或者 CoreAudio 的后端)在 ARM 上可能因为线程优先级设置不当而出现断续。FEX-Emu 翻译后的代码执行速度比原生慢,如果音频线程的优先级不够高,就会被其他线程抢占,导致缓冲区欠载。

解决办法是调整 Wine 的音频缓冲区大小。在winecfg的音频选项卡里,把缓冲区调大一些(比如从默认的 50ms 调到 100ms),给音频线程更多的容错空间。代价是音频延迟增加,但对于大部分游戏来说,100ms 的延迟是可以接受的。如果游戏对音频延迟敏感(比如音游),那就需要在性能和延迟之间做取舍了。

另一个可能的原因是采样率不匹配。Windows 程序可能请求 44.1kHz 的采样率,而系统音频设备工作在 48kHz,Wine 需要做重采样。重采样算法如果质量不高,会有杂音。可以在winecfg里强制指定采样率跟系统一致,避免重采样。

5.4 输入设备不响应或映射错误

手柄和键盘的输入问题通常出在 Wine 的输入子系统上。Wine 在 Linux 上通过 evdev 或者 SDL 读取输入设备,在 macOS 上通过 IOKit。如果设备被其他程序独占,Wine 就读不到。

排查时先用evtest(Linux)或者系统的输入设备查看工具确认设备是否正常工作。然后在 Wine 的注册表里检查输入设备的映射,HKEY_CURRENT_USER\Software\Wine\DirectInput下面有相关配置。有些手柄需要手动指定为native模式才能被游戏识别。

键盘映射错误比较少见,但如果遇到,通常是键盘布局的问题。Wine 默认使用系统的键盘布局,如果系统布局跟游戏期望的不一致,按键就会错位。可以在winecfg的驱动选项卡里手动指定键盘布局。

6. 性能调优:让翻译层跑得更快

6.1 FEX-Emu 的翻译缓存策略

FEX-Emu 的性能很大程度上取决于翻译缓存的命中率。翻译缓存分两级:一级是内存中的缓存,二级是磁盘上的缓存。内存缓存命中时,指令直接执行,没有翻译开销;磁盘缓存命中时,需要从磁盘加载翻译结果,比重新翻译快,但比内存缓存慢。

增大内存缓存的大小能提升命中率,但会占用更多内存。FEX-Emu 的配置里有MaxCacheSize之类的参数,默认值通常比较保守。在内存充足的设备上(8GB 以上),可以适当调大。我一般设成 256MB 到 512MB,再大收益就不明显了。

磁盘缓存的位置建议放在 SSD 上,机械硬盘的随机读取速度会成为瓶颈。如果设备支持 NVMe,把缓存放在 NVMe 盘上能明显缩短加载时间。缓存文件会随着使用不断增大,要定期清理旧的缓存,否则磁盘空间会被占满。

6.2 多线程程序的调度优化

Wine 和 FEX-Emu 都对多线程程序有额外的开销。Wine 需要模拟 Windows 的线程模型,FEX-Emu 需要为每个线程维护独立的翻译状态。线程数越多,开销越大。

对于多线程游戏,可以尝试限制线程数。有些游戏会根据 CPU 核心数自动设置线程数,在 ARM 设备上核心数可能很多(比如 8 核或 10 核),但翻译层的开销使得实际有效的并行度没那么高。手动把游戏的线程数限制在 4 到 6 个,往往能减少线程切换的开销,提升整体帧率。

CPU 亲和性设置也有帮助。把 Wine 的进程绑定到特定的核心上,减少跨核心的缓存失效。在 Linux 上用taskset,在 macOS 上用taskpolicy。具体绑到哪些核心要看设备的拓扑结构,一般建议绑到大核上,小核留给系统后台任务。

6.3 图形设置的取舍

在 ARM 设备上跑 Windows 游戏,图形设置要务实。分辨率不要追求原生,适当降低能大幅提升帧率。抗锯齿关掉或者用最低档,MSAA 在翻译层上的开销比原生大得多。阴影质量、后处理效果这些也建议调低。

DXMT 有一些自己的性能选项,比如是否启用异步着色器编译、是否启用管线缓存。异步编译能减少卡顿,但可能导致画面短暂异常(着色器还没编译完就渲染了)。管线缓存能加速着色器的加载,但会占用磁盘空间。这些选项的取舍要看具体游戏,没有一刀切的最优解。

垂直同步建议关掉。翻译层的帧率本来就不稳定,开垂直同步会让帧率被锁在 30 或 60,而且输入延迟增加。关掉垂直同步后,虽然可能有画面撕裂,但操作响应更快,整体体验反而更好。如果撕裂严重,可以在 Metal 层面开自适应同步(如果设备支持)。

7. 这套方案适合谁,不适合谁

7.1 适合的场景

Madeira 这套组合最适合的场景是:在 ARM Linux 设备(比如树莓派 5、各种 ARM 开发板、ARM 笔记本)上运行轻量级的 Windows 程序和老游戏。这些程序对性能要求不高,D3D 特性用得少,Wine 和 DXMT 的兼容性足够覆盖。

另一个适合的场景是技术研究和学习。如果你想理解二进制翻译、API 翻译、图形 API 转换这些底层机制,自己搭一套 Madeira 环境,从源码编译到调试运行,整个过程能学到很多东西。这比看文档和论文直观得多,因为你能亲眼看到每层翻译的实际效果和性能开销。

对于 Apple Silicon Mac 用户,如果你不想用 CrossOver 这类商业方案,Madeira 也是一个选择。但要注意,macOS 上的系统调用限制比 Linux 多,Wine 的某些功能可能受限。而且 macOS 的 Metal 驱动跟 DXMT 的兼容性需要额外测试,不是所有游戏都能跑。

7.2 不适合的场景

如果你追求开箱即用、稳定运行最新的 3A 游戏,Madeira 不适合你。翻译层的性能损失是客观存在的,x86-64 到 ARM64 的翻译开销通常在 20% 到 50% 之间,具体取决于程序的指令特征。图形 API 的翻译也有开销,DXMT 的效率目前还比不上原生的 D3D 驱动。

如果你需要运行依赖内核态驱动的程序(比如某些反作弊系统、虚拟机软件),Wine 本身就跑不了,加上 FEX-Emu 也没用。这类程序需要真正的 Windows 内核,Wine 的用户态实现无法满足。

如果你对稳定性要求极高,不能接受偶发的崩溃和兼容性问题,那还是用原生的 Windows 环境或者成熟的商业兼容方案。Madeira 这类开源组合的测试覆盖度有限,遇到问题的概率比商业方案高。

7.3 一些实际的预期管理

我在实际使用中最大的体会是:不要期待完美。翻译层能做到"能跑",但很难做到"跑得好"。帧率波动、偶发崩溃、某些功能不可用,这些都是常态。你要有一定的调试能力和耐心,遇到问题能自己查日志、看源码、试配置。

另外,社区的支持很重要。Wine、FEX-Emu、DXMT 都有自己的社区论坛和聊天群,遇到问题先搜一下有没有人遇到过。很多坑别人已经踩过了,解决方案可能就在某个 issue 或者讨论帖里。自己闷头调可能花好几天,问一下可能几分钟就解决了。

最后,记录你的配置。每次调通一个游戏,把 Wine 版本、FEX-Emu 版本、DXMT 版本、注册表修改、环境变量、游戏设置都记下来。下次遇到类似问题,这些记录能帮你快速定位。我自己的记录已经攒了几十个游戏的配置,新游戏上手时先翻记录,能省很多时间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 16:40:19

Unity完整RPG项目实战:从零搭建核心系统与工程架构

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 16:39:37

Claude Code九月更新:AGENTS.md、长任务续接与插件管理详解

1. “认了”AGENTS.md:项目级指令的开放标准时代如果你跟我一样,从上半年就开始把 Claude Code 当主力编码工具用,那你对CLAUDE.md一定不陌生。它是 Claude Code 用来读取项目说明、理解仓库上下文、约束代码风格的主配置文件。过去小半年里&…

作者头像 李华
网站建设 2026/10/1 16:39:27

Origin插件实现多组两两比较显著性字母自动标注

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 16:38:51

液晶显示基础:从原理到段码屏驱动的实用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 16:38:49

穿越火线安全策略升级:从行为风控到设备指纹的全面解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 16:38:49

参考文献交叉引用机制:Word、Zotero、LaTeX实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华