我用 TypeScript 完全重写了 Pokemon Yellow —— 它是如何在浏览器中运行的

发布: (2026年3月17日 GMT+8 22:30)
5 分钟阅读
原文: Dev.to

Source: Dev.to

我花了数月时间用 TypeScript 从头重写 Pokémon Yellow。这不是模拟器——它是一次完整的重新实现,逐条指令地将 Z80 汇编移植到 HTML5 Canvas。

在此玩 (自行提供 ROM) | 源代码

概览

整个引擎约 280 KB 的 TypeScript。没有随游戏一起提供任何资源;所有内容都直接从你自己的 ROM 文件在浏览器中提取。ROM 永远不会离开你的机器——生产构建只包含引擎本身,不包含任何受版权保护的内容。

引擎架构

ROM 验证与提取

  • 通过 SHA‑1 哈希验证上传的 ROM。
  • 运行 14 个专用提取器,解析原始二进制数据:
    • 宝可梦属性、招式数据、地图布局、对白文本、训练家队伍、音频序列。

图形解压缩

  • 使用原始压缩算法(RLE + 位对编码 + 增量解码)解压第 1 代精灵。
  • 将 Game Boy VRAM 格式的 1bpp/2bpp 瓦片图形解码为 ImageData

缓存

  • 将所有提取的数据缓存到 IndexedDB,因此再次访问时可瞬间加载。

汇编到 TypeScript 的翻译

原始游戏运行在 Sharp LR35902(Game Boy CPU)上。移植意味着将类似下面的汇编翻译为 TypeScript:

Audio1_CalculateFrequency:
    ld a, [wChannelOctave]
    inc a
    cp 7
    jr z, .done
    sra d
    rr e
    jr .loop
function calculateFrequency(octave: number, freq: number): number {
  let d = (freq >> 8) & 0xFF;
  let e = freq & 0xFF;
  for (let a = octave + 1; a > 1) | (d & 0x80)) & 0xFF; // SRA (arithmetic shift)
    const carry = d & 1;
    e = ((carry > 1)) & 0xFF; // RR (rotate right through carry)
    d = newD;
  }
  return (d << 8) | e;
}

每个细节都很重要——使用逻辑右移 (SRL) 而不是算术右移 (SRA) 会改变音乐的音高。我曾两次犯下这个错误。

音频合成

  • Game Boy 拥有四个声音通道(两个脉冲波,一个可编程波形,一个噪声)。
  • 实现了基于 ScriptProcessorNode 的合成器,以 44.1 kHz 生成采样,模拟全部四个通道。
  • 音乐引擎以 59.7 Hz(匹配 Game Boy 的 VBlank 频率)运行,解释从 ROM 中提取的指令序列(速度变化、音符事件、占空比切换、颤音、音高滑音)。
  • 50+ 条音乐轨道和 37 条音效均可完整播放。

战斗系统精确度

战斗系统忠实再现了第 1 代所有臭名昭著的怪癖:

  • 聚焦能量 bug – 暴击率被除以 4 而不是乘以。
  • 1/256 失误 glitch – 100 % 命中率的招式仍有约 0.4 % 的概率会失误。
  • 徽章属性提升叠加 – 烧伤/麻痹的属性下降每次都会重新应用徽章加成,导致溢出。

一套 334 条战斗测试 验证了每个边缘情况都与原版游戏相符。

演示功能

  • 带有动画皮卡丘和完整音乐的标题画面。
  • 大木博士的介绍序列。
  • 真新镇 → 1号道路 → 常磐市(共 12 张地图)。
  • 包含完整第 1 代机制的野生和训练家战斗。
  • 带有亲密度系统的皮卡丘随行。
  • 图鉴、队伍菜单、道具、商店、电脑、存档/读取。
  • 为移动端/平板提供的触控控制。

实时演示允许你上传合法获取的 ROM,并在桌面或移动设备的浏览器中进行游戏。

技术细节

  • TypeScript + HTML5 Canvas – 无框架、无依赖。
  • 使用 Vite 进行构建。
  • 使用 Vitest 进行测试(375 条测试)。
  • 大约 35 000 行 TypeScript 源码。

仓库与许可证

  • GitHub – MIT 许可证。欢迎提交 PR。
  • 与 Claude Code 作为编码伙伴共同构建。
0 浏览
Back to Blog

相关文章

阅读更多 »