SHARP PC-1600KでLCDを直接制御して描画!

先日「Bad Apple!!リベンジ版」を投稿した。

 

ポケコンの画面でBad Apple!!がリアルタイムで動くというのは結構な驚きだったようだ(^^) メモリの方はズルしちゃった感が強いけれども!!

 

そんな中、「PC-1600KでLCDCへのアクセス方法を知りたい」というお声があった。そういえば過去に調べてみたけど資料があんまりなく、独自でROMを解析したんだった。

ネットでも見たことが無かったので、資料として残そうというのが今回のブログ(^^)

私としては珍しくガチンコ技術ブログw

 

f:id:PocketGriffon:20210417121610j:plain

とりあえずテスト用の表示データを用意した。昔懐かしいフォントだ(^^;

Bad Apple!!での描画方法

当初、Bad Apple!!で画像データを表示する際、IOCSのサービス(LOADLCD:0160h)を利用していた。

呼び出し方としてはこんな感じ。

    LD  A,#ライン(0 - 3)

    LD  DE,#データが格納されたアドレス

    CALL 0160h

これで1行(縦8ドット)のグラフィックデータが表示される。

これを4回繰り返す事で画面全体が描画される仕組みだ。

 

このIOCSをコールすると、横のドットは無条件に画面全体(156ドット)を描画してしまう。Bad Apple!!では横64ドットしかデータがないけれども、残りの92ドットも表示されちゃうのだ!いくらなんでもコレはもったいない!ということで、直接LCDCをコントロール出来ないか…という理由でROMを解析した。

 

その時に調べてみたところ、どうやら左から64ドット単位で処理しているらしい…という事が分かった。64+64+28ドットという感じで3つの処理を行う。

Bad Apple!!では64ドットのみ表示されれば良いので、じゃあということで画面中央に表示していた画像を左側に寄せて、64ドットの処理1回で表示出来るようにして解決した。

 

その後、PC-E500系のLCD描画を調べている時に「PC-E500活用研究(工学社)」を見てみたら、とても見覚えのある数値が出てきて、あれ??これってPC-1600Kと同じなのでは…となった。実際に調べてみたところ、まるっきり同じだった!(^^;; なんてこったぃ!

というわけで、今回はPC-E500の資料も活用していきたい。

 

PC-E500系のLCDコントローラ

PC-E500系のポケコンでは液晶の表示にHITACHI HD61202というチップが使われている。

f:id:PocketGriffon:20210417123404j:plain

たまたま分解したままのPC-E550が手元にあったので、写真をパチリ(たまたま?)

ここまでわかれば、あとはネットでデータシートを探せば良い。

Hitachi HD61202 Datasheet

英語に抵抗ある場合は、工学社から発売されていたPC-E500活用研究という書籍の208ページに、かいつまんだ情報が載っているので、そちらを参照してもらうのが良いと思う。

f:id:PocketGriffon:20210417123844j:plain

気になって調べてみたら「PC-E500/PC-1480U活用研究」でも「PC-E550/PC-1490UII活用研究」でも「PC-E650/PC-U6000活用研究」でも208ページだったw 中身ほぼ一緒!この活用研究、3冊ホントに必要だったのかな…汗

 

ここに書かれている「アクセス・アドレス」はPC-E500用なので、PC-1600K用に置き換える必要がある。コントローラ1は54h、コントローラ2は58hだ。

注意したいのは、XアドレスYアドレスという呼び方。画面のXYドットなどとは違い、あくまでもLCDコントローラでの呼称だ。しかもなんとなくXとYが逆なので頭を切り替える必要がある。私はこの手の資料を見ずに解析していたので意識していなかったが、資料を見てからの方がこんがらがった(^^;;

f:id:PocketGriffon:20210417125021j:plain

コントローラ1のX=0〜3が画面左の64ドットだ。1バイト8ドット構成なので、0=0..7ドット、1=8..15ドット、2=16..23ドット、3=24..31ドット。

X=4以降は画面右の28ドットをアクセスする際に使う。ちょっと分かりづらい。

 

アクセスの手順としては以下な感じ。

    Xアドレスを設定

    Yアドレスを設定

    表示データを出力

LCDコントローラへアクセスする際には、LCDが処理中かどうかを判定する必要がある。処理中に書き込みを行った場合は、そのデータは無視されるようだ。

これを素直にプログラムするとこんな感じ。

f:id:PocketGriffon:20210417130115j:plain

実際のデータ出力は「outi」という命令で行っている。

今気がついたが、私はLCDコントローラを0と1で管理していた。LCDC1となっているところはコントローラ2として読んで欲しい(紛らわしい…)

このプログラムで画面左側に64x32ドットの画像データが表示される。実際にBad Apple!!で使っているプログラムそのままだ。データのアドレスは$xx00にアライメントされてる必要がある。

 

このLCDコントローラは縦方向へのスクロール機能がある。「表示開始ライン」というデータを設定してやる事でドット単位にスクロール出来るらしい。今回のBad Apple!!では使っていない。むしろBASIC側でこの機能を使っているので、辻褄を合わせてやらないといけない。F05Chというワークは現在のスクロール値を保存している。ここを参照してXアドレスの値を調整している。

 

中央の64ドットを表示するためにはLCDコントローラ1をアクセスするが、プログラムはほぼ一緒だ。

そして右側28ドットはLCDコントローラ2のXアドレスを4〜7に設定してやれば良い。

 

速度比較!

やっぱり作ったものの速度比較は欠かせないと思う!(^-^)

プログラムの最適化、高速化はプログラムしている上でとても楽しい!

画面全体を1000回表示した時の速度を表示してみることにした。カウンタは1/64秒に1ずつ数字があがっていくので、表示された数値を64で割れば秒数が出る。

 

まず、IOCSで表示した場合の速度を測ってみた。

f:id:PocketGriffon:20210417132043j:plain

表示されてるのは10進数だ(^^;;

1000回表示するのに1988と出たので掛かった処理は31.0625秒、秒間31.62回表示出来た。

秒間30回と言えば遅くはないけども…って事になるが、秒間30回の書き換えをしたかったBad Apple!!では表示だけでこれだけ処理が掛かるのは、やはりアウトだった(^^;;

IOCS = 1988 [31.0625秒:31.62回/秒]

 

それでは直接LCDコントローラを制御して表示する方法の速度を測ってみよう。

f:id:PocketGriffon:20210417132727j:plain

おお!どどーんと速くなった!時間は19.78125秒、秒間50.55回の表示が出来るようになった。IOCSに比べて倍とは言わないけれども約7割弱の高速化。

実際にゲームなどに使う場合は、画面全体でなくて2/3くらいをゲーム画面にしたらもう少し快適化できそう!

直アクセス = 1266[19.78125秒:50.55回/秒]

 

さらなる高速化は可能?

さて…ブログとしてはここで終わってしまっても良いかなーと思ったんだけど、どーしても気になる事があったので追加で実験してみた!(^^;;

プログラマたるもの、疑問を残してはいかんのだ!(変なフラグ立てたらダメ)

 

もう一度、PC-E500活用研究の表を見てみよう。

f:id:PocketGriffon:20210417133420j:plain

一番右側に「同時アクセス」という項目がある。同時アクセス…気になるよね!(^^;

これはおそらく画面クリアなどを高速に行うためにあるモードなんだと思う。00で埋めるとかFFで埋めるとか、同じデータを両コントローラへ書き込む時に使ったら便利!

 

これと……さっきのプログラムでLCDコントローラがBUSYの間待つってコード……気にならない?? データを書き込むと、次のデータを書き込めるようになるまで、だいたい40サイクルほど待たねばならないようだ。1ループに40サイクル…ちょっと無駄に思える。

LCDコントローラが2つあるのだったら、交互に書き込んでやったらどうなるんだろ??

 

しかしデータを書き込むためのレジスタロードなどに時間がかかってしまったら本末転倒。プログラムは結構複雑になる??そんな風に思っていたが…ピンと来るものがあった!

制御すべきLCDコントローラは2つ、そしてZ80も裏と表のレジスタが2セット!

おお、これでプログラムの方針は決まった!(^^)

 

以下、作ってみたプログラム。

表と裏のレジスタが頻繁に入れ替わるので相当こんがらがるw

f:id:PocketGriffon:20210417142158j:plain
XYアドレスへ出力するのは2つのコントローラへ同時アクセスしている。

Yアドレス出力後にBUSY信号をチェックせねばXアドレス出力がうまくいかなかった。

 

そしてデータの出力はnopを並べる事でBUSY信号のチェックをパスした。手元にあるPC-1600Kではちゃんと動いたが、マシンごとの個体差が無いとは限らないのでギリギリの設計はダメ。ギリギリを見定めた上で、nopをもう1つずつ入れると良いかも知れない(^-^)

 

このプログラムで左64ドットと中央64ドットは描画出来るが、右側の28ドットは表示されない。そこは前に使っていたプログラムをそのまま呼び出す事にした。

デバッグをしてちゃんと動くようになったところで、お楽しみの速度を測ってみよう!

 

f:id:PocketGriffon:20210417142826j:plain

!!!!すごい!倍以上速くなった!!(^O^)

時間は9.71875秒、秒間102.89回の表示が出来るようになった。IOCSに比べたら3倍以上の高速化となった。

LCDC交互アクセス = 622[9.1875秒:102.89回/秒]

 

正直言えば、ここまで速くなるとは思っていなかった。おそらくLCDC同時&交互アクセスなどはPC-E500シリーズでは定石的なテクニックなんだろうけれども、今回改めてやってみた事で優位性は証明できた気がする(^^)

あ、いや待て。Z80は裏レジスタがあるからここまで高速化出来たワケなので、PC-E500などではあんまり有用ではないのかも??うーむ、調べたくなってきてしまう…滝汗

 

いろんな思いを残しつつ、今回はここまで!(^^;

ではまた次回!(^-^)ノ