以前のバージョン(以降「Ver.1」と書きます)
と大きく異なるのは、スクロール方式です。
これにより、描画処理ルーチンを全て変更しなければならなくなりました。
(1) 描画プレーン概略
Ver.1の描画プレーン概略
スクロールプレーンは、Gプレーンのみで、キャラクタは2プレーン描画でした。
(詳細はこちら)
Ver.2の描画プレーン概略
スクロール背景、キャラクタ共にB,G,Rプレーンの3プレーン描画をしています。
Ver.2はCRTCのスタートアドレスを変化させる事による、ハードウェア的スクロールになるので、3プレーン描画であっても (上部の1ライン(8ドット)だけの描画にすぎないので) 速度的に不利になるどころか、「スクロールをさせる”だけ”」ならば、圧倒的な高速動作が実現出来ます。
(「スクロールさせる”だけ”」ならば・・・です。キャラ描画・消去は処理コストアップなので、全般的にはトントンと言った所でしょうか。)
なお、スクロ−ル背景のマップチップは2プレーン分のデータしか持っていませんが、Bプレーンに$FF (全てのBitが1)
を描いています。
マップチップのデータは2プレーンですので、4色対応となりました。
Ver.1は、描画位置の制約がある(擬似?)4色でした。
(2) 表示可能色について
Ver.1ではキャラクタ描画においては、以下の通り表示可能色は6色でしたが、”まともに”描画できるのは、黒と白だけでした。
※グレー箇所は描画不可能
Ver.2において、Bプレーンがオン(1)の箇所はスクロール背景色です。
カラーコード
1,3,5,7がスクロール背景色です。
パレット機能にて、順にカラー****としています。
Ver.2において、Bプレーンがオフ (0)
の箇所がキャラクタ色です。
カラーコード 0,2,4,6がキャラクタ色です。
パレット機能にて、順にカラー****としています。
これによりVer.2では、キャラクタも4色(スクロール背景とは別の色)が自由に描画出来るようになりました。
緑(4)が使えなくなりましたが、赤(2)が自在に使えるようになったのは大きなメリットです。
当然ながら、(自在に描画できる分)処理速度とはトレードオフになってしまいます。
なお、キャラクタデータは2プレーン分+マスクデータしか持たせていませんが、3プレーン描画なのです。
描画時には、GとRプレーンにおいてVRAMデータ値をマスクデータでANDし、(穴を開けてから) その値と描画データとをORします。
これは、ごくごく普通の「重ね合せ処理」です。 (詳細はこちらに記載してあります)
さらに、Bプレーンは、マスクデータ値をそのまま書き込みます。
キャラクタ描画する箇所に穴を開けるという表現が分かり易いでしょうか。
これらの処理は、次に表示する画面に描画を行い、全ての描画処理が完了したら、その画面を表示させるようにします。
これにより、画面のちらつきは無くなります。
前章で書きましたが、スタートアドレスによって、ループバック処理の有無が異なります。
描画処理もループバック処理の有無の区別を付けて処理低減を図っています。
(3) キャラクタ描画後の消去(マップチップを描画して上書き)
キャラクタ描画の際に、8ドット単位でどこに描画させたかを記録 (以降「描画位置記録」と書きます) しておきます。
「今」の描画位置記録と「1ループ前」の描画位置記録を保持しておきます。必要なメモリ容量は、横20×縦25×2
=
1000Byteです。
以下【図1】をテーブル化しており、それに基づき描画位置記録に対し値を代入していきます。
※以下の図はサイズが10ドットのキャラクタ用です。20ドット用、3ドット用、アンドアジェネシス用のテーブルもあります。
代入する値
【図1】
【図1】の赤枠はマップチップの描画位置を示しています。
画面(1〜4)において、マップチップの描画先は2ドットづつずれているので、マップチップ描画をどの位置で行うのかをテーブル化しているのです。
描画位置記録の開始アドレス
+ Int(y座標 / 8) * 20 + x座標 が記録開始アドレスになります。
例えば画面1において、y座標 Mod 8
(剰余)が0の場合は以下の通りです。
※【蛇足?】上述のy座標はBit
0をリセットしており、偶数値となっています。
実際にはy座標は1ドット単位でキャラクタ描画を行っているですが、テーブル容量の削減の為、丸めてあるのです。
【図1】を見てもらえるとキャラクタ描画(■)が縦方向に11個ある事が分かると思います。
これは、キャラクタ描画のy座標が奇数値にも対応するように1ドット多く消すようにしているのです。
・記録開始アドレスに「3」を代入
(上記のテーブルは10ドットキャラクタの場合なので)
・記録開始アドレス + 1
(8ドット右の位置)のも「3」を代入
・記録開始アドレス + 20
(8ドット下の位置)に「1」を代入します。
・・・代入と書きましたが、正確に書くと以下の通り、既に記録済の描画位置記録の情報とORします。
・マップチップ上部4ドットを描画の場合、値1でORする
・マップチップ下部4ドットを描画の場合、値2でORする
・マップチップ全部8ドットを描画の場合、値3でORする
ORをする事により、複数のキャラクタが重なって描画された時に対応できます。
※【蛇足?】 【図1】を見ると、描画しなくてもよい(消去しなくてもよい)マップチップを描画する事になってしまっています。
(もっとテーブルを細分化すれば無駄は省けますが、メモリとのトレードオフですね)
Ver.2はCRTC設定によるスクロール方式なので、固定の地上キャラに関してはマップチップ描画による消去は必要はありません。
なぜなら、それらは下に動いているように見えますが描画開始VRAMアドレスに変化は無いからです。
(Ver.1はスクロールに併せてキャラを2ドットづつ下に移動させていたので、キャラ上部はマップチップ描画にて消去する必要がありました)
ですから、固定の地上キャラにおいては、「前項(3)キャラクタ描画後の消去」の処理は省いています。
また、描画位置記録は(8ドット単位で)横20×縦25を確保しておりますが、プレイ画面は横18×縦23です。縦1行目と25行目、横1列目と19列目はマスクされており表示されてませんので、その位置にある描画位置記録は無視してマップチップを描画させる必要はありません。
逆に処理コストの増大は「アンドアジェネシス」です。
登場してからの多くの時間は「浮遊」(画面上では止まっている)です。
止まっているように見えてCRTCスクロール方式では、常に描画開始VRAMアドレスは変化してしまいますので、常に下部8ドットを(背景を描画して)消去しなければなりません。
もちろん、描画したアンドアジェネシスを(次の処理で)全てを消去する必要はありません。
4ループ先(4画面先)でも、消去した箇所を再度「アンドアジェネシス」で上書きしてしまう箇所が多く発生するからです。
その上書き箇所は「描画位置記録」に対し、8ドット単位で描画”しなくても良い箇所”を記録しておきます。
※手法は「前項(3)キャラクタ描画後の消去」に準じています。
・マップチップ全部8ドットを描画しない場合とし、値4でORする
描画位置記録データのbit
2が1の場合(4以上の場合)は、マップチップを描画しないようにしています。
なお、アンドアジェネシスの動作
(登場時・浮遊時・上に退去時・下に移動)により、マップチップ描画を「する箇所」と「しなくても良い箇所」が異なります。
動作に併せた消去箇所テーブルを準備して、適切な場所にマップチップ描画をするようにしています。