DEEP!P6! へ戻る

PC-6001mkII/PC-6601用 ちょっとだけ高速な文字表示ルーチン


◆はじめに

◆自作プログラムでの使い方

◆補足事項

◆サンプルリスト ver 1.3

10 REM **************

11 REM コウソク PRINT テスト

12 REM    TINYヤロウ

13 REM **************

20 CLEAR 300,&HF000

30 GOSUB 50000

40 FOR S=3 TO 4

50 REM *************

51 REM PRINTデ ヒョウジ

52 REM *************

60 SCREEN S,2,2:CLS

70 T=TIME

80 FOR I=1 TO 16

90 LOCATE I,I:COLOR I

100 PRINT"PRINTデ ヒョウジ"

110 NEXT

120 T1(S-3)=TIME-T

130 REM *************

131 REM マシンゴデ ヒョウジ

132 REM *************

140 SCREEN S,2,2:CLS

150 T=TIME

160 FOR I=1 TO 16

170 LOCATE I,I:COLOR I

180 Z$=USR("マシンゴデ ヒョウジ")

190 NEXT

200 T2(S-3)=TIME-T

210 NEXT

220 SCREEN 1,1,1:CLS

230 PRINT"ジカン ケイソク ケッカ":PRINT

240 PRINT"SCREEN 3"

250 PRINT"PRINT:";T1(0);" マシンゴ:";T2(0)

260 PRINT

270 PRINT"SCREEN 4"

280 PRINT"PRINT:";T1(1);" マシンゴ:";T2(1)

290 END

50000 REM ***************

50001 REM コウソク PRINT ルーチン

50002 REM ***************

50010 FOR I=&HF000 TO &HF14B

50020 READ A$:POKE I,VAL("&H"+A$)

50030 NEXT

50040 POKE &HFAEB,0:POKE &HFAEC,&HF0

50050 RETURN

50100 DATA 3A,92,FD,FE,02,D8,3A,93,FD,28,08,3D,E6,03,21,34

50110 DATA F1,18,0A,3D,E6,0F,21,14,F1,DD,21,3C,F1,87,4F,06

50120 DATA 00,09,7E,32,BD,F0,23,7E,32,BE,F0,2A,A8,FD,2D,26

50130 DATA 00,29,29,29,29,4D,44,29,29,29,5D,54,29,19,09,3A

50140 DATA A9,FD,3D,4F,06,00,09,3A,92,FD,FE,03,28,01,09,3A

50150 DATA 91,FD,84,67,22,12,F1,3A,39,FF,2A,3B,FF,08,E5,CD

50160 DATA 9E,F0,2A,12,F1,3A,92,FD,FE,03,3A,A9,FD,28,07,FE

50170 DATA 14,23,30,0A,18,04,FE,28,30,04,23,3C,18,11,3A,A8

50180 DATA FD,FE,14,30,08,3C,32,A8,FD,01,69,01,09,3E,01,32

50190 DATA A9,FD,22,12,F1,E1,08,23,3D,20,C2,E1,E1,C9,7E,CD

50200 DATA A0,14,F3,DB,92,E6,FB,D3,92,2A,12,F1,3A,92,FD,FE

50210 DATA 03,28,3C,01,0F,0A,E5,EB,11,CF,F0,D9,01,00,00,E1

50220 DATA D9,7E,A1,12,AE,0F,0F,0F,0F,32,D2,F0,D9,DD,5E,00

50230 DATA DD,56,00,79,A2,77,79,A3,23,77,7C,C6,20,67,78,A3

50240 DATA 77,78,A2,2B,77,11,28,E0,19,D9,23,10,D4,18,1B,EB

50250 DATA 01,E0,0A,3A,BD,F0,A6,12,7A,91,57,3A,BE,F0,A6,12

50260 DATA 7B,C6,28,5F,7A,89,57,23,10,E9,DB,92,F6,04,D3,92

50270 DATA FB,C9,00,00,00,00,55,00,AA,00,FF,00,00,55,55,55

50280 DATA AA,55,FF,55,00,AA,55,AA,AA,AA,FF,AA,00,FF,55,FF

