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 的用户项目,引发了关于人工智能辅助开发的激烈争论。 该项目通过将游戏的 ARMv4T 代码重新编译为 Cortex-M33 架构,并以软件方式重构了 Game Boy Advance 的视频硬件,实现了 60 FPS 的 HDMI 输出。尽管其技术成就值得关注,但评论区很快演变成了一场关于“氛围编程”(vibe-coding)和人工智能生成文档的元讨论。 批评者认为该项目是“AI 垃圾”,声称开发者过于依赖大语言模型来生成代码和说明文档,缺乏必要的人工审查。相反,支持者则捍卫将人工智能作为探索性学习工具的用法,并驳斥了批评者中存在的精英主义式门槛。讨论还涉及了潜在的版权风险(鉴于项目中包含了游戏资产),以及关于 AI 生成文本中对破折号和分号使用方式的滑稽争论。归根结底,这篇帖子是当前开发者社区围绕人工智能在创意和开源软件项目中扮演的角色而产生矛盾的一个缩影。
相关文章

原文

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