PC-6001mkII/PC-6601は、グラフィック画面へのPRINTがとても遅いので、ちょっとだけ高速なPRINTルーチンをマシン語で作ってみました。
さらに高速化した ver 1.3 になりました。(2012.3.6)
まず、サンプルリストの50000行以降のマシン語書き込み部分を呼び出します。
そして、BASICプログラムから、
文字変数 = USR(文字列)
または、
文字変数 = USR(文字変数)
のように使ってください。
ダウンロードはこちら
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 |