Show HN:将《宝可梦 绿宝石》移植到树莓派 Pico 2
Show HN: Pokémon Emerald Ported to Raspberry Pi Pico 2

原始链接: https://github.com/mattdeeds/pokeemerald-rp2350

《宝可梦 绿宝石》已成功移植,可在 6 美元的 WeAct Studio Core2350B 微控制器(RP2350B)上原生运行。与模拟器不同,本项目通过将 *pokeemerald* 反编译代码重新编译至 ARM Cortex-M33 架构,实现了 60 FPS 的稳定帧率。 该系统充分利用了 RP2350 的两个核心:核心 0 处理游戏逻辑,核心 1 运行基于软件的 PPU 光栅化器。图形通过芯片的 HSTX 外设经由 HDMI 输出,该外设可独立处理显示扫描,从而确保画面无撕裂。游戏直接从 16MB 的 QSPI 闪存中运行,存档数据可在重启后保留。 虽然游戏可以从头到尾完整游玩,但仍有一些功能受限: * **音频:** 音乐引擎功能正常,但部分乐器类目前尚未实现。 * **连接性:** 通信线和无线适配器功能(交换/对战)尚未实现。 * **实时时钟(RTC):** 不支持实时时钟,影响浆果生长等基于时间的游戏事件。 本项目基于 *pokeemerald-wasm* 移植版开发,通过针对基于浏览器的参考版本进行自动化测试,保持了字节级的 PPU 精度。这是一项针对硬件进行深度优化的工程壮举,证明了现代低成本微控制器完全有能力原生运行复杂的经典游戏。

Hacker News 上的一篇帖子正在讨论一个最近的项目,该项目将《宝可梦:绿宝石》移植到了 Raspberry Pi Pico 2 (RP2350) 上。通过将代码从 ARMv4T 重新编译为 Cortex-M33,并利用设备的第二个核心以软件方式实现 GBA 的视频硬件,该项目实现了 60 FPS 的 HDMI 输出。 然而,讨论很快演变成关于软件开发中使用 AI 的两极分化争论。许多评论者批评该项目的 README 和代码库带有“AI 生成感”(vibecoded)——这是一个用来形容未经深度人工干预、由大语言模型生成的代码的术语。批评者认为此类项目缺乏技术真实性,并在公共代码库中充斥着“垃圾内容”;而支持者则为这种探索新工具的行为辩护,认为这是一种有效的学习尝试。其他引起关注的技术点还包括对代码库中包含受版权保护素材的担忧、潜在的硬件限制,以及关于优化 HDMI 音频性能的建议。
相关文章

原文

Pokémon Emerald running natively on a $6 microcontroller — full game, 60 fps, HDMI out, real buttons, saves that survive a power cycle. No emulator: the pret decompilation is recompiled from ARMv4T to Cortex-M33 and the Game Boy Advance's video hardware is reimplemented in software on the second core.

Target board is a WeAct Studio Core2350B (RP2350B, 16 MB QSPI flash). The whole game — code, graphics, maps, music — is an 11.7 MB image executed in place from flash.

        RP2350B @ 252 MHz
  ┌──────────────┬──────────────┐
  │    core 0    │    core 1    │
  │  game logic  │  PPU render  │──▶ 240×160 RGB565 framebuffer
  │   ~0.3 ms/f  │  ~12 ms/f    │         │
  └──────────────┴──────────────┘         ▼
         ▲                          HSTX ──▶ DVI/HDMI 640×480p60
    GP0–GP9 buttons                        (2× upscale, DMA control-block ring)

Playable start to finish as far as it has been tested — boots, plays the intro, starts a new game, walks the overworld, battles, and saves. Every scene holds a locked 60 fps except the OBJ-window intro cinematic. It is not a finished product; see Limitations.

Video ✅ Full PPU: modes 0–4, affine, sprites, windows, blending. Byte-exact vs. reference.
Frame rate ✅ Locked 60 fps, tear-free, vsync-locked to the scanout beam
Input ✅ 10 GPIO buttons
Saves ✅ Persist to QSPI flash, survive reboot and reflash
Audio ⚠️ Music plays; some instrument classes silent (see below)
Link cable / RFU ❌ Not implemented

See docs/HARDWARE.md for the full pinout, bill of materials, and wiring notes. In brief: an RP2350B board, an HSTX-to-HDMI breakout wired in the Pico DVI Sock pin order, ten buttons to ground, and optionally a PCM5102A I²S DAC for sound.

See docs/BUILD.md for prerequisites and the full procedure. The short version, from the repo root:

