ダウンロードは🎥こちら
これは、PC-6001 初代機で動かしたものです。外部に余計はハードウエアは付けていません(RAMは32Kにしていますが)。
境界がちらちらと動くのがイマイチなんですが、一応画面の上半分はSCREEN4、下半分はSCREEN3 になっています。
これは、ソフトウエアで画面描画期間を検出して、そこから一定時間後に画面の切り替えを行ってます。
(事前にページ3とページ4を、SCREEN3 とSCREEN 4 に設定しています)
プログラムがこれです。
vsync.zip
・画面描画期間の検出の方法
画面描画期間の時だけ止まっているCPU で、その止まっている期間を検出するためには、CPU の外部に基準の時計が必要になります。
今回は、SUB-CPU がつながっている8255 のポートを使用しました(詳細は後述)。
特定ポートにデータを書き込むと、4MHz で64クロックぐらいかかる処理があります。
これを使い、画面描画期間を判定します。
データ書き込み
↓
4MHz で40クロックぐらい待つ
↓
処理が完了しているかを判断する
画面描画期間以外:処理が完了しない。
画面描画期間:CPU が途中で止まっているため、実際には40クロック以上の時間が経っており、処理が完了する。
で判断します。
・8255のポートの話
かなりハード寄りの話です。
SUB-CPU とメインCPU との通信のために、8255 のモード2を使っている、という話は周知だと思います。
このモード2ですがもっと細かく見ると、以下のようになります(SUB-CPU に出力時)。
OUT 0x93,0x08 :INTE2 をリセットして、リード側のポートを無効にする(→ライト側のポートのみ有効になる)。
↓
IN (0x92) :bit3 とbit7 が 1 になるまで待つ(8255が受信可能になるまで待つ)
↓
OUT 0x93,0x09 :INTE2 をセットする(後のためにINTE2を戻しておく?)。
↓
OUT 0x90,DATA :SUB-CPU へ出力するデータを書き込む。
最後のデータを出力すると、8255 の port-C の bit7(OBF)が、H→L になります。この信号が、SUB-CPU の割り込み信号になっています。
↓
SUB-CPU は、割り込みが発生すると、データを読み出すためにリードイネーブルをLにします。この信号が、8255 の port-C の bit6 (ACK) になっています。
↓
8255 は、8255 の port-C の bit6 (ACK) がLになると、読み出しが完了したと判断して、port-C の bit7(OBF)をL→Hとして、処理が終了します。
一連の動きを実機のPC-6601 で測定したものがこれになります。動きとしては、初代機PC-6001 でも同じです。
画面描画期間はちゃんと検出出来ているようですが、毎フレーム検出できるというわけではありません。
それは、(当然ですが)画面描画期間中に検出ルーチンを通らないと検出できないため、プログラムのループが長い時には、検出できないことがあるようです。


https://twitter.com/fuzzball/status/223099132334706688
2msタイマーも止まっちゃうしなぁなんて思ったりしながら‥。
8255を使うのは思い付かなかったです。
何かおもしろいこと出来ないかなぁ。
私も最初は2msタイマを考えていましたが、さすがに長いと思ったので、他を探していました。
最初に考えたのは、sub-CPU を使う手です。
sub-CPU にゲームキー検索(CALL 1061 で使っているヤツ)をして、その値が返って来る時間をタイマ代わりにするものです。
ただ、これも結構時間が長く、水平同期で2ライン分以上(4MHz 換算で500クロック以上)の時間がかかります。
今回アップしたのは逆に短すぎるようで、検出できないこともしばしばです。
sub-CPU の方は、もう一度考え直してみる価値はありそうです。
どのくらいの時間なのかなど、調べたり考察したりする能力が私には無いので、
早々にあきらめていました‥。
私は二画面切り替えの同期を取りたいだけなので、
2HSYNC程度なら使えそうな気が?
でも、最近はVSYNC熱がちょっと冷めちゃってるからなぁ(笑)
「8255を使う」というのは、8255へのアクセスで何かウェイトが掛かるのかと思っていたのですが、サブCPUを使うという意味だったんですね。
ゲームキー検索では長過ぎる、サンプルで使用しているCMTクローズでは短過ぎる、
ということでいいのかな?
サンプルのバージョンは、8255の応答時間を使っているので、SUB-CPUに送っているデータ(CMTクローズ)は、特に意味はありません。
Z80 → 8255 → sub-CPU へとデータを送る際に、8255のモード2でハンドシェークみたいな事を行っています。
Z80 が 8255 にデータを出力
↓
8255 がそのデータをラッチし、同時にデータが入力された事を sub-CPU に通知
↓
sub-CPU がその通知を受けて、ラッチしているデータを読み込む
が一連の流れで、その分の時間を待ち時間に使っています。
ちなみに BASICROM の sub-CPU のアクセスで、何やらビットを見て待っているループがありますが、その見ているビットがこれに当たります。
ゲームキー検索の方は、純粋に sub-CPU からのレスポンスを待つ事になるかと思います。キースキャンを2列分行うので、結構時間がかかります...
純粋に「サブCPUへのコマンド送信に掛かる時間」、
BASIC ROMで言うと call $0e8f の処理時間 ということですね。
ゲームキー検索の方もあまり芳しくないようですね‥うむむ。