ファミコンエミュレータを写経してみるお話2【PPU】
前回
やること
前回は初歩として、CPU
の実装を行い、参考サイトを元に一通りの必要と思われる命令を網羅的に実装しました。まだファミコンをエミュレートする際に必要な実装がかけているかもしれませんが、その場合は後々修正していこうと思っています。
LogiClover vol.1
を読んでいると、CPU
の次にPPU
を実装しています。これは、ファミコンの描画を司る部分だそうで、CPU
により間接的に制御されているとのこと。今回は制御をする機構はなるべく後回しに、PPU
のスタンドアロンなトコから実装していけたらなと思ってます。
参考にするもの
- コード周りはこちらのコードを観させてもらおうと思います。また
Rust
の書き方の勉強としても頼りにさせてもらいます。 github.com
ファミコンエミュレータの創り方 - Speaker Deck
- こちらに有志の皆さんが
NES
の情報をまとめて下さっているので、利用させてもらいます。特に、コードを写経しているだけでは意味がないので、まずこちらを見て自分で実装を考えます。
- こちらの本も参考にさせてもらいます。1つ目のリンクの方の実装と見比べる事で、実装にマストな部分を見出すために使いました。また、こちらの方の実装順番も参考にしてます。
読み始める前に
- ファミコンの仕様についてはネット上にたくさん情報が上がっているので、ここでは詳しい事は書かないです。(自分も分からない)用語の説明もほとんどしていません。 しかし、実装手順の再現性があるサイトは個人的に少ないなと感じたので、自分の試行錯誤をここにまとめて、うまく踏み台にしてもらえたらなと考えています。言語は
Rust
を使っており参考サイトもRust
が中心のものが多いです。 - また、解説力も乏しいので、適宜実装が完了したと思われる
commit
にジャンプできるGithub
のリンクをそれぞれに置いておくので、そこからコミット履歴などを参照していただいてもらう形にします。申し訳ないです。
レジスタ
前回のCPU
同様、レジスタ周りから作り始めるのが良さそうです。ということで、コード参考のリポジトリを確認すると、どうやらRAM
の実装とOAM
やPPU_ADDR
などを別途細かく分けて実装していること、またそれらにRAM
の実装が必要なことが分かったので同時にやってしまいます。RAM
の実装は、いろんな箇所で使いまわせるような実装になっていました。Register
の入出力周りのベースを実装したのがこのコミットです。
現状ここの実装が分からなかったので、修正しました。今後の動きによっては元に戻そうと思います。 https://github.com/196Ikuchil/nes_emulator/commit/5c3f2690437d9552b7af515fb047210fc8aaa309#r37678779
PPU
レジスタが動きそうなので、これを利用してPPU
の動きをエミュレートしていきます。まず描画する背景、スプライトを生成できるようにしようと思います。参考書籍より、タイルが最小構成要素だと思ったのですが、参考実装ではsprite_utils.rs
のSprite
という構造体がおそらく最小要素になっている(タイル・スプライトの共通要素をここで定義)ので、そこから作ります。
注意点として以下があります。
- 8*16のスプライトに対応済みとのことなのでそのまま実装する
Mapper3
に対応済みとのことだが、現状不必要なので実装しない
PPU
を呼び出せる部分まで実装しました。これをフレームごとに呼び出して画面を作っていくイメージです。リンクはPPU
メイン実装時のコミットですが、パーツごとになんとなくコミットを分けているのでそちらも実装順の参考になるかもです。
run
させることで、そのフレームで必要な背景とスプライトを一通り生成するはずです。
DMA
CPU
を介さずに直接RAM
へデータを読み込む機構を実装します。詳しくはこのスライドに紹介されています。
ファミコンエミュレータの創り方 - Speaker Deck
これも機能のみ実装しておきます。
後々に、Bus
で0x4014
番地に書き込みがあった場合にDMA
による転送が有効になるように仕込みますが、現状は実装されていません。
積み残し
今回は最低限PPU
の機能として必要そうな部分のみの実装を行いました。テストコードをサボってしまい少ない分、しっかり動くかまだ未知数ですが、切りがいいので続きは次回に回します。次回は前回のCPU
と合わせてテストROM
を動かせるようにして、今回の分のデバッグも行いたいと考えています。
追記
修正が加わっているので、PPU
あたりの該当コードは直しておいてください。後々修正する記事で同じリンクが登場するので今じゃなくても大丈夫です。
github.com
github.com
ここではspriteに修正に入っています。
github.com
またここでは画面のスクロールに修正が入っています。