FC『麻雀』がFCEUXで正しくエミュレートされない件 その2

TASVideosのフォーラムにも書きましたが、もしかしたら原因がわかったかもしれません。

前回はトレースログを見ても原因がさっぱりわからなかったのですが、FCEUXの ppu.cpp を眺めていたらスプライトDMAにかかる時間が512CPUクロックであることに気付きました。NesDevWikiによると:

This takes 513 cycles to copy 256 bytes from this memory into $2004

とのことなので、1CPUクロック足りないことになります。これが原因で他の命令が余分に実行されているのではないかと考え、スプライトDMAで513CPUクロック消費するパッチを書いてみました。するとニューファミコンと同じ配牌が得られるようになりました。ただ私はNESのハードウェアに詳しいわけではないので、このパッチが正しいのかどうかはよくわかりません。

パッチとバイナリをアップしておきます:

ただしこのパッチは消費クロック数を変更するので、今度は他のゲームでdesyncが発生する可能性もあります。ということで、TASVideosのいくつかのムービーについて検証してみました。以下のムービーはパッチ版でもdesyncしません:

しかし、以下のムービーはパッチ版だとdesyncします:

一般的に、「クロック依存な」ムービーほどdesyncしやすいといえそうです。ロックマン1は(クロック的な意味で)非常にシビアなタイミングのバグ技を使っており*1、またWizardryシリーズと麻雀は乱数がクロックに依存しています。クロック依存乱数はそこそこ広く使われていると思われるので、探せば他にもdesyncするムービーが見つかるかもしれません。

もし本当にスプライトDMAの実装が誤っているとしたら、その問題の取り扱いについて若干の議論を要するだろうと思いますが、とりあえずは上記のパッチが正しいのかどうか(正しくないならどこに問題があるのか)を知りたいところです。詳しい方がいたら教えていただけるとうれしいです><

*1:ロックマン2もdesyncするのかなと思いましたが、1に比べると若干余裕があったようで大丈夫みたいです