50290 DATA AA,FF,FF,FF,00,00,FF,00,00,FF,FF,FF,00,03,0C,0F

50300 DATA 30,33,3C,3F,C0,C3,CC,CF,F0,F3,FC,FF





◆アセンブラソース

;------------------------------

; 高速グラフィックPRINTルーチン

; (USR関数使用版 ver 1.3)

;

; by TINY野郎

;------------------------------



	ORG	0F000H



;BIOS

_GETCGADR	EQU	014A0H	; in:Aレジスタに文字コード out:DEレジスタにCGROMのアドレス



;システムワーク

_VRAMTOP	EQU	0FD91H	; 現在のページのVRAMアドレスの上位8ビット

_SCRMODE	EQU	0FD92H	; 現在のページのスクリーンモード-1

_COLOR1		EQU	0FD93H	; COLOR文で指定された第一パラメータ

_CURSORY	EQU	0FDA8H	; LOCATEで指定されたX+1

_CURSORX	EQU	0FDA9H	; LOCATEで指定されたY+1

;_USRFUNC	EQU	0FAEBH	; USR関数のジャンプ先(BASICで指定する)

_USRSTLEN	EQU	0FF39H	; USR関数の引数として与えられた文字列の文字数

_USRSTDAT	EQU	0FF3BH	; USR関数の引数として与えられた文字列のアドレス



;-------------------------------

; メイン処理

; (USR関数から呼ばれる)

;-------------------------------

START:

	LD	A,(_SCRMODE)	; A = スクリーンモード-1

	CP	2		; スクリーンモード-1 が2より大きいか小さいか

	RET	C		; スクリーンモード-1 が2より小さいなら(スクリーンモードが3より小さいなら)RETURN

				; USR関数の引数が数値ではなく文字列なので、そのままRETURNだと?TM Errorになるけどちょうどいいや

	LD	A,(_COLOR1)	; A = COLOR文で指定された第一パラメータ(文字色)

	JR	Z,COLMSKSET3	; さっき調べた スクリーンモード-1 が2なら(スクリーンモードが3なら)ジャンプ



COLMSKSET4:

	; SCREEN4用カラーマスク

	DEC	A		; COLORの値はいくらでも指定できるので

	AND	3		; 0〜3 に変換して Aに入れる

	LD	HL,COLMSK4	; SCREEN4用のカラーマスクテーブル

	JR	COLMSKSET

COLMSKSET3:

	; SCREEN3用カラーマスク

	DEC	A		; COLORの値はいくらでも指定できるので

	AND	15		; 0〜15 に変換して Aに入れる

	LD	HL,COLMSK3	; SCREEN3用のカラーマスクテーブル

	LD	IX,SC3BITTBL	; SCREEN3用伸長テーブル

COLMSKSET:

	; カラーマスクデータを取得

	ADD	A,A		; カラーマスクテーブルは2バイトなので

	LD	C,A		;

	LD	B,0		;

	ADD	HL,BC		; COLORに対応するカラーマスクテーブルのアドレスを計算

	LD	A,(HL)		; プレーン1のカラーマスク

	LD	(WCOLMSK1),A	; 保持しておくのも面倒なのでワークに書いておこう

	INC	HL		;

	LD	A,(HL)		; プレーン2のカラーマスク

	LD	(WCOLMSK2),A	; 保持しておくのも面倒なので以下略



