Hotdry.

Article

WinCE64:Nintendo 64 硬件上的 Windows CE 2.11 移植架构

解析在 N64 真实硬件上运行 Windows CE 2.11 的实模式引导流程、VR4300 HAL/OAL 设计与 NAND 模拟器实现细节。

2026-05-15systems

Windows CE 2.11 发布于 1999 年,Nintendo 64 则更早(1996 年)。将前者移植到后者的裸金属硬件上运行,这绝非简单的交叉编译问题 —— 而是一场跨越三代嵌入式平台工程思维的逆向重构。WinCE64 项目(throatymumbo/WinCE64)正是这一挑战的系统性解答:它用自定义 HAL/OAL 接住未经修改的 nk.lib 内核,在 N64 的 VR4300 MIPS 处理器上完整还原了 CE 2.11 的 GWES 桌面与 Shell 环境。

架构分层:从 IPL3 到 NK.BIN

项目采用典型的双阶段加载架构。bootloader 目录下的 libdragon IPL3 trampoline 是第一阶段,负责在 N64 上电后完成最小硬件初始化,随后将 SD 卡上封装的 CE ROM 镜像(nk.bin)加载到 RDRAM 中执行。第二阶段才是真正的 CE 内核 ——nk.exe(封装于 nk.lib)负责 PSL(Processor Support Layer)调度、TLB 管理与线程调度。

架构图清晰展示了层级关系:未经修改的 nk.lib 处于核心位置,其下方是整套 BSP 代码(HAL、OAL、驱动程序),其上方是 CE 标准用户态模块(coredll.dllgwes.exefilesys.exedevice.exeshell.exe)。这意味着只要 BSP 层正确实现了 CE 定义的 OAL 接口,理论上任何版本的 CE 内核都能在此硬件上运行 —— 项目选 2.11 版本纯属个人偏好与版权规避考量。

关键设计约束在于:CE 2.11 并不持有 N64 专有的硬件抽象定义,nk.lib 仅实现了与平台无关的核心调度逻辑。所有外设驱动 —— 从帧缓冲刷新到控制器轮询 —— 都必须由 OEM 在 BSP 层重新实现。项目将这些驱动全部置于 bsp/ 目录下,并通过标准 CE DDI 接口向上对接 GWES。

HAL/OAL:VR4300 的 CE 适配层

OAL(OEM Adaptation Layer)是 CE 移植工作中最底层的代码,其核心职责是将 CE 内核的抽象硬件请求翻译为特定 CPU 架构的操作序列。N64 采用 MIPS R4300 的变体 VR4300,这决定了 HAL 层的实现与主流 ARM/x86 嵌入式移植有本质差异。

首先是异常向量与中断处理。MIPS 架构使用固定的异常入口地址(0x80000000 起),HAL 必须在启动阶段正确设置这些向量,并将 N64 的 MIPS 中断控制器映射到 CE 的 IRQ 系统。TLB(Translation Lookaside Buffer)管理是另一个核心工作:CE 内核假设存在分页内存管理系统,OAL 必须为 nk.lib 提供虚拟地址到物理 RDRAM 的映射表。

RDRAM 本身是 N64 存储系统的特殊存在。项目文档特别提到了 LE-mode(Little-Endian)RDRA partial-word 读写 quirk——N64 原始设计为大端序,但其 RDRAM 控制器在处理非对齐字访问时表现出小端行为。这一硬件层面的 quirk 在仿真器中不可见,仅在真实硬件上触发,迫使 HAL 实现了专门的工作区代码来规避数据损坏。

定时器是 HAL 另一项关键功能。CE 内核依赖周期性定时中断来驱动调度器与超时检测。OAL 必须配置 VR4300 的 count/compare 寄存器以生成稳定的时间基准,同时保证中断服务例程足够高效,避免与 N64 音频硬件的 SysAD 总线访问产生竞争。

显示驱动:VI + RDP 双路渲染

N64 的图形子系统由 VI(Video Interface)和 RDP(Reality Display Processor)两个独立部件组成。VI 负责将帧缓冲内容输出到 CVBS/S-Video 信号,RDP 则承担多边形光栅化与纹理采样。WinCE64 的显示驱动策略是让 VI 作为最终输出窗口,而将 RDP 作为 GDI 填充加速器。

CE 2.11 的显示驱动架构基于 GPE(Graphics Peripheral Engine)抽象层。标准 SDK 提供了 MGDI(Mini Graphics Driver Interface)和 GPE 库,但这些库面向的是通用帧缓冲设备。项目编写了自定义 GPE 实现,将 Ng PrimWrite 调用转发到 RDP 的 RDP FillRectangle 命令 —— 这意味着窗口背景填充和矩形绘制操作可以完全绕过 CPU 计算,直接在图形硬件上执行。