make tools && make modern           # first: decomp tools + generated assets
rp2350/gen_sound_assets.sh          # one-time: wav→bin, mid→song .s
rp2350/build_objs.sh                # game sources → rp2350/build/libpokeemerald.a
cmake -B rp2350/hw/build -S rp2350/hw -G Ninja   # PICO_SDK_PATH must be set
ninja -C rp2350/hw/build emerald
picotool load -f rp2350/hw/build/emerald.uf2

rp2350/hw/CMakeLists.txt also builds standalone bring-up targets that were used to validate each subsystem on silicon before integration, and which are the fastest way to debug a new board: hstx_test (colour bars), psram_test, i2s_test (440 Hz sine), display_test, ppu_display_test, emerald_hwtest.

The full engineering log — every phase, the measurements that made the go/no-go call, and the bugs that cost the most time — is in docs/PORTING.md. The short story:

It piggybacks on a WASM port. tripplyons/pokeemerald-wasm had already fenced every dependency on real GBA hardware behind #if WASM. Reusing those seams as #if WASM || RP2350 meant the de-hardwaring work was already done; this port only had to add the MCU-specific half.

The GBA memory map survives. The game still writes DISPCNT, VRAM, OAM and palette RAM at their original addresses — those are just plain SRAM now. Live RAM is ~378 KB of the RP2350's 520 KB. ROM lives in QSPI flash via XIP, with the game's 0x08000000 base remapped to 0x10000000.

The PPU is a software rasteriser on core 1. Ported from the WASM host's web/app.js and validated byte-exact against it. The first working version ran at 909 ms/frame; per-frame palette LUTs, per-scanline window masks, 8-pixel tile spans, and incremental affine stepping brought that to 60 fps — about 45× faster. Specialised inner loops then cut typical scenes to ~12 ms.

Scanout needs no CPU at all. A DMA control-block ring feeds the HSTX serialiser a full 525-line frame with the CPU never touching the re-arm path. The interrupt is advisory. This is what makes the display immune to the multi-millisecond stalls that flash writes cause during saves — and it took killing an ~0.8-blink-per-minute HDMI dropout to get there.

Honest list of what is stubbed, missing, or wrong:

  • Audio is incomplete. The m4a engine is ported and music plays, but DPCM (compressed) and reverse-playback instruments are silent stubs. Mixing is coupled to the frame rate, so any scene below 60 fps underruns. It has not had a careful by-ear correctness pass.
  • No link cable or wireless. The RFU and multiboot paths are stubbed. Trading, battling, and the Mystery Gift download-code path do not work. (Mystery Gift's run-downloaded-code path relocates data as Thumb code, which cannot work on an M33 as written.)
  • The RTC is a dead cartridge clock. Real Emerald bit-bangs an RTC over cartridge GPIO, which does not exist here. Time reads as zero and the in-game clock-set screen reports "clock is stopped." Berry growth and other time-of-day events are affected.
  • The OBJ-window intro cinematic runs at 20–25 ms/frame, below 60 fps. It is the one scene with no fast path.
  • Audio hardware is optional but unpolished. Without the I²S DAC wired, the game runs silently and correctly.

This is a fork of pokeemerald-wasm, which is a fork of pret/pokeemerald. Almost everything here is upstream; the port is confined to one directory.

Path What it is
rp2350/ The port. PPU, HSTX display driver, BIOS calls, m4a engine, build scripts.
rp2350/hw/ Pico SDK project: game_main.c, linker script, flash saves, I²S, test targets.
docs/ Hardware, build, and porting documentation.
src/, data/, graphics/, sound/ Upstream pokeemerald game sources and assets.
web/, tools/wasm_* The WASM build, kept as the PPU reference (see below).

The WASM build is deliberately retained. rp2350/ppu_validate.sh runs the game in a browser, dumps GBA memory plus reference frames from the JavaScript rasteriser, renders the same state with rp2350/ppu.c, and pixel-diffs the two. That harness is the only reason the PPU can be called byte-exact, and it caught real bugs during every optimisation pass. The Cloudflare deployment config from upstream has been removed, but make wasm and make serve-wasm still work.

rp2350/ is original work, released under the MIT License (rp2350/LICENSE).

The rest of the repository is the pret decompilation and carries no license from this project. Following pret convention, no ROM is required or included — the decompilation builds the game from its own committed sources. Pokémon and Pokémon character names are trademarks of Nintendo, Creatures Inc., and GAME FREAK Inc. This project is not affiliated with or endorsed by any of them.

联系我们 contact @ memedata.com