このエントリーをはてなブックマークに追加
スポンサーリンク

カーソルの形状設定

PC-9801のカーソル

PC-9801のMS-DOS、つまりテキストV-RAM上のカーソルは、グラフィックコントローラーが都度割り込みをかけて点滅表示させています。

J-3100やDOS/VのDOSでは、カーソルはBIOSがソフト的に表示させています。J-3100ではBIOSがタイマー割り込みをかけて点滅表示をさせていますし、DOS/Vでは点滅はせずにV-RAMとXORを取って該当箇所を反転表示させています。したがって、J-3100やDOS/VではレジスタをセットしてBIOS割り込みをかけるだけでカーソルの形状を設定できます。

しかし、PC-9801ではグラフィックコントローラーがカーソルを表示させていますので、グラフィックコントローラーにコマンドを送信しなければなりません。

GDCコマンドの発行

グラフィックコントローラー(以下GDC)へコマンドを送信するためには、いくつか段取りが必要です。

GDCコはFIFOバッファにてコマンドをバッファリングしています。FIFOですので、最後のコマンドを最初に実行します。したがって、割り込み処理ルーチンが何かGDCにコマンドを送っている最中にGDCに何かコマンドを発行してしまうと、そちらが先に実行され、割り込み処理が行っていた処理が誤動作してしまうかもしれません。

そこで、GDCのFIFOバッファが空になるまで待ちます。具体的には、I/Oポート60Hのビット2を検査します。

60H GDCステータス(Read)
ビット 意味
7 LIGHT PEN DETECT
6 HORIZONTAL BANK
5 VERTICAL SYNC
4 DMA EXECUTE
3 DRAWING
2 FIFO EMPTY
1 FIFO FULL
0 DATA READY
ビット2が1ならFIFO EMPTY、つまりFIFOバッファが空という事です。

しかし、ここで2つ問題があります。

@割り込み処理の問題
GDCにアクセスしているのは、なにもあなたの実行させているプログラムだけではありません。MS-DOS上ではさまざまな割り込み処理が動いており、途中で割り込み処理がGDCを使うかもしれません。そこで、GDCのEMPTYを検出する前に、割り込み禁止(CLI)しておく必要があります。
A再チェックの間隔
もし、あなたが部下に仕事を頼みたいとします。しかし、部下はあなたよりさらに上司に頼まれた仕事を割り込みでしていました。そこで、あなたは部下に「今やってる仕事は終わったか?」と聞くでしょう。ところが、あまりに頻繁に「仕事終わったか?」と聞くと、その返事をするのに時間をとられてしまってかえって仕事が終わらなくなってしまいます。

これは私もよく経験した事で、トラブル発生時にせっかちなお客さんからもう1分おきぐらいに電話で「まだかまだか」と催促の電話がかかってしまい、その電話の対応のせいで仕事が全然進まなくなってしまいました。

同様に、60Hをチェックする間隔にある程度時間を空けないと、GDCがあなたへの要求に対して返事をするのに時間を取られてしまい、今やってる仕事が終わらなくなってしまいます。そこで、GDCのFIFOバッファが空でなかった時は、適当な待ち時間を入れてから再度60Hをチェックします。

待ち時間を入れるのに、普通はタイマー割り込みをかけるのですが、PC-9801ではこのタイマー割り込みが複雑で、GDCのFIFOバッファを読み出すためだけのウェイトであれば、PC-9801ではポート5FHに何らかの値を書き込むと0.6μ秒以上のウェイトが保証されているので、とりあえずこれをウェイトとして利用します。
;------- 0.6マイクロ秒以上のウェイト
WAI		=	$
		PUSH	DX
		PUSH	AX
		MOV	DX,005FH
		MOV	AX,0
		OUT	DX,AX
		POP	AX
		POP	DX
		RET
以上の事をまとめると、以下のロジックになります。

;----- FIFOバッファチェック
CHKFIFO		=	$
		PUSHF
		CLI
		IN	AL,60H
		TEST	AL,4
		JZ	RETRY
		JMP	GDCSEND

;---- やり直し
RETRY		=	$
		POPF
		CALL	WAI
		JMP	CHKFIFO

;---- GDCコマンド送信
GDCSEND		=	$

     (後述)


画面の行数の取得

GDCのカーソルの形状変更コマンド「4BH」は、カーソルの形状と共にテキスト1行あたりのドット数も設定しなければなりません。つまり「1行あたりのドット数は現状維持」っていうコマンドがないのです。

PC-9801はグラフィックスが640×400ドットでテキストは80×25ですので、1行あたりのドット数は400÷25で16ドットです。ところが、MS-DOSでは画面の行数を20行にする事もできるため、ワークエリアを参照して現在の画面モードが、20行なのか25行なのかを取得しなければなりません。

