ゲームボーイのエミュレータを自作した話

February 28, 2019 (Updated on: January 14, 2021)
by Keichi Takahashi

最近ゲームボーイのエミュレータを自作した.これが予想以上に楽しい趣味だったので ,色々な人に勧めたいと思いこの記事を書いている. 開発したエミュレータ “rgb” のソースコードはここに 公開している.ちなみにRustで書いた.

Mario

なぜエミュレータなのか

今までエミュレータを書いたことがなかったから,に尽きる.QemuやWineなどの エミュレータは普段から使っているし,エミュレータの動作原理は理解しているつもり でも,自作したことがなかったので,何となく気持ち悪さがあった.

今回,自ら手を動かしてゲームボーイのエミュレータを開発したことにより, 大体エミュレータの作り方が把握でき,他のプラットフォームのエミュレータも開発 できる見込みが立った. また,副次的効果としてコンピュータアーキテクチャの良い復習になった. ゲームボーイはレトロかつ単純なアーキテクチャとは言え,コンピュータアーキテクチャの 教科書に出てくるような構成要素を一通り備えている.あるアーキテクチャを クロックレベルで隅々まで 理解するというのは,エンジニアとして良い経験になるし,自信もつくと思う.

なぜゲームボーイなのか

資料と開発環境が充実しており,ハードウェアが比較的単純なため,短い期間で開発 できる見込みがあったためゲームボーイを選んだ. また,ファミコンのエミュレータを自作したという記事は 見かけるのに,ゲームボーイのエミュレータを自作したという記事が (日本では) 少なかった. 個人的理由として,僕が初めて触ったゲーム機がゲームボーイだったということもある.

ちなみに今年はゲームボーイ30周年らしいので,エミュレータを自作するなら良い タイミングかもしれない.

豊富な資料

各命令の動作やペリフェラルの仕様が有志によって詳細に解析され,ドキュメントとして 整理されている.そのため,結局,実機を触らないままエミュレータを完成させることが できた.以下に,特に参考になった資料を書いておく.

  • Pan Docs: おそらくゲームボーイの 資料としては最も有名で,誰もがまずこれを読むと思われる.CPU,PPU, APU,カートリッジなど,一応全てのハードウェアの情報がまとまっている. ただし,簡潔に書かれており情報が足りない部分があるので,他の資料も 参照しながら開発することになる.オリジナルのバージョンは更新されていなが, Wikiにあるバージョンは更新が 続けられているようだ.
  • Gameboy CPU (LR35902) instruction set: ゲームボーイのCPU (LR35902) の全命令をまとめた表. 一覧性が高く,オペランドのフォーマットや命令のクロック数も記載されているため, 命令デコーダの作成に重宝する.ただし,一部のクロック数は間違っているという 罠がある.
  • Game Boy CPU Manual: CPU の各命令の詳しい動作が記載されている.フラグがセット・クリアされる条件など, 上の表よりも詳しい.ただし,一部の命令 (DAA命令など) の動作はこの資料でも まだ情報が足りないため,他の資料をあたることになる.

充実した周辺環境

アセンブラ,エミュレータ,デバッガ等の開発ツールがが充実している. ここら辺の開発ツールがないプラットフォームだと,自分で全てのツールを自作 しなければいけないので大変だと思う. 以下に,主に使用したツールを書いておく.

  • WLA DX, RGBDS (アセンブラ): テスト用のROMを作成したり,既存のテストROMを改造する際に使った.
  • BGB (エミュレータ・デバッガ): 色々あるエミュレータの 中で,デバッガ機能が一番充実している.ブレークポイント,ステップ実行, レジスタの表示はもちろん,VRAMの中身を可視化できる.BGBの動作 と自分のエミュレータの動作を比較することでデバッグに重宝した. Windows用のアプリケーションだが,Wineを使うことでmacOSやLinux上で問題なく 動く.
  • Blargg’s test roms (テス トROM): 各種資料を参考にエミュレータを実装していっても,本当に正しく実装 できているのかわからないという問題がある.テストROMを使うことにより, エミュレータの動作を自動的に検証できる. テストROMは実機で通ることが確認されているため,ドキュメントよりも信頼できる. Blargg’s test romsには複数のROMが含まれているが,中でも命令の動作をテスト するcpu_instrsと,命令のクロック数をテストするinstr_timingは通らないと, 実際のゲームは動かないと思う.逆に言えば,他のテストは通らなくても何とかなる.

なお,GitHubにAwesome Game Boy Development というawesome-*系のページがあり,エミュレータやゲームの開発に有用なツールや ドキュメントがまとまっている.

単純なハードウェア

ゲームボーイは8-bitのCPUを中核とした単純なハードウェアで, 資料を眺めていると,自作できそうな気がしてくる.僕がエミュレータを開発する きっかけになったのはMichael SteilさんによるThe Ultimate Game Boy Talkという 発表で,1時間の発表でゲームボーイの全てのハードウェアについて,かなり詳しく 話している.

また,ハードウェアが単純なので,開発量・期間も少なくて済み,趣味に向いている. 僕が書いたエミュレータはRustで約2,000行で,開発期間は約1ヶ月である. 時代が進んで複雑・多機能なハードウェアになってくると,簡単なゲームを1本動かす までに力尽きる可能性が出てくるのではないかと思う.

Tips

最後に,実際にエミュレータを書いてみて学んだ知見についてメモしておく.

  • テストROMを使う: まずはテストROMを通すことを目標に開発した方が良い. 上で紹介したBlargg’s test romsは,シリアル出力にテスト結果を出力してくれる 機能がある.そのため,PPUが未実装の開発の初期段階からでも使用できる.
  • ドキュメントには誤りがある: 上で豊富なドキュメントと書いているのに矛盾 しているが,あくまで非公式のドキュメントであり,たまに間違いがある. 命令のクロック数やフラグの更新は最たるもので,多くのドキュメントで微妙に 間違っている箇所がある.ドキュメント通りに実装してテストROMが通らない場合 は,ドキュメントを疑い,テストROM通りに実装した方が良い.
  • 基本的なデバッガを実装する: エミュレータの開発中,多くの時間をデバッグに 費やすことになる.このとき,エミュレータに基本的なデバッグ機能を実装 しておくと大きな助けになる.僕の場合はレジスタのダンプと,実行した命令の トレース機能しか実装せず残りはprintfデバッグで頑張ったが,さぼらず ブレークポイントやステップ実行も実装しておけば,結果的には手間が減ったので はないかと思う.
  • ROMとROM吸出し機を買う: エミュレータを作成するからには,実際のゲームを 動作せることが目標になると思う.そこで,ゲームのカートリッジからROM吸出し機 でROMを抽出する必要がある.カートリッジは1本100円,吸出し機は2,000円 程度から購入できるので,本気でエミュレータを開発するなら良い投資だと思う. どうしてもカートリッジを買いたくない場合は,有志が作成したオープンソースの ゲームのROMを使うという手もある (Homebrew Hub を参照) .とはいえ, 自作したエミュレータ上で自分で吸い出したROMを動かすのは感慨深いので ぜひおすすめしたい.