NESエミュレータのここまでの進捗

r7kamura/rnes の進捗について。

2018年11月2日

RubyでNESエミュレータをつくりはじめたのが2018年11月2日の夜。ROM のパーサから書き始めて、CPU、CPU バス、PPU、PPU バス、ターミナルでの画面描画用のレンダラーの順で実装を進めていくことに。

2018年11月3日

つくりはじめてから16時間ぐらいコードを書いて、ようやく HELLO, WORLD! を表示できるように。実行速度が気になるので fps を測ってみたところ…… 3fps……そんな……。この HELLO, WORLD! は、NES 研究室 という Web サイトが公開してくれている NES 用のありがたいサンプル ROM で描画されたもの。

2018年11月5日

前日までは背景描画しか実装されていなかったので、ここでスプライトの描画を実装。NES の画面は二つのレイヤーで管理されていて、8×8 ピクセルで画面上に敷き詰められる背景のレイヤーと、同じく 8x8 ピクセル (8×16 にすることも出来る) で画面上の任意の位置に配置できるスプライトのレイヤーが存在する。その内の後者のレイヤーを描画する仕組みの実装をはじめたという話。もしこの辺りの NES の仕組みの話に需要があれば、一段落ついたらブログにでもまとめようかと思っている。

この日の成果として、ギコ猫でもわかるファミコンプログラミング という Web サイトで公開されている、1つのスプライトデータを画面左上付近に描画する ROM が動くようになった。

2018年11月6日

ターミナル上で動かしているので、標準入力からキーボード入力を取れるだろうと思い、WASD で上下左右に動くためのキーパッドを実装した。しかし改行を入力するまでターミナルが入力を受け付けてくれないので、 S → Enter や D → Enter みたいな入力を強いられるつらい仕様に。

2018年11月7日

nestest という、NES エミュレータ実装界隈で重宝されている CPU テスト用の ROM があるものの、そもそもこの ROM のデータを画面に描画するための実装が足りていない。しかし nestest を正しい実装で動かしたときのログデータが公開されているため、自分の NES エミュレータにもそれと同じ形式でログを出力する機能を実装し、結果を突き合わして不具合を探していくことに。

突き合わせてみると不具合だらけで、酷いものだとビットをマスクするための「value & 0xFF」というコードが誤って「value && 0xFF」となっていたりした。CPU 命令の実装では、計算結果が負の値だったらレジスタの negative ビットを操作したりというところが上手く実装されていない、という不具合が多かった。

2018年11月8日

背景描画をスクロールに対応させたり、DMA 転送という WRAM から VRAM に高速にデータを転送する仕組みを実装したりと色々やった結果、『ギコ猫でもわかるファミコンプログラミング』の縦スクロールのレースゲームがそれらしく描画されるように。ただ、道路上に表示されるはずのスプライトが表示されていなくて不安が募る。

2018年11月9日

それなりに動くようになってきたので、RubyでNESエミュレータをつくりはじめた話を投稿。

2018年11月10日

nestest が画面に映るようになり、既にログと突き合わせて不具合修正をがんばっていたので、無事全てのテストに成功していることが確認できた。しかし画面描画周りに不具合があるのか、アスタリスクの記号の位置がずれているのが気になる。

2018年11月11日

nesdev という NES エミュレータの膨大な情報をまとめたありがたい Wiki があり、前述した nestest もそこで紹介されていたものなのだけど、nesdev では nestest 以外のテスト用 ROM も紹介されているので、これを動かして不具合を探していくことに。「このアドレスに対する読み書き時のミラーリングが上手く実装されていないよ」ということが分かるような ROM が提供されていたりして、本当にありがたい。

2018年11月12日

吸い出したスーパーマリオブロスの ROM がようやく少し動くように。しかしマリオはよく分からない状態になっているし、背景も描画されていない箇所がそこそこあるしで、完動までまだまだ先は長そう。ちなみに、UNIX の端末を設定するための stty というコマンドを調べた結果、改行を入力しなくてもキーパッドを操作できるようになるなど、微妙な改善も加えられた。

※下の画像はアニメーション GIF になっているけど、容量が大きいせいで環境によってはループしないようになっているので、画像単体で表示すると動くようになるはず。

つづく

以上、ここまで10日間程度の進捗報告でした。