Skip to content

项目架构概览 — 概念

分层架构

pokeemerald-wasm 采用三层边界适配架构,各层通过定义良好的接口通信:

核心组件

WASM 编译管线

topics/wasm-compilation/ 是项目的核心基础设施:

  • 使用 clang --target=wasm32-unknown-unknown -DMODERN=1 -DWASM=1 编译所有 .c 文件
  • 使用 wasm-ld 链接,配置 256MB 线性内存
  • 导出 AgbMain(入口)和 WasmRunFrame(帧执行)函数

GBA 硬件模拟

topics/gba-hardware/ 在 WASM 模块的 256MB 线性内存中复刻了 GBA 的内存映射——游戏代码像在真机上一样按固定地址读写这些区域,渲染器再从同一片内存读取它们合成画面:

  • I/O 寄存器0x04000000 起的内存映射寄存器(DISPCNT、DISPSTAT 等)
  • 调色板 RAM0x05000000,256 色 × 2 组(BG/OBJ)
  • 视频内存0x06000000VRAM 存储背景 Tile 和精灵图块数据
  • OAM0x07000000OAM 存储 128 个精灵的属性(位置、大小、Tile 索引)
  • Flash 存储0x0E000000,128KB 存档区域

资源转换管线

topics/asset-pipeline/ 负责将 GBA 特有的二进制数据转换为 WASM 可用的格式:

  • generate_wasm_assets.py:扫描源码中的 INCGFX / INCBIN 宏,生成 WASM 资源文件
  • wasm_asm_data.py:将 GBA 汇编数据文件(.s)中的 .word.byte 等指令转为 WASM 可链接的数据

渲染管线

topics/rendering/ 由 WASM 模块内的 src/wasm_display.c#if WASM 守卫)实现,把 GBA 的图形输出合成成一张 240×160 的 RGBA 帧缓冲区,宿主再把它搬到屏幕:

  • 背景渲染:读取 VRAM 中的 Tile 数据,根据背景模式(Mode 0-4)组合像素(TextBgPixel / AffineBgPixel
  • 精灵渲染:读取 OAM 属性,从 VRAM 提取 Sprite 图块像素,处理旋转/缩放(RenderSprites / ObjPixel
  • 调色板转换:将 GBA BGR555 格式转为 RGBA8888,写入模块内缓冲区(GbaColor
  • 导出WasmRenderFrame() 合成一帧,WasmDisplayBuffer() 返回 RGBA 指针;宿主 app.js 只需 putImageData

数据流:帧渲染流程

与原始 GBA 构建的兼容

项目保持了与原始 GBA 构建路径的完全兼容:

  1. make / make modern:仍可构建标准 GBA ROM
  2. make compare:仍可校验 ROM 完整性
  3. WASM 专用代码通过 #if WASM 守卫,不影响 GBA 构建
  4. WASM 专用源文件包括 src/wasm_display.c(软件 PPU)、wasm_field_effect_scripts.c 等,全部被 #if WASM 隔离

除了浏览器前端,上游还提供 make native-raylib(桌面 Raylib)、make native-bench(无头基准测试)、make native-kindle(Kindle Scribe 帧缓冲)三条原生构建路径。它们用 wasm2c 把同一份 WASM 转成 C 再链接各自宿主,复用相同的渲染与游戏核心。详见 构建部署概念

相关概念