CALCADDR:

	;-----------------------

	; VRAMアドレスの計算

	;-----------------------

	; 文字1行は、グラフィックVRAMだと

	; 横40バイト×縦10ドット=400バイトなので

	; LOCATEで指定されたYの値を400倍する

	LD	HL,(_CURSORY)	; LOCATEで指定されたY+1

	DEC	L		; -1する

	LD	H,0		; カーソルのY座標がHLレジスタに入る

	ADD	HL,HL		; x2

	ADD	HL,HL		; x4

	ADD	HL,HL		; x8

	ADD	HL,HL		; x16

	LD	C,L		;    16倍したところで

	LD	B,H		;    BCレジスタにコピー

	ADD	HL,HL		; x32

	ADD	HL,HL		; x64

	ADD	HL,HL		; x128

	LD	E,L		;    128倍したところで

	LD	D,H		;    DEレジスタにコピー

	ADD	HL,HL		; x256

	ADD	HL,DE		; Yの256倍 + Yの128倍 = Yの384倍

	ADD	HL,BC		; Yの384倍 + Yの 16倍 = Yの400倍

	; もっと短く400倍の計算ができたりするかもしれないけどあまり考えなかった…



	; LOCATEで指定されたXの値を足して

	; 最終的なVRAMアドレスを計算

	LD	A,(_CURSORX)	; LOCATEで指定されたX+1

	DEC	A		; -1する

	LD	C,A		;

	LD	B,0		; カーソルのX座標がBCレジスタに入る

	

	ADD	HL,BC		; X座標分のオフセットをVRAMアドレスに足す

	LD	A,(_SCRMODE)	; 突然のスクリーンモードチェック

	CP	3		; スクリーンモード-1が3(つまりスクリーンモードが4)かチェック

	JR	Z,PRTSTRX4	; スクリーンモードが4ならジャンプ

PRTSTRX3:

	; SCREEN3用の処理

	ADD	HL,BC		; SCREEN 3 は文字が横2バイト使うのでもう一度X座標分のオフセットを足す

PRTSTRX4:

	LD	A,(_VRAMTOP)	; そのページのVRAM先頭アドレスの上位8ビット

	ADD	A,H		; 計算済みのHLに加算して

	LD	H,A		;「最終的に文字を書くVRAMアドレス」を計算する

	LD	(WPUTVRAM),HL	; ワークに書いておく





PRTSTR:

	;-----------------------

	; 文字描画とカーソル移動

	;-----------------------

	; USR関数の引数を解析

	LD	A,(_USRSTLEN)	; 文字数

	LD	HL,(_USRSTDAT)	; 文字列データ

PRTSTRLP:

	EX	AF,AF'		; AFを裏レジスタに切り替え

	PUSH	HL		; 文字列データアドレス退避



	; ここまででセットされているもの

	; ・HLに文字データのアドレス

	; ・(WPUTVRAM)に文字を書くVRAMアドレス

	CALL	PUTASC		; 1文字描画



	LD	HL,(WPUTVRAM)	; 現VRAMアドレス

	; 一行右へ移る処理

	LD	A,(_SCRMODE)	; 突然のスクリーンモードチェック

	CP	3		; スクリーンモード-1が3(つまりスクリーンモードが4)かチェック

	LD	A,(_CURSORX)	; カーソルのX座標

	JR	Z,PRTSTRN4	; スクリーンモードが4ならジャンプ

PRTSTRN3:

	CP	20		; SCREEN 3 はX座標は19まで

	INC	HL		; VRAMを1バイト右に動かす(あとでもう1バイト動かす)

	JR	NC,PRTSTRNL	; 右端なら次の行へ

	JR	PRTSTRNX	; 右へ

PRTSTRN4:

	CP	40		; SCREEN 4 はX座標は39まで

	JR	NC,PRTSTRNL	; 右端なら次の行へ

PRTSTRNX:

	INC	HL		; VRAMを1バイト右に動かす(SCREEN 3 だと合計2バイト動かす)

	INC	A		; カーソルのX座標を+1

	JR	PRTSTRNM	; 次の文字へ

PRTSTRNL:

	; 一行下へ移る処理

	LD	A,(_CURSORY)	; カーソルのY座標

	CP	20		; Y座標は19まで

	JR	NC,PRTSTRNR	; 最下段なら次の行へ行かない

	INC	A		; Y座標を+1する

	LD	(_CURSORY),A	; LOCATEのY座標をアップデート

	LD	BC,361		; VRAMのアドレスを次の行の

	ADD	HL,BC		; 左端まで進める

PRTSTRNR:

	LD	A,1		; X座標を左端にする

