多分もう気づいていると思いますが、前回の書き込みはバブルボブルのカスタムMCUです。
バブルボブルと言えば一番メジャーな部類で、MAMEでもすでに何年も前からサポートされていますが、MCUのオリジナルROMが無かったため、エミュレーション動作は完全ではありませんでした。
一時期、海賊版の基板に載っていた68705のプログラムがオリジナルから取り出されたものと思われていた頃がありました。しかし、モンスターの動きが違い、クロックアイテムの動作も間違ってました。
プログラムと基板回路を詳しく調べたところ、オリジナルのMCUは68705とは全く異なり(ピンアウトが合いません)、68701ではないかと予想されていました。68705のプログラムは、ブラックボックスリバースエンジニアリングテクニックを使ったもので、オリジナルのMCUを動作させ、メモリからのリード・ライトを記録することで海賊版屋がゼロから書いたものでした。オリジナルのMCUはメモリから読み込みを行い、それに対して何らかの処理をしていたので、この68705プログラムも何もしなくても意味のないメモリ読み込みを多く行います。
このプログラムがエミュレータ内で次第にシミュレーションコードに置き換えられていくに従って、エミュレーション精度も大きく向上しました。モンスターの動作は改善され、クロックアイテムの動作も修正されました。しかし、それでもEXTENDバブルのランダム発生の仕組みなど、いくつかの謎が残っていました。
そしてついに今回、Trinity氏がオリジナルのMCU ROMを取り出すことに成功しました。チップのパッケージを溶かし、顕微鏡で写真を撮って、ROMの内容を手作業で1bitずつ解読する作業を行いました。先日の書き込みにある写真は、MCUが以前に推測された68701ではなく、6801クラスの6801U4であることを示しています。
このROMにより、100%完璧なエミュレーションに必要なパズルの最後のピースをついに入手しました。
オリジナルMCUプログラムの解析はとても興味深いものです。ゲームでは次第に使用されなくなった、以下のような、多くのプロテクト機能を提供するようにデザインされています:
- コイン入力とクレジットカウンタの処理
- 両プレイヤーの残ライフの操作
- 現在プレイ中の面数の操作
- 4つ変数を異なった速度で増加
- ランダムデータと思われる1280バイトから値を返す
このような機能が使われなくなった理由はおそらくいろいろあるでしょう。ひとつは、MCUがデータ処理をするには1フレーム必要なので、単にあまりよいやり方ではないということ。他には、MCUでハードコードしてしまうと、コインエイジの変更が柔軟に行えないなどなどです。
次に、これまでのシミュレーションが実物にどれくらい近かったかを見てみましょう。答えは本物にきわめて近く、逆に「出来すぎ」でした。理由を見てみます。
まず、クロックアイテムの動作は正確でしたが、1フレームずれていました(シミュレーションでは1フレーム遅れが起きていた)。
EXTEND泡のランダム化はオリジナルのMCUには存在していません。しかし、シミュレーションコードは乱数生成器を使い、完全にランダムな文字を生成していました。ところが、オリジナルMCUでは単純に1フレーム毎にカウンタを増やすだけです。これにより、EXTENDの出現が予想できるようになるので、ゲームプレイへの影響は重大です。新しい泡は、128フレーム毎に画面に入って来て、128/6の余りは2なので、次に出現するのは2つずれた文字になります。E→T→N、またはX→E→Dの順序で、その後繰り返します。ただし例外があって、新しい泡が画面に入ってくるのと全く同じフレームで泡をはくと、この泡は1フレーム遅れます。そのために、ボタンのタイミングをぴったり正確にすれば、泡の出現順序を変更でき、理論的にはひとつの面で6文字全てを集めることも可能なはずです。また、画面にすでに16個の泡があるときは新しい泡は現れませんが、これも泡の順序を変更します。
最後に、これが一番重要ですが、モンスターとプレイヤーの座標位置の比較です。比較結果は、>、=、<を示すフラグと、絶対的な距離で返されます。これはシミュレーションでも正しく行われていたのですが、オリジナルのMCUにはバグがあります。プレイヤーとモンスターの接触を調べる部分があり、接触のフラグとどのモンスターと接触したのかを返す部分のコードが正しく動作していません。プレイヤーのY座標と、あるモンスターのY座標が同じで、さらにプレイヤーのX座標と別なモンスターのX座標が同じときでもフラグを設定してしまうのです。
メインプログラムの方でこのフラグを無視するようにしているので大きな問題はなく、2つ目のZ80が実際の正確な当たり判定をしています。しかし、プレイヤーのX軸位置から8ピクセル内にモンスターがいると、MCUの方もすぐに処理を完全停止してしまうので、例えば、3段真上にモンスターがいたとして、そのモンスターがリストの最初にある場合、他のモンスターはプレイヤーを追いかけるのを止めてしまいます。これはとても微妙で、個人的には全然気づかなかったのですが、理論的にはこのような動作をしています。