なぜ"サイクル正確"エミュレーションが必要なのか
いわゆるエミュレータはサイクル正確(cycle-accurate)なエミュレータと、機能レベル(function/functional accurate)エミュレータの2つに大別できる。
ゲーム機のエミュレータは一般的に前者であり、Nintendo64やGameCube/Wiiエミュレータが例外的に後者に属する(内蔵DSPや周辺プロセサをエミュレートしない。コミュニティではHLEと呼ばれる。)。比べて、qemuや他のアーキテクチャエミュレータは後者が一般的と言える。
時間精度
サイクル正確なエミュレータは、全モジュールに共通した"エミュレーション時間"の概念があり、この時間の概念をどの程度厳密に管理するかが(とても)微妙な問題となる。
エミュレータの動作は、簡単には、
- CPUを1ステップエミュレーションする
- (実際のハードウェアにおける)1ステップの実行に掛かるはずの時間を算出する
- エミュレータ内の時間をその分進める
- 周辺チップの状態を更新する (★)
の繰り返しとなる。
エミュレータの時間精度は★の部分の更新をどの程度の頻度で行うかに依る。
例えば、いわゆる"ラスタスクロール効果"を再現するには、TV画面が1ラインを書くのに掛かる時間と同様の精度でエミュレーションを行う、つまり"ラインベースのエミュレーション"を行う必要がある*1。
通常の感覚で言えば、CPUのクロックは多すぎて困ることはない。PCのゲームなら、1GHzのCPUでも3GHzのCPUでも、フレームレートやその他画質等の違いはあっても、ゲームが正常に動作することには代わりはない。
しかし、ゲームコンソールにおいては重要な問題になりうる。そして、そのときどのような問題が起こるかというのが、そのまま、サイクル正確なエミュレーションの必要性になる。
時間は未定義動作を定義する
それなりの数のゲームプログラムは"偶然"動作しているに過ぎない。
プロセサの世界では、"変数に値を代入した後、値が反映されるのは2クロック後"のような現象が多々ある。他にも、プロセサの時間的なバグに依存したコードであったり、未定義値に依存したコードであることもある。
これらの未定義な動作を決定付けるのが"時間"であり、これを正確にエミュレーションする必要がある。