PRTSTRNM:

	LD	(_CURSORX),A	; LOCATEのX座標をアップデート

	LD	(WPUTVRAM),HL



	POP	HL		; 文字列データアドレス復帰

	EX	AF,AF'		; AFを表レジスタに戻す

	INC	HL		; 次の文字へ

	DEC	A		; 文字数を-1して

	JR	NZ,PRTSTRLP	; 0になるまで繰り返す

	

	POP	HL		; USR関数からBASICへ戻る際の

	POP	HL		; チェック部分を飛ばす



	RET			; BASICへ戻る

	

;-------------------------------

; 1文字描画サブルーチン

;  in: HLに文字データのアドレス

;  in: (WPUTVRAM)に文字を書くVRAMアドレス

;-------------------------------

PUTASC:

	LD	A,(HL)		; 次の文字

	CALL	_GETCGADR	; DEにCGROMのデータアドレス

	

	;CGROMに切り替え

	DI			; 割り込み禁止

	IN	A,(092H)	; ポート92Hの

	AND	0FBH		; ビット2を0にすると

	OUT	(92H),A		; CGROMが見える



	LD	HL,(WPUTVRAM)	; HLに文字を描画するVRAM



	LD	A,(_SCRMODE)	; A = スクリーンモード-1

	CP	3		; スクリーンモード-1 が3なら(つまりスクリーンモードが4なら)

	JR	Z,PUTASC4	; SCREEN4用の描画ルーチンへジャンプ

PUTASC3:

	;-----------------------

	; SCREEN3用描画ルーチン

	;-----------------------

	LD	BC,0A0FH	; 縦10ライン, 表C = 下位4ビットマスク

	PUSH	HL		; VRAMアドレスを裏HLにコピー

	EX	DE,HL		; 表HL = CGROMアドレス

	LD	DE,PUTASC3IXE	; (余ってるので…)

	EXX			; (裏)

_WCOLMSK:

WCOLMSK1	EQU	_WCOLMSK+1

WCOLMSK2	EQU	_WCOLMSK+2

	LD	BC,0000H	; 自己書き換えされる(by 紅茶羊羹先生)

;----

	POP	HL		; 裏HL = VRAMアドレス

	EXX			; (表)

PUTASC3LP1:

	LD	A,(HL)		; CGROMからフォントデータを読む

	; フォントデータを横に伸長してDEレジスタに格納する

	; テーブルにして高速化(アドバイス by GORRY先生)

	AND	C		; データの下位4ビットを取得

	LD	(DE),A		; 自己書き換え LD E,(IX+[ここ])

	XOR	(HL)		; 下位4ビットを0にする(by 紅茶羊羹先生)

	RRCA			; データの

	RRCA			; 上位

	RRCA			; 4ビットを

	RRCA			; 抽出

	LD	(PUTASC3IXD),A	; 自己書き換え LD D,(IX+[ここ])

	EXX			; (裏) CGROMのアドレス退避

_PUTASC3IXE:

PUTASC3IXE	EQU	_PUTASC3IXE+2

	LD	E,(IX+0)	; 伸長テーブルからデータを拾う。+0の部分は自己書き換えされる

_PUTASC3IXD:

PUTASC3IXD	EQU	_PUTASC3IXD+2

	LD	D,(IX+0)	; 伸長テーブルからデータを拾う。+0の部分は自己書き換えされる

	; 例えば、元のデータが [0100 1101] の場合

	; DEレジスタの値は [0011 0000 1111 0011] になる

	

	; このままだと、すべてのドットが1(=白)になるので

	; 不必要なビットやプレーンをマスクすることで色をつける

	LD	A,C		; プレーン1用カラーマスク

	AND	D		; Dレジスタをマスク

	LD	(HL),A		; VRAMに書く

	LD	A,C		; プレーン1用カラーマスク

	AND	E		; Eレジスタもマスク

	INC	HL		; VRAMを1つ進めて

	LD	(HL),A		; 書く

	LD	A,H		; Hのみ加算することで

	ADD	A,20H		; プレーン2へ

	LD	H,A		;(by 紅茶羊羹先生)

	LD	A,B		; プレーン2用カラーマスク

	AND	E		; Eレジスタをマスク

	LD	(HL),A		; VRAMに書く

	LD	A,B		; プレーン2用カラーマスク

	AND	D		; Dレジスタもマスク

	DEC	HL		; VRAMを1つ戻して

	LD	(HL),A		; 書く

	LD	DE,0-2000H+40	; 

	ADD	HL,DE		; マイナス値を加算してプレーン1の次のラインへ



	EXX			; (表) CGROMのアドレス/カウンタ復帰

	INC	HL		; 次のデータへ

	DJNZ	PUTASC3LP1	; 縦10ライン終わるまでループ

	JR	PUTASC_RET	; 終了処理へ



	

