LCDコントローラの制御法
for FX-890P/Z-1シリーズ


 Z-1シリーズ/FX-890P(以後Z-1と省略)でフルグラフィックのゲームを作成しようとした場合問題となるのが、いかにスピードを維持するかということでしょう。
 たしかにBIOSで提供されるグラフィック関係の処理ルーチンを利用すれば比較的簡単にグラフィックを表示することが出来ますが、ゲーム等に使用するにはあまりにも遅すぎますし、だいいちVRAM構造が複雑すぎます。
 そこで、これらの問題を一挙に解決する方法としてLCDコントローラ(以後LCDCと省略)を直接操作するという方法が上げられます。LCDCを操作出来ればLCDに直接データを送ることが出来ますし、何種類かある表示モードの中からその時に一番最適な表示モードを選ぶことが出来ます。
 ということで、これよりLCDCの操作方法等について説明していきたいと思います。
 なお、特に重要ではないと思われる箇所は省略しているのでご了承下さい。

サンプルプログラムです。

1.LCDCの操作の仕方

 Z-1に使用されているLCDCは日立のHD66108Tというものが使用されています。これを操作してLCDにデータを書き込むのですが、では実際にどのようにして操作するのかというとLCDCには内部に7つのレジスタが存在していて、これらを用いて操作します。
 これら内部レジスタはメインRAMにつながっていて、そのアドレスは

(1010 xxxx xxxx xxxx xxx0B):アドレスレジスタ
(1010 xxxx xxxx xxxx xxx1B):他のレジスタ

となっています。ここで、xは0でも1でも良いことを指しています。(例えば、アドレスレジスタはA0000HでもA0002Hでも同じです。)
 内部レジスタを読み書きするときは、まず「アドレスレジスタ」に

b7 b6 b5 b4 b3 b2 b1 b0
│ │ │ │ │ └─┴─┴─ レジスタ番号
│ │ │ └─┴─────── 未使用(0として下さい)
│ │ └─────────── DISP
│ └───────────── STBY
└─────────────── BUSY

DISP:LCDのオン/オフ (1-オン)

と設定してから「他のレジスタ」でデータを読み書きします。
 BUSYとSTBYは通常は使わないので説明は省略します。(0として下さい)

2.内部レジスタ

 各レジスタとレジスタ番号の対応は下記のようになっています。

0:DRAM(表示メモリ)
1:XAR(Xアドレス)
2:YAR(Yアドレス)
3:FCR(コントロール)
4:MDR(モード)
5:CSR(Cセレクト)

 これらのうち4番と5番についてはまず使うことはないと思われるので説明は省略します。

b7 b6 b5 b4 b3 b2 b1 b0
│ │ │ │ │ └─┴─┴─ DUTY(通常は101B)
│ │ │ └─┴─────── ROS (通常は10B)
│ │ └─────────── PON (通常は1B)
│ └───────────── WLS
└─────────────── INC

INC:アドレスインクリメント方向 (0-Y方向 、1-X方向)
WLS:ワード長セレクト (0-8ビット、1-6ビット)

PON,ROS,DUTYは通常は変更することはないと思われるので説明は省略します。(PON:1B、ROS:10B、DUTY:101Bとして下さい)

ちなみにZ-1の標準での動作モードは、

DISP:オン
INC:Y方向
WLS:6ビット

となっていますが、ゲームなどを作る場合は

DISP:オン
INC:X方向
WLS:8ビット

とした方がなにかと処理が簡単になります。
 これ以降は特に記述がないかぎりこの動作モードになっていると考えてください。

3.VRAM構造

 Z-1のLCDは画面の中央で右と左に別れているので注意が必要です。

 画面とアドレスの関係は、

(4,0) (5,0) 〜 (16,0) (4,32) 〜 (16,32) (17,32)
(4,1) (5,1) 〜 (16,1) (4,33) 〜 (16,33) (17,33)



(4,30) (5,30) 〜 (16,30) (4,62) 〜 (16,62) (17,62)
(4,31) (5,31) 〜 (16,31) (4,63) 〜 (16,63) (17,63)

となっているのですが、実際はこの範囲全てが画面に表示される訳ではなくて、一部画面には表示されない部分も存在しています。
 一番上のラインを例に、実際に画面に表示される範囲を示しますと、

