PCEエミュレータの実行速度を速くしたい

PCEエミュレータの実行速度を速くしたい。


どんなゲームでも普通、V-Blankとの同期をとって動作している。
つまり1/60秒の周期でウエイトを入れて、一定の速度でゲームが進行するようにしているわけだ。


PCエンジンのような昔のゲーム機は、マルチタスクでソフトが動いていないので、タイミング待ちのウエイトはビジーループで待つのが普通だ。


ジーループというのは、ループ以外になにもしない無限ループのことである。


1/60秒に相当するPCエンジンのCPUクロック時間ごとに、ほぼ必ずビジーループが存在し、現状ではこれも忠実にエミュレーションしていることになる。


ちなみにPCエンジンのCPUはHuC6280という名前である。


ゲームの重さによりけりだが、例えばHuC6280のCPUパワーの8割を使っているゲームがあるとしよう。
その場合、残り2割のCPUパワーは、ビジーループでぐるぐるとなにもしないループを回すことに使われている。

エミュレータの場合、これを忠実にエミュレーションするのはとても無駄なCPUパワーを使ってしまう。


エミュレータではCPU以外にもグラフィックスや音源のエミュレーションを実行しなければならない。
ジーループで暇潰ししてないで、CPU以外のハードウェアをエミュレーションする処理にさっさと移ることができれば理想的だ。


そのためには、V-Blank待ちのビジーループに入ったことを何らかの方法で検出して、そのビジーループを除去してやる必要がある。


V-Blank待ちのビジーループを検出するのはちょっとむずかしい。
確率的には、V-Blankが発生した瞬間に実行していたコードは、V-Blank待ちのビジーループである可能性が高い。

しかし、処理落ちしていた場合とか、初期設定時とか、場面遷移時などの場合は、上に該当しない。


なのでV-Blank待ちのビジーループを確実に検出することは難しい。


V-Blankの瞬間に実行していたコードが、前方へ戻る分岐命令かつ、そのコードがV-Blankの瞬間にかなりの割合で実行されていたら、これはV-Blank待ちのビジーループである、とたぶん言える。
そんな統計的な方法で検出するしかないと思われる。


そのコードを、適当な未定義命令に置き換えておき、その未定義命令をV-Blank待ちに入ったことを示すハンドラとして使うことを検討している。


ジーループと思われる部分のコードを、エミュレータ側で強引に書き換えてしまうわけだ。
かなりアグレッシブというか、一歩間違うと動かなくなってしまうような最適化だ。


HuC6280の未定義命令は22種類ある。
そのうち1つをハンドラとして使う。

具体的には、未定義のOpcodeは以下の通りである。
$0B, $1B, $2B, $33, $3B, $4B, $5B, $5C, $63, $6B, $7B, $8B, $9B, $AB, $BB, $CB, $DB, $DC, $E2, $EB, $FB, $FC


さて、うまくいくだろうか。