現在、趣味のゲーム制作で PC-8001mk2 専用のソフトを鋭意制作中です。とはいえ、趣味の範囲なので、余暇の時間を使っている関係で、なかなか進捗は遅いのですが…。そして、最近知ったのですが、PC-8001mk2 では、例えテキストの DMA を停止しても、GVRAM(グラフィック画面)の反映はやっぱり DMA によって、表示中はアクセスが出来なくなっているようなのです。
昔のモニタはブラウン管です。ブラウン管の表示は電子ビームを蛍光面に照射して実現しています。この電子ビームは一点しかないので、画面の上から順次走査することで表示を更新しています。そして、電子ビームの位置が一番右下まで行ったら、そこから左上まで戻っていきます。画面上を水平に走査する事から、右から左に戻る事を水平ブランキング、右下から左上に戻る事を垂直ブランキングと呼びます。
表示の真っ最中に表示情報を変えられると困ることから、GVRAM表示中に GVRAMの内容を書き換えようとすると、CPUの処理は停止して、画面が表示されていない水平ブランキングや垂直ブランキングの期間に入るまで待たさせてしまいます。水平ブラキングの期間は時間的にはとても短いです。PC-8001mk2 の処理速度で言えば 50clk 程度しか実測で取れなかったようです。表に出ている表示中の時間が 150clk ですから、GVRAM 書き換えが一回のブランキングで終わらなかった場合は、また 150clk もの時間、CPU は待たされることになってしまうのです。
つまり、単純に動作速度を上げただけでは、実際の描画速度の向上は見込めないということです。一度の水平ブランキングで GVRAMに書き込める Z80のバイト数は push を4つ並べての 8バイトが限界です。レジスタは HL,DE,BC,AF ですから、ホントにギリギリですよね。push は一回で 11clk ですから、11×4 = 44clk です。
…ですが、実はさらに罠が待ち受けています。GVRAM にバンクを切り替えると、1命令について 1clk 余分に時間がかかるようなのです。これを M1クロックと読んでいます。そのため、命令4つだと、さらに +4clk となりますので、トータルでは 48clk となります。50clk でアウトですから、本当に push 4つ並べただけでギリギリなんです。なので安全を見て、push を3つ並べただけとして、それ以外の時間は次の push のために準備を 150clk 未満で行う…というプログラムが最も効率的に動作することになります。
この DMA による CPU の停止を意識した処理の例がこちらです。
GVRAM に切り替えた直後から、間髪入れずに push を 4回叩き込んでいます。この push を 5個にすると、DMA で CPU が停止されられて、5個目の push 一回に 200clk トータルでかかるという悲惨な状態となります。こんな事を画面表示の実装系全体に考慮しなければ、本来の速度が出ないとか、本当に昔の PC でのプログラミングは面倒ですよね…
;----------------------------------------------------------------------- ; 画面全体を消去する ; ClearScreen: ld hl, 0 .NUMBER equ (VRAM.WIDTH * VRAM.HEIGHT / 8) .@0 ld bc, (.NUMBER % 256) * 256 + (.NUMBER - 1) / 256 + 1 ld (.@9), sp di ld sp, VRAM.ADRS + VRAM.WIDTH * VRAM.HEIGHT .@1 out (PORT.GVRAM), a push hl push hl push hl push hl out (PORT.RAM), a djnz .@1 dec c jp nz, .@1 .@9 equ $ + 1 ld sp, 0 ei ret
なお、16bit のループに関しては、以下を参照してみてください。
※ 第4世代という触れ込みと、2023年末の購入ユーザーコメントから、Wi-Fi対応メモリの中で、これなら使えるかもというのをチョイスしています。ちゃんと Wi-Fi 経由で中身とやり取りできたら、レトロPC開発で SDドライブと組み合わせるとかなり便利ではないかと。
コメント