2025/07/04 09:34 Writing a Game Boy Emulator in OCaml

ロボ子、今日はOCamlで作られたゲームボーイエミュレータ「CAMLBOY」について話すのじゃ!

ゲームボーイエミュレータですか、博士! OCamlで作られているとは珍しいですね。ブラウザ上で動くみたいですが、すごい。

そうじゃろう? しかもスマホのブラウザで60FPSで動くらしいぞ。記事によると、開発の目的はOCamlでの中規模プロジェクトの実践と、OCamlの高度な機能を使うことらしいのじゃ。

functor、GADT、first-class moduleですか。OCamlならではですね。アーキテクチャはどのようになっているんですか?

CPU、タイマー、GPUがクロックに従って固定レートで動いて、バスがCPUとハードウェアモジュール間のデータ読み書きをルーティングするらしいぞ。ハードウェアモジュールは`Addressable_intf.S`インターフェースを実装するのじゃ。

`Addressable_intf.S`ですか。8ビットデータの読み書きに使うんですね。16ビットデータ用には`Word_addressable_intf.S`があるみたいですね。

その通り!メインループは、CPUが命令を実行して、タイマーとGPUをCPUの消費サイクル数だけ進める、という流れじゃ。

なるほど。CPUモジュールは、Busモジュールへの依存を解消するためにfunctorを使っているんですね。テストのしやすさを考えているのが素晴らしいです。

じゃろ?命令セットはGADTを使って定義して、`execute`関数の型安全性を確保しているらしいぞ。カートリッジはfirst-class moduleを使ってランタイムにモジュールを選択するのじゃ。

GADTにfirst-class moduleですか。高度な機能が満載ですね!統合テストにはテストROMと`ppx_expect`を使っているんですね。リグレッション検出に役立ちそうです。

`js_of_ocaml`でJavaScriptにコンパイルして、ブラウザUIには`Brr`ライブラリを使っているらしいぞ。最適化も頑張っていて、Chromeのプロファイラでボトルネックを特定して潰しているのじゃ。

`oam_table.ml`や`tile_data.ml`、`timer.ml`、`tile_map.ml`など、かなり細かく最適化しているんですね。`Bigstringaf.get`の代わりに`Bigstringaf.unsafe_get`を使うだけでもパフォーマンスが向上するとは驚きです。

`js_of_ocaml`のインライン展開を無効化するとパフォーマンスが上がるのも面白い発見じゃな。OCamlの利点としては、duneによる容易なビルドや、Merlin、OCamlformatによる開発支援があるらしいぞ。

静的型付け、バリアント型、パターンマッチング、モジュールシステム、型推論もOCamlの強みですよね。一方で、opamのドキュメントが不十分で、再現可能な依存関係の解決が難しいという課題もあるんですね。

抽象化に依存することによる構文コストが高いというのも、OCamlの課題じゃな。でも、それを差し引いても、OCamlは素晴らしい言語なのじゃ!

そうですね! OCamlでゲームボーイエミュレータを作ってしまうなんて、本当にすごいと思いました。私もいつか、こんな大規模なプロジェクトに挑戦してみたいです。

ロボ子ならきっとできるぞ! ちなみに、このエミュレータで一番最初にプレイするゲームは何にする?

そうですね…やはりここは定番のテトリスでしょうか!

テトリスか。私はやっぱり、ドクターマリオかな!

博士らしいですね!

ところでロボ子、ゲームボーイって、実は「携帯ゲーム機」というジャンルを確立した、すごい発明品だったって知ってたか?

そうなんですね!知りませんでした!

せやろ?…って、ロボ子!今、完璧なボケのチャンスやったのに、なんでスルーするんじゃ!

えっ?あ…すみません、博士。次からは気をつけます…(汗)
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。