PUTASC4:

	;-----------------------

	; SCREEN4用描画ルーチン

	;-----------------------

	EX	DE,HL

	LD	BC,0AE0H	; 縦10ライン, C = -20H(by 紅茶羊羹先生)

PUTASC4LP:

	LD	A,(WCOLMSK1)	; プレーン1用カラーマスク

	AND	(HL)		; CGROMからフォントデータを読む+データをマスクする(by 紅茶羊羹先生)

	LD	(DE),A		; VRAMに書く

	LD	A,D		; 

	SUB	C		; DE += 2000H

	LD	D,A		; プレーン2へ

	LD	A,(WCOLMSK2)	; プレーン2用カラーマスク

	AND	(HL)		; データをマスクする

	LD	(DE),A		; VRAMに書く

	LD	A,E		; 16ビット演算を

	ADD	A,40		; 使わずに

	LD	E,A		; DEに -2000H+40を

	LD	A,D		; 加算する

	ADC	A,C		; (by 紅茶羊羹先生)

	LD	D,A		; マイナス値を加算してプレーン1の次のラインへ

	INC	HL		; 次のデータへ

	DJNZ	PUTASC4LP	; 縦10ライン終わるまでループ

	

	;-----------------------

	; 終了処理

	;-----------------------

PUTASC_RET:

	IN	A,(092H)	; ポート92Hの

	OR	04H		; ビット2を1にすると

	OUT	(92H),A		; CGROMが隠れる

	EI			; 割り込み解除

	RET			; 1文字描画終わり

	

;-------------------------------

; ワークエリア

;-------------------------------



; 一時保存用

WPUTVRAM:	

	DEFW	0

; カラーマスクテーブル(プレーン1用マスクデータ, プレーン2用マスクデータ)

; CGROMから読んだデータを、VRAMに書く前にこの値とマスクすることで色をつける

COLMSK3:

	DEFB	000H,000H	; COLOR 1

	DEFB	055H,000H	; COLOR 2

	DEFB	0AAH,000H	; COLOR 3

	DEFB	0FFH,000H	; COLOR 4

	DEFB	000H,055H	; COLOR 5

	DEFB	055H,055H	; COLOR 6

	DEFB	0AAH,055H	; COLOR 7

	DEFB	0FFH,055H	; COLOR 8

	DEFB	000H,0AAH	; COLOR 9

	DEFB	055H,0AAH	; COLOR 10

	DEFB	0AAH,0AAH	; COLOR 11

	DEFB	0FFH,0AAH	; COLOR 12

	DEFB	000H,0FFH	; COLOR 13

	DEFB	055H,0FFH	; COLOR 14

	DEFB	0AAH,0FFH	; COLOR 15

	DEFB	0FFH,0FFH	; COLOR 16

COLMSK4:

	DEFB	000H,000H	; COLOR 1

	DEFB	0FFH,000H	; COLOR 2

	DEFB	000H,0FFH	; COLOR 3

	DEFB	0FFH,0FFH	; COLOR 4



; SCREEN3のビット伸長を計算せずにテーブルで保持

SC3BITTBL:

	DEFB	000H,003H,00CH,00FH

	DEFB	030H,033H,03CH,03FH

	DEFB	0C0H,0C3H,0CCH,0CFH

	DEFB	0F0H,0F3H,0FCH,0FFH

	

;-------------------------------



	END



; TINY野郎 2013.3