0000:0053CH
ビット 意味
0 0 画面の行数25
1 画面の行数20

カーソル形状の変更コマンド

ここまできて、ようやくGDCにコマンドを送れるようになります。
I/Oポート 意味
60H GDCコマンドパラメーター送信(ライト)
62H GDCコマンド送信(ライト)
カーソルの形状変更コマンドは4BHですので、まず62Hに4BHを書きます。その後、60Hにパラメーターを出力します。これは3回に分けて8ビットずつ出力します。

1回目
ビット 意味
7 0 カーソルを表示しない
1 カーソルを表示する
6〜5 未使用(常に0)
4〜0 (1行あたりのドット数)-1
1行のドット数はテキスト画面が80×25なら16-1で15、80x20なら20-1で19を指定します。なので、80×25でカーソルを表示させる場合は、

128 + (16-1) = 143 = 8FH

を指定します。1行のドット数の指定が大きすぎると下の方の行が画面からはみ出して見えなくなってしまいますし、1行のドット数が少なすぎるとテキストが重なって表示されてしまいます。

△1行のドット数を誤って少なく指定してしまった場合

2回目
ビット 意味
7〜6 ブリンクレートの下位2ビット
5 0 ブリンクする
1 ブリンクしない
4〜0 カーソル表示開始ライン(0〜16または0〜20)

3回目
ビット 意味
7〜3 カーソル表示終了ライン(0〜16または0〜20)
2〜0 ブリンクレートの上位3ビット

カーソルの表示開始ライン、表示終了ラインを指定します、開始ライン>終了ラインの場合はカーソルが消えます。

ブリンクレートはカーソルの点滅の速さで5ビット(0〜31)で指定しますが、色々変更してみましたがいくらやっても変わりませんでした。なので大きければ速くなるのか遅くなるのかわかりませんでした。とりあえずいつも12(01100B)ぐらいを指定しています。
;---- GDCコマンド送信
GDCSEND		=	$
		MOV	AL,4BH
		OUT	62H,AL
		MOV	SI,OFFSET CURDATA
		MOV	AL,[SI]
		OUT	60H,AL
		MOV	AL,[SI+1]
		OUT	60H,AL
		MOV	AL,[SI+2]
		OUT	60H,AL

       (省略)

;----- カーソルの形状データ
CURDATA		DB	8FH,0FH,7BH

エスケープシーケンスやBIOSを使う場合

このコマンドはカーソルの形状を設定するだけで、現在の形状を読み出す事ができません。したがって、エスケープシーケンスやBIOSで「カーソルを消す」「カーソルを出す」というコマンドを使った場合、カーソルが消える前の状態が復元されるわけではなく、カーソルはデフォルトの状態で復元されます。

エスケープシーケンス
カーソルを消す ESC [>5h
カーソルを出す ESC [>5l

BIOS INT18H
AH=12H カーソルを消す
AH=11H カーソルを出す

なので、エスケープシーケンスやBIOSを使ってカーソルを消したり出したりした後は、自前のルーチンでもう一度カーソルの形状を再設定する必要があります。

終わりに

これと同じ事をJ-3100でやるなら、
;--------カーソルの形状設定
		MOV	CH,ES:[SI]
		MOV	CL,ES:[SI+1]
		MOV	AH,1
		INT	10H
こんな感じになります。ここで、ES:[SI]にはカーソル表示開始行、ES:[SI+1]にはカーソル表示終了行が入ってるとします。J-3100では4行で済むことが、なんでこんなに長くなるのかというと、PC-9801はCPUにできる限り負担をかけないように、さまざまな外部コントローラーがついているためです。

結局、多くの外部コントローラーの存在は製造コストを跳ね上げ、プログラムを複雑化する要因となりました。また、PC-9821MATEシリーズが発売された頃には、CPUの急速な性能の向上により、外部コントローラではなくCPUが直接V-RAMを書き換えたほうがかえって高速になってしまいました。

1990年頃東芝から代理店向けに配布された販促用資料の1つに、「PC-9801はアンタッチャブル、それが私のフィロソフィ」というツッコミどころ満載の文書がありました。しかし、実際に国内で売れたのはPC-9801でした。(海外では圧倒的にT-3100でしたが) 結局、プログラミングのしやすさが必ずしも売り上げにつながるというわけではないようです。

参考文献
『PC‐9801スーパーテクニック』 1992年 小高輝真、清水和文、速水祐 著 アスキー
『J-3100解析ハンドブック』 1989年 土屋勝著 ナツメ社
『DOS/Vテクニカル・リファレンス・マニュアル』 1993年 芦達剛著 ソフトバンク
スポンサーリンク