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

February 28, 2019 (Updated on: June 9, 2019)
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を動かすのは感慨深いのでぜひおすすめしたい.