Open5

Writing NES Emulator in Rustをやってみる

Wagomu056Wagomu056

チャプター5-1

無限ループ

nestest.nesを実行してみると無限ループに。。
デバッガでprogram_counterを見ると0xc004から開始していた。
nestest.logを確認すると0xc000から開始していないとおかしいようだ。

reset時のprogram_counterの読み込みに失敗している?

nestest.nesのバイナリを確認すると、0x3ffc-0x3ffdに0xc004が入っている。
正しく読み込めているようだ。

$ od -tx1z -Ax nestest.nes | less
003fb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004000 00 00 00 00 00 00 00 00 00 00 af c5 04 c0 f4 c5  >................<
004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004030 80 80 ff 80 80 00 00 00 80 80 ff 80 80 00 00 00  >................<
  • 0x3ffcなのは0xfffc - 0x8000 - 0x4000された結果
  • odでは0x3ffcではなく0x400cに0xc004が入っているように見えるが、これはnesファイルのヘッダ分、アドレスに+0x0010されているため

main.rsでprogram_counterを指定していた

https://github.com/bugzmanov/nes_ebook/blob/785b9ed8b803d9f4bd51274f4d0c68c14a1b3a8b/code/ch5.1/src/main.rs#L45-L48
これはnestestの仕様で、PPU実装していない場合は0xc000にするものらしい。

Start execution at $C000 and compare execution with a known good log

https://www.nesdev.org/wiki/Emulator_tests

チャプター4まではこのようなprogram_counterの強制上書きは無いので注意。

Wagomu056Wagomu056

チャプター5-1

RORのキャリーフラグが正しくない?

mynes.logとnestest_no_cycle.logの差分をとると、メインページに書かれているのと違う箇所で差分が発生していた。

$ diff -y -W 155 mynes.log nestest_no_cycle.log | less
CF51  6A        ROR A                           A:01 X:55 Y:69 P:65 SP:FB       CF51  6A        ROR A                           A:01 X:55 Y:69 P:65 SP:FB
CF52  90 1E     BCC $CF72                       A:80 X:55 Y:69 P:E4 SP:FB    |  CF52  90 1E     BCC $CF72                       A:80 X:55 Y:69 P:E5 SP:FB

0xcf52のP(status)の値が違う。本来はE5だが、E4になってしまっている。
これは、キャリーフラグが立っていないということ。
ログはそれぞれ命令実行時のものなので、実行結果としてのフラグの変化は次のログに反映されている。
つまり、RORで正しくキャリーフラグが立っていない。

RORのキャリーフラグを立てる処理が間違っていた

ROLのキャリーフラグを立てる処理をそのままRORにコピーしてしまっていた。
ROLは対象の7ビット目がキャリーフラグを立てるかどうかに関係するが、RORは0ビット目だった。
https://github.com/Wagomu056/NES_Emulator/commit/d73eb9f9fdd63f1688707d693b94536050eb0e82#diff-16ea746418d0dc9dedc450d269604162d29fa755f5eeb5157eaaf8b5343d7064R584