このような関係になっています。
ここで「白」の部分は画面に表示されない所で、「赤」と「青」の部分が画面に表示される所です。
 見てわかるように、左右と中央に表示されない部分があり、さらに中央は左側のLCDと右側のLCDが半分ずつ重なっています。

4.具体的な使用例

 これまでLCDCに関する説明をしてきましたが、これだけでは何をどうしていいのかわからないと思われるので、ここでは具体的にLCDにグラフィックを出力するプログラムを例にとって説明したいと思います。

 ではまずこのファイルと共に収録されている「PRINT.ASM」を御覧下さい。
このプログラムはラベル「SCREEN」からの25*32バイトの仮想VRAMデータをLCDに送るサブルーチンです。
 これからこのプログラムの流れにそって説明していきます。

 まず初めにLCDCの動作モードの変更を行っていますが、こうやってLCDをアクセスするときだけ動作モードを切り替えてやれば文字表示などをBIOSを使って行うことが出来るので便利です。
 その次のPRLP1のループで実際にLCDにデータを書き込んでいるのですが、上で説明したようにLCDの右半分と左半分とではYアドレスが32だけずれていて、しかも中央では右と左がはんぶんずつ(4ビットずつ)重なっているので、右と左に別けて書き込んでいます。
PRSUBはSIレジスタで指定されたアドレスから13バイトのデータをLCDアドレスの(4,DL)〜(16,DL)に転送しています。PRSLP1のループで転送しているのですが、ここにあるスタック命令はウェイトを掛けるために使っています。これはDRAMレジスタにデータを書き込んでからLCDCが処理を終えるまで多少時間がかかるためです。
 最後に動作モードを標準に戻して終了します。なお、このときLCDCのレジスタ指定をDRAMレジスタにしておかないとBASICに戻ったとき不都合が起きます。

 このサブルーチンを使ったサンプルプログラムとして「STAR.ASM」を用意したので参考にして下さい。これは実行すると星が画面上を流れていきます。
(「2D-SHOT」の背景のスクロールと同じ動作原理です。)

5.キャラクターの表示方法

 上記のルーチンを使えばグラフィックを表示することが出来ますが、それだけではゲームを作ることは出来ません。そう、キャラクターの表示方法を知らなければだめです。
 ということで、どのようにして仮想VRAM上にキャラクターを表示するかというのを説明します。(ここで説明するのはキャラの大きさが8*8ドットの場合です。)

 キャラクターを表示するときに問題となるのがX座標です。Y座標を1ドット単位で動かすのは簡単ですが(アドレスを変えるだけ)、X座標は仮想VRAMの構造上1バイト=8ドットとなっているので、そのままではX方向だけ8ドット移動になってしまいます。
 ではどうするかというと、ビットシフトを行えばいいのです。
 具体的に言いますとX座標を8で割って答えをアドレスに加算し、あまりの分だけキャラクターデータを右シフトさせて、そのデータを仮想VRAMに書き込むのです。
 例を上げると、

★パターンデータ37Hを(21,3)に表示する。ただし、表示画面の大きさはX方向が25バイトで仮想VRAMは2000Hからとする。

21を8で割ると2あまり5なのでパターンデータを五つ右シフトさせる。

00110111 00000000

00000001 10111000

これをアドレス204DH(2000H+3*25+2)からOR命令で書き込む。

 以上のアルゴリズムをプログラム化したものが「CHRSET.ASM」です。
 また、これを使ったサンプルプログラムとして「MOVE.ASM」を用意しました。
これは実行するとキャラが画面内を勝手に動き回ります。

6.さいごに

 以上でLCDCに関する説明を終わります。
 ここに書いてあることがだいたい分かればフルグラフィックのゲームを作るのはそんなに難しいことではありません。
 なお、ここで紹介したプログラムはフリーソフトです。作者はこれに関する一切の権利を放棄していますので、改造やルーチンの転用など自由に行ってかまいません。
 書き忘れていましたが、サンプルプログラムはマシン語領域を500Hほど取って内蔵アセンブラでアセンブルしたあと、2000Hから実行してください。
[BRK]キー以外を押すと終了します。

7.参考文献

Z-1/FX-890P活用研究 工学社
ポケコンジャーナル'92 5月号 工学社
Z80マシン語秘伝の書 日高徹著 哲学出版
Z-1言語入門書「アセンブリ言語編」 CASIO

 

NIFTY-Serve YHW02344
村中 昭雄(STEAR)