光标渲染是另一个工程难点。CE 2.11 将光标拆分为 CURSOR.LIBMCURSOR.LIB 两个库,这一设计适用于支持 overlay 模式的硬件(overlay 允许光标层叠加在主帧缓冲之上)。但 N64 的 VI 不支持 overlay,光标层必须合成到主帧缓冲中。驱动通过软件光标合成器解决了这一问题:在每次垂直同步中断后,光标位图被混合到帧缓冲指定坐标处。

输入子系统:SI Joybus 与鼠标模拟

N64 控制器通过 SI(Serial Interface)Joybus 协议与主机通信。这是一个半双工同步串行总线,控制器内部包含一个 PROM,负责响应主机的轮询请求并返回当前输入状态。项目在 bsp/drivers/kbdmouse/ 中实现了完整的 SI 轮询解码逻辑。

控制器被映射为 CE 的鼠标设备:A 按钮对应左键,B 按钮对应右键,方向键控制光标移动。官方 N64 鼠标同样受支持,这使得在 CE 桌面环境中进行精细操作成为可能。从 CE 的视角看,这些设备通过标准的 Mouse_Open/Mouse_Read PDD 接口向上提供服务。

SD 存储:FatFS 与 EverDrive-X7 驱动

CE 2.11 将文件系统抽象为 FSD(File System Driver)层,标准实现支持 FAT12/FAT16/MS-DOS 分区。项目在 bsp/drivers/sdfsd/ 中实现了 FatFS 封装 FSD,并将 SD 卡挂载为根目录下的 \SDCard\ 路径。

物理层面,SD 卡数据通过 EverDrive-64 X7 cartridges 的 FPGA 控制器访问。项目没有直接使用 libdragon 的 libcart 库,而是编写了 edx_x7.c—— 一个基于 PI-DMA 的驱动程序。文档指出了这一决策的根源:libdragon 在处理真实硬件上的 cart 总线读写后写 quirk 时存在盲区,该 quirk 在仿真环境中完全不可见,但在硬件上会导致数据错位。直接操作 X7 的 DMA 通道可以绕过这一问题。

音频子系统:AI 硬件与 Wave PDD

N64 的音频输出由 AI(Audio Interface)硬件负责,它从主内存读取 PCM 数据并转换为 I2S 数字音频流。项目实现了 polling 模式的 AI 驱动而非中断驱动 —— 这是因为 MI_INTR_MASK_AI 中断开启时会阻塞 SysAD 总线访问,而 CE 的 wave API 栈需要频繁进行小块数据传输。

驱动通过持续轮询 AI 状态寄存器来检测缓冲区空缺,并在 CE 的 waveOutWrite 调用时将新数据块写入 AI FIFO。这种设计牺牲了一些 CPU 效率,但避免了总线争用导致的音频断断续续问题。驱动层叠于标准的 waveapi.dll 之上,CE 应用程序通过 sndPlaySoundWwaveOutOpen API 即可触发音频播放。

Shell:从零构建 Win9x 风格桌面

CE 2.11 SDK 最大的工程空白是没有提供桌面 Shell。微软的设计哲学是:OEM 厂商应当基于 GWES API 构建自己的 Shell,Platform Builder 仅提供内核与系统服务。H/PC Pro 设备上看到的 Shell 来自微软的硬件合作伙伴,而非 SDK 分发。

项目在 bsp/shell/ 中实现了完整的 Win9x 风格桌面组件:桌面窗口管理、任务栏(含开始按钮与时钟)、文件浏览器(遍历 \SDCard\ 并调用 FindFirstFileW)、模态对话框,以及带 commctrl 旋转控件的 UI。驱动层 bsp/drivers/commctrl/ 还补全了 CE 2.11 SDK 遗漏的 commctrl.dll DllMain—— 没有这个入口,spinner 控件类根本不会向系统注册。

构建系统:Wine 承载二十年前的工具链

CE 2.11 的官方构建工具(CLMIPS.EXELINK.EXERC.EXEROMIMAGE.EXE)是运行在 Windows NT/9x 上的 16/32 位混合可执行文件。项目使用 Wine 在 Linux 环境下原样运行这些工具,无需虚拟机或模拟器。构建脚本保持了单一 wineserver 进程常驻以分摊冷启动开销,使干净构建总耗时控制在约 30 秒。

最终产物 n64ce.z64(约 3.5 MB)通过 diag/ed64_upload 工具直接写入 EverDrive-64 X7 的 SD 卡并自动执行。项目不出具预编译 ROM 镜像 —— 所有 CE 二进制文件(nk.exegwes.execoredll.dll 等)来自微软 SDK 的静态库,分发这些内容超出 MIT 许可证范围。


资料来源throatymumbo/WinCE64 - GitHub

systems

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com