🎮

Go で実装したファミコンエミュレータ「ChibiNES」を公開した話 (Idea)

2022/08/01に公開約3,700字

何番煎じか分かりませんが、私も「ファミコンエミュレータを書いてみたい!」と思って「ChibiNES」というファミコンエミュレータを公開しました

https://github.com/kaishuu0123/chibines

Releases からバイナリをダウンロードできます

ファミコンは子供の頃にやっていたこともあり、特段と思い入れがありました (とはいえ、私の世代はスーファミ全盛期なのだろうか)

機能紹介、苦労話、振り返りと雑多に書いていこうと思います

機能紹介

README.md に画像を貼り付けていますが、マリオや私の独断と偏見で選んだゲームが動きます。

NSF Player (NSF というファイルから音楽を再生するプレイヤー) も(別コマンドでですが)動きます (音無しバージョン)

https://youtu.be/IAwbvn3i6Vo

Mapper を全て実装するのは現実的ではないので、持っていたゲームに留めました。

このプロジェクトを通じてやりたかったこと

  1. 自分の好きだったゲームを動かしたかった
    • 吸い出し機買いました
  2. マルチプラットフォーム(Windows, Mac, Linux)でバイナリを提供したい
    • マルチプラットフォームなライブラリの選定
    • GitHub Actions で Releases にバイナリが登録できるように
  3. ネイティブアプリケーションで動かしたい
    • ブラウザで動かす方法(Canvas, WebAudio)もありますが、そこはロマンです
  4. VirtuaNES に実装されている NSFプレイヤーのようなものを作りたい
  5. Go で何か重めな実装をしてみたかった
  6. (後になって出てきたモチベ) christopherpow/nes-test-roms: Collection of test ROMs for testing a NES emulator. の PPU テストが通るレベルを目指したかった
    • この nes-test-roms のテストに PASS しなくても動きますし、他のメジャーなエミュレータも通ってない ROM もありますが、「ハードの癖」みたいなものを知るいい機会だったので
    • (これにめちゃくちゃ苦しめられた)

中身の話 (ライブラリとか選定理由とか)

ライブラリのお話

  • GUI 周りは go-gl/glfw (GLFW) と inkyblackness/imgui-go (Dear ImGUI)
    • このプロジェクトの副産物として imgui-go に PR を送って無事 Merge されました 🎉
    • Qt とか GTK (!?) とかも迷ったんですが、OS ネイティブな何かを使うわけではないので、Dear ImGUI で実装することにしました
    • Qt の OSS 版は M1 Mac というか Apple Silicon に対応していなかったので残念ながら却下となりました
    • GLFW 側でファイルの D&D に対応してくれていたので、ファイルダイアログの実装はしないことにしました
    • (余談) Mesen は Core 部分は C++、GUI 部分は C# (.NET Framework かな?) で書かれているみたいですね
  • 音声は portaudio (fogleman/nes から)
    • SDL2 の audio を使っても良かったのですが、SDL2 に移植するモチベは無かったのでそのままにしています

また、いろいろなところからコードを引っ張ってきてるので、Core 部分はキメラ化しています

  • Core 部分 (CPU, PPU, APU) は libretro/Mesen の丸パクリ を参考
  • NSF Player の再生機構は theinternetftw/famigo から
    • 表示部分は調べつつ書きました

エミュレータ実装を体験してみての感想

  • ファミコン文化すごい
    • 自作の ROM を開発していたり、チップチューンな曲を作っている方がいたり、モチベーションが凄いなぁ、と
    • NSD.lib などのライブラリを公開されている方もいらっしゃったり、奥が深い世界だなぁ、と感銘を受けています
  • ファミコン本体の拡張をせずに「カセットでどうにかしよう!」の気持ちが凄すぎる
    • 仕様理解として一番苦労したところなんですが、当時のファミコンゲーム開発者の方々の「とにかくカセットでなんとかしよう!」という情熱が凄いですね
    • バンク切り替えから始まり、拡張音源もあったり、チャレンジングすぎます
  • Mapper の各種実装が全然分からん
    • FPGA を使ったエミュレータとかであれば、カセットの中にチップが入ってるので Mapper の実装はいらないのですが、ソフトウェアエミュレーションではもちろん必要です
    • 「先人の方々はカセットをめちゃくちゃ解析して挙動を見たんだろうなぁ」と思い、その情熱に感服します
    • 全 Mapper 対応は趣味でやる領域じゃない 対応できてるソフトはすごい
  • 音のプログラミング奥が深すぎる
    • 未だに理解が浅いと思います
    • まず音の出し方から分からない、APU のコードを読んで「なんでこの音が出るんだ?」という疑問が晴れない、みたいなのを延々と繰り返してました
    • 小さいプログラムを書いて、サイン波を鳴らしてみたり、APU 周りはとにかく苦労しました
    • 拡張音源というものを知った時には「なんでやヽ(`Д´)ノ」と思わず叫びそうになったほど

まとめ

  • 実際に仕様を読んでみたり、コードを書いてみないと知ることができないエミュレータの世界を知ることができました
    • chibines 自体に工夫する余地(テストを書いたり、リファクタしたり etc ...) はものすごく多いですが、一旦キリがいいところまで来たので、しばらくはこのまま置いておくことにします
  • ゲームボーイやスーパーファミコンのエミュレータはどうなってるんだろう?という気持ちが出てきました
    • Mapper ってやっぱりありそうな気がするけど、あるんかな。どれくらい複雑なんだろう・・・?
  • エミュレータを初めて書く場合はファミコンより仕様がシンプルなハードから始めたほうがいい
    • 自分の場合は CHIP-8 のエミュレータを先に書いて、大体の技術スタックを決めました
    • CHIP-8 はめっちゃシンプルでした。音はサイン波出すだけだし ... (遠い目)

2022/08/01 追記

  • ToyNES から ChibiNES に改名しました

自分のブログ からの転記です

zenn に記事を集約しようと思い立って、こちらに書きました

Discussion

ログインするとコメントできます