Z80 ゲーム機を作ろう(その9)
今回は,週末に作業を集中して行ったので,いつもより更新が早くできました。
さて,前回は,スプライトのキャラクタージェネレータ ROM から,スプライトの 1 ライン分のパターンデータを取り出すところまで作りました。
結局,スプライト機能の基板は 3 枚になってしまいましたが,3 枚揃って,スプライトが画面に表示できるようになります。今回は,残っていたスプライトのラインバッファ周りの基板を作ります。
ラインバッファって?
昨今の PC などは,ダブルバッファになっているフレームバッファと呼ばれるものに描画し,垂直同期に合わせてフリップする…と言うことは,ゲームプログラムの文献などでよく見たりしますよね。
フレームバッファはフレーム単位で画面情報を書き込むバッファです(…よね?)。
1 画面分の情報を書き込んだら,それを画面に反映します。
これに対し,ラインバッファは,ライン単位で画面情報を書き込むバッファですので,1 ライン毎にその内容を画面に反映します。書き込み単位が短いだけで,行うことは似ているんですね。
また,フレームバッファは,書き込んだあとに画面に反映する(バッファをフリップする)タイミングは,ソフトウェアで制御できるのが一般的です。
ですので,画面にたくさん表示したければ,時間をかけて描画し,フリップのタイミングを遅らせると,たくさん表示することはできます。
ただ,その結果,画面の更新頻度が低くなり,「処理落ち」とか「フレーム落ち」とか,「FPS が低い」と言った状態になってしまいます。
今回作るラインバッファは,このフリップするタイミングが,ハードウェアによって水平帰線タイミングで行われます。
「フレーム落ち」みたいに「ライン落ち」をしたら,画面の一部が崩れてしまいますので,必ず一定のタイミングで画面に反映する必要があります。
こういった理由から,表示できる枚数が限定されてしまうんですね。
その反面,1 ライン分のメモリがあれば良いので,フレームバッファに比べて,メモリは少なく済みます。
では,枚数をより多く表示するにはどうすれば良いかというと,処理するクロック数を上げて,読み書きの速いメモリを使用すれば良いのです。…って当たり前か。
ラインバッファ読み書きの流れ
1 ライン分のバッファなので,その容量は,横ドット数分になります。
前回作った基板で,スプライトの,横 16 ドット分のデータが順次送られてきますので,これを書き込む直前に,スプライトメモリから水平位置を取得して,カウンタにロードします。
このカウンタが,ラインバッファの書き込みアドレスになり,左から右へ 16 ドット分書き込まれていきます。
もちろん透明色は書き込みスルーします。これを最大 16 枚分繰り返します。
また,これと同時に,もう一方のバッファには一つ前のラインで情報が書き込まれていますので,ドットクロックに合わせてバッファの左端から右端に向かって読み出します。
1 ドット分読みだしたら,次回の書き込みに備えて,その場所をクリアしておきます。
これと同じタイミングで,BG からも表示データが出力されていますので,これらを表示優先順にしたがって選択し,一番上になるドットデータが最終的にモニターに送られることになるんですね。(この時代の大抵のゲームは,BG よりスプライトの表示優先順位が高いものが多かった気がします)
ラインバッファ基板
今回作った基板がこちらです。
なんか,コネクタが増えてきましたね…。
ダブルバッファの切り替えをするので,マルチプレクサが数個あります。
Z80 と接続
いつものように,階数が増えて 8 階建てになりました。持ち上げると,結構重いです(笑)。
そして,スプライトが表示できるようになりましたので,簡単なテストプログラムを作りました。BG との合成が,まだできないのと,パレット機能がないので,表示としてはまだ寂しいですが,BG と違って,それぞれをドット単位に動かすことができます。
(MPEG-4,750kbps,5.6MB)
全表示枚数は 32 枚で,MSX と同じ程度ですが,同一ラインに 16 枚まで表示できます。
さて,あとは BG とスプライトを重ねて,パレット変換して表示できれば,ゲーム機っぽくなると思います。何となく完成が見えてきました!
まだ,スクロール BG も残っていますが,次回は,BG とスプライトの重ね合わせと,これらの表示プライオリティを制御する基板を作ってみたいと思います。
基板の枚数が増えてきたので,全体的な安定性がチョット不安ですが,まぁ,気楽にやっていきます。