概要
以前、JSで書いた(ファミコンのエミュレータを書いた - undefined)ファミコンのエミュレータをRustで書き直してみた。
また、技術的な内容はQiitaの方にも書いているので興味のある方は参照してみてください。(まだ Hello, World!
までしか書けてませんが。)
もともとファミコンのエミュレータって新しい言語を習得するのにちょうどいい題材だったりするのでは、って話しからスタートしてて、よくわからないのでJSで書いてみて、ようやくRustで一通りは実装できた感じ。まだバグや未実装(音声周りやマッパー)も多いんですが、ひとまずはお腹いっぱいな感じ。
成果物
あと、いくつかのROMは以下で遊べるようにしてます。音が出るので注意してください。 またAPUの実装にまだバグが残っているのDCMチャンネルが未実装なので音が変だったり出てなかったりします。 描画のほうはマッパー0であれば、ほぼほぼ問題ないと思ってます。
また、現状chromeでのみ動きます。firefoxは(多分)esmodulesのフラグを立てれば動きます。
https://bokuweb.github.io/rustynes/
CPUやPPUやRAM / ROM周りをRustで書いて、描画や音はemscriptenを介してJS側でcanvas / WebAudioのAPIを叩くようにしています。
これに着手し始めたときは、wasm32-unknown-emscripten
しか選択肢がなかったのですが、今なら、wasm32-unknown-unknown
が選択できます。
今から着手するなら、wasm32-unknown-unknown
前提で、stdweb
かwasm-bindgen
辺りを使用しemscriptenを剥がしたほうが良い面が多いような気がします。
過程
移植するだけなので強くてニューゲーム気分だったんですが、駄目ですね。 前回よりわけの分からない状態は減ったものの、それでもおかしなバグには遭遇しました。
Hello world
ここまでは、とにかくコンパイラに怒られまくったりどうやってブラウザで描画するのがいいのか悩んだりで大変でした。Qiitaかどこかにも書きましたがHello, World!
を表示するにはCPUがほぼほぼ実装できていないといけないのでやはりここまでは苦労しますね。
GIKO005
スプライトを表示するサンプル。Hello, Worldからここまではすんなり。
GIKO016
スクロールが絡んでくるとやはりよくわからないこと現象に遭遇する
GIKO017
前回対応していなかった8 * 16形式のスプライトに対応した、が、ばぐってて歩く度に顔が上下するキャラクターが産まれてしまった。
Super mario bros
さすがにハマりどこは抑えてたので着手後早い段階でそこそこ描画されてた。
思わぬところがスクロール
隠しブロックが隠れてない
土管が仕事しない
音の伸びが良すぎる このバグまだ解決できてなくて、地下でブロック叩いたときになんとも言えない音が鳴る
falling
今回見つけた謎のROM。ひたすらおっさん(?)が落ちていくゲーム。 実はオープンソースで、initial commitが2018年の1月7日になっている。
つまり2018年産まれのファミコンROMということになる。タイトルの音楽が好きだったりする(ちょっとAPUの実装の都合でおかしいとこありますが)
速度
WebAssemblyというと速度が気になると思います。JS版との比較を行ってみました。
WebAudio周辺は共通かつJSは側の処理なので比較はAPUをディセーブルにして、giko017.nes
でメインループの処理時間20回分の平均値を取っています。マシンはMacBook Air (11-inch, Early 2015)
, 1.6 GHz Intel Core i5
, 8 GB 1600 MHz DDR3
。
ブラウザ | JS版 | Wasm版 |
---|---|---|
Chrome 63 | 4.36ms | 5.68ms |
Firefox 58 | 5.76ms | 3.98ms |
Safari 11 | 9.98ms | 4.21ms |
Firefox, Safariではwasmのほうが速かったんですが、chromeではJS版の方が速くwasm版はイマイチでした。emscriptenのグルーコードのオーバーヘッドやrust / wasm周りに不備、チューニング不足も当然あるでしょうが、firefoxでそこそこ速いこと考えると、v8すごいって話しとchrome x wasmはまだまだってことになるんでしょうか。このあたり正直なところよくわかってないです。
さいごに
まだ未実装箇所やバグも多いんですが、お腹いっぱいなのでひとまずここまでにして、何か次に取り掛かりたいなーという思い。 一応Rustで書いたものの、分からないことだらけでもう少し、いろいろ書いてみないとなーという気持ち。
なにかおかしなことしてたらプルリクエストなどいただけると泣いて喜びます
題材としては、以前お世話になったARM7のエミュレータを書いてみるとか、ラズパイにOSを移植してみるとかが楽しそうだなーと思いつつ、goも勉強したいので時間はかかりそうです。