%第1版第6刷 P215〜
6章 VDPコマンドの使用法
MSX-VIDEOではGRAPHIC 4〜GRAPHIC 7モードにおいて、基本的なグラフィック処理をハードウェアによって行えるようになっており、それらをまとめてVDPコマンドと呼んでいます。VDPコマンドによるグラフィックの描画は、必要なパラメータを設定した後にコマンドを起動するのみでよく、ソフトウェアの負担軽減およびグラフィックのスピードアップの点で大きな効果が得られます。本章ではこのVDPコマンドについて説明します。
6.1 VDPコマンドの座標系
VDPコマンドを実行する際、ソース(転送元)あるいはデスティネーション(転送先)の位置はすべて図4.72のような(X,Y)座標で表されます。また同図からわかるように、コマンド実行時にはページの区別はいっさいなくなり、128KバイトのVRAM全体が1つの大きな座標系の中に置かれます。
図4.72 VRAMの座標系
6.2 VDPコマンドの種類
MSX-VIDEOで実行できるコマンドには、表4.5に示す12種類があります。
コマンド名 | 転送先 | 転送元 | 転送単位 | ニーモニック | R#46(上位4ビット) | |||
---|---|---|---|---|---|---|---|---|
High speed move (高速移動) | VRAM | CPU | バイト | HMMC | 1 | 1 | 1 | 1 |
VRAM | VRAM | バイト | YMMM | 1 | 1 | 1 | 0 | |
VRAM | VRAM | バイト | HMMM | 1 | 1 | 0 | 1 | |
VRAM | VDP | バイト | HMMV | 1 | 1 | 0 | 0 | |
Logical move (論理移動) | VRAM | CPU | ドット | LMMC | 1 | 0 | 1 | 1 |
CPU | VRAM | ドット | LMCM | 1 | 0 | 1 | 0 | |
VRAM | VRAM | ドット | LMMM | 1 | 0 | 0 | 1 | |
VRAM | VDP | ドット | LMMV | 1 | 0 | 0 | 0 | |
Line(描画) | VRAM | VDP | ドット | LINE | 0 | 1 | 1 | 1 |
Search(探索) | VRAM | VDP | ドット | SRCH | 0 | 1 | 1 | 0 |
Pset(描点) | VRAM | VDP | ドット | PSET | 0 | 1 | 0 | 1 |
Point | VDP | VRAM | ドット | POINT | 0 | 1 | 0 | 0 |
未使用 | − | − | − | − | 0 | 0 | 1 | 1 |
− | − | − | − | 0 | 0 | 1 | 0 | |
− | − | − | − | 0 | 0 | 0 | 1 | |
Stop | − | − | − | − | 0 | 0 | 0 | 0 |
- MSX-VIDEOは、レジスタR#46(Commaod register)にデータが書き込まれると、ステータスレジスタS#2のビットO(CE/Command Execute)を1にセットしてからコマンドの実行を開始します。必要なパラメータは、コマンド実行前にレジスタR#32〜R#45にセットされていなければなりません。
- コマンドの実行が終了するとCEは0となります。
- コマンドの実行を途中で中断するには、STOPコマンドを実行して下さい。
- コマンドの動作は、ビットマップモード(GRAPHIC 4〜GRAPHIC 7)のときしか保証されません。
表4.5 VDPコマンド一覧
6.3 ロジカルオペレーション
コマンドを実行する際、VRAM上のデータと指定したデータの間で、種々の論理演算(ロジカルオペレーション)を行うことができます。実際には、各演算は表4.6に示したような法則にしたがって行われます。
表中SCはソースの色、DCはデスティネーションの色を表す数値です。IMP、AND、OR、EOR、NOTは、SCとCCにそれぞれの演算を施した結果をデスティネーションに書き込みます。また、頭に“T”のついた演算では、SC=Oに相当するドットは演算の対象とならず、DCのまま残ります。この演算を使用すると、2つの図形の色の部分だけを重ね合わせることが可能になり、アニメーションなどに威力を発揮します。
divプラグインは存在しません。この演算の例をリスト4.7に示します。
演算名 | Operation(演算勒作) | L03 | L02 | L01 | L00 |
---|---|---|---|---|---|
IMP | DC=SC | 0 | 0 | 0 | 0 |
AND | DC=SC×DC | 0 | 0 | 1 | 1 |
OR | DC=SC+DC | 0 | 0 | 1 | 1 |
EOR | DC=!SC×DC+SC×!DC | 0 | 1 | 1 | 1 |
NOT | DC=!SC | 0 | 1 | 0 | 0 |
− | 0 | 1 | 0 | 1 | |
− | 0 | 1 | 1 | 0 | |
− | 0 | 1 | 1 | 1 | |
TIMP | if SC=0 then DC=DC else DC=SC | 1 | 0 | 0 | 0 |
TAND | if SC=O then DC=DC else DC=SC×DC | 1 | 0 | 0 | 1 |
TOR | if SC=0 then DC=DC else DC=SC+DC | 1 | 0 | 1 | 0 |
TEOR | if SC=O then DC=DC else DC=!SC×DC+SC×!DC | 1 | 0 | 1 | 1 |
TNOT | if SC=O then DC=DC else DC=!SC | 1 | 1 | 0 | 0 |
− | 1 | 1 | 0 | 1 | |
− | 1 | 1 | 1 | 0 | |
− | 1 | 1 | 1 | 1 |
※SC=Source Color code
※DC=Destination Color code
※EOR=Exclusive OR
表4.6 ロジカルオペレーション一覧
リスト4.7 Tつき演算の例
1000 '================================================== 1010 ' List 4.7 logical operation with T 1020 '================================================== 1030 ' 1040 SCREEN8 : COLOR 15,0,0 : CLS 1050 DIM A% (3587) 1060 ' 1070 LINE (50,50)-(60,100),48,B : PAINT (51,51),156,48 1080 CIRCLE (55.30),30,255 : PAINT(55,30),240,255 1090 COPY(20.0)-(90.100) To A% 1100 CLS 1110 ' 1120 R=RND(-TIME) 1130 FOR Y=0 TO 100 STEP 3 1140 X=INT(RND(1)*186) 1150 COPY A% TO (X,Y),,TPSET 1160 NEXT 1170 ' 1180 GOTO 1180
6.4 領域指定
AREA-MOVEに属するコマンドは、任意の長方形に囲まれた領域内の画像データを転送するものです。転送元領域は、図4.73のように長方形の1つの頂点と各辺の長さによって指定され、SX、SYは転送元長方形の基準点、NX、NYは各辺の長さ(ドット数)、DIX、DIYの2ビットはデータ転送の方向を表します(DIXとDIYの意味はコマンドの種類によって異なる)。DX、DYには転送先領域の基準点を指定します。
図4.73 領域の指:き
6.5 各コマンドの使用法
コマンドは大きく分けて高速転送コマンド、論理転送コマンド、描画コマンドの3種類あり、使用法もさまざまです。次にそれらを1つ1つ解説します。
6.5.1 HMMC(CPU→VRAM高速転送)
VRAMの指定された領域にCPUからデータをバイト単位で転送します(図4.74)、ロジカルオペレーションは指定できません。このHMMCをはじめとする高速転送コマンドでは、データはバイト単位で転送されます。したがって、GRAPHIC 4〜6のモードではそれぞれX座標の下位1ビット、2ビット、1ビットが参照されない点に注意してください(図4.75)。
図4.76に示すパラメータをレジスタに設定します。この時点で、CPU側から転送するデータの最初の1バイトだけはR#44に書き込んでおきます。R#46にコマンドコードF0Hを書き込むとコマンドの実行が開始され、MSX-VIDEOはR#44のデータを受け取ってVRAMに書き込み、その後CPU側からのデータ待ち状態になります。
CPU側では,第2バイト以降のデータをR#44に書き込んでいきます。ただしS#2のTRビットを参照し、MSX-VIDEOがデータ受け入れ可能な状態(TRビットが“1”)になるのを待ってデータを送らなくてはいけません。S#2のCEビットが“0”になるとすべてのデータ転送が終わったことを示します(図4.77)。リスト4.8にHMMCのサンプルを示します。
図4.75 参照されないドット
図4.76 HMMCコマンドのレジスタ設定
図4.77 HMMCコマンド実行のフローチャート
リスト4.8 HMMCコマンド実行例
;============================================================ ; List 4.8 HMMC sample ; to vse, set H,L,D,E,IX and go ; RAM [IX] ---> VRAM (H,L)-(D,E) ;============================================================ ; RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- HMMC: DI ;disable interrupt CALL WAIT.VDP ;watt end of command LD A,(WRVDP) LD C,A INC C ;C := PORT#1's address LD A,36 OUT (C),A LD A,17+80H OUT (C),A ;R#17 := 36 INC C INC C ;C := PORT#3's address XOR OUT (C),H ;DX OUT (C),A OUT (C),L ;DY OUT (C),A LD A,H ;make NX and DIX SUB A,D LD D,00000100B JR NC,HMMC1 LD D,00000000B NEG HMMC1: LD H,A ;H := NX , D := DIX LD A,L ;make NY and DIY SUB A,E LD E,00001000B JR NC,HMMC2 LD E,00000000B NEG HMMC2: LD L,A ;L := NY , E := DIY XOR A OUT (C),H ;NX OUT (C),A OUT (C),L ;NY OUT (C),A LD H,(IX+0) OUT (C),H ;first DATA LD A,D OR E OUT (C),A ;DIX and DIY LD A,0F0H OUT (C),A ;HMMC command LD A,(RDVDP) LD C,A ;C := PORT#1's address LOOP: LD A,2 CALL GET.STATUS BIT 0,A ;check CE bit JR Z,EX1T BIT 7,A ;check TR bit JR Z,LOOP INC IX LD A,(IX+0) OUT (C),A JR LOOP EXIT: LD A,0 CALL GET.STATUS ;when exit, you must select S#0 EI RET GET.STATUS: ;read status register specified by A PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: ;wait VDP ready LD A,2 CALL GET.STATUS AND 1 JR NZ,WAIT.VDP XOR A CALL GET.STATUS RET ENO
6.5.2 YMMM(Y軸方向のVRAM問高速転送)
VRAMの指定された領域のデータをVRAMの他の領域にバイト単位で転送します.ただしこのコマンドでの転送はY軸方向だけに限られます(図4.78)。
図4.79に示すデータをレジスタに設定した後、R#46にコマンドコードE0Hを書き込むとコマンドの実行が開始されます。S#2のCEビットが"1"の間はコマンド実行中であることを示します。リスト49にYMMMのサンプルを示します。
図4.78 YMMMコマンドの動作
図4.79 YMMMコマンドのレジスタ設定
リスト4.9 YMMMコマンド実行例
;============================================================ ; List 4.9 YMMM sample ; to use, set L,E,B,C,D(bit 2) and go ; VRAM (B,L)-(*,E) ---> VRAM (B,C) ; DIX must be set in D(bit 2) ;============================================================ ; RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- YMMM: DI ;disable interrupt PUSH BC ;save distination CALL WAIT.VDP ;wait end of command LD A,(WRVDP) LD C,A INC C ;C := PORT#1's address LD A,34 OUT (C),A LD A,17+80H OUT (C),A ;R#17 := 34 INC C INC C ;C := PORT#3's address XOR A OUT (C),L ;SY OUT (C),A LD A,L ;make NY and DIY SUB A,E LD E,00001000B JP NC,YMMM1 LD E,00000000B NEG YMMM1: LD L,A ;L := NY , D := DIY LD A,D OR E POP DE ;restore DX,DY PUSH AF ;save DIX,DIY XOR A OUT (C),D ;DX OUT (C),A OUT (C),E ;DY OUT (C),A OUT (C),A ;dummy OUT (C),A ;dummy OUT (C),L ;NY OUT (C),A OUT (C),A ;dummy POP AF OUT (C),A ;DIX and DIY LD A,11010000B ;YMMM command OUT (C),A EI RET GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET END
6.5.3 HMMM(VRAM問高速転送)
VRAMの指定された領域のデータをVRAMの他の領域にバイト単位で転送します(図4.80)。
図4.81に示すパラメータをセットした後、R#46にD0Hを書き込むとコマンドを実行します。コマンド実行中は、S#2のCEビットが“1”になります。リスト4.10にHMMMのサンプルを表示します。
図4.80 HMMMコマンドの動作
図4.81 HMMMコマンドのレジスタ設定
リスト4.10 HMMMコマンド実行例
;============================================================ ; List 4.10 HMMM sample ; to use, set H,L,D,E,B,C and go ; VRAM (H,L)-(D,E) ---> VRAM (B,C) ;============================================================ ; RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- HMMM: DI ;disable interrupt PUSH BC ;save distination CALL WAIT.VDP ;wait end of command LD A,(WRVDP) LD C,A INC C ;C := PORT#'s address LD A,32 OUT (C),A LD A,80H+17 OUT (C),A ;R#17 := 32 INC C INC C ;C := PORT#3's address XOR A OUT (C),H ;SX OUT (C),A OUT (C),L ;SY OUT (C),A LD A,H ;make NX and DIX SUB A,D LD D,00000100B JP NC,HMMM1 LD D,00000000B NEG HMMM1: LD H,A ;H := NX , D := DIX LD A,L ;make NY and DIY SUB A,E LD E,00001000B JP NC,HMMM2 LD E,00000000B NEG HMMM2: LD L,A ;L := NY , E := DIY LD A,D OR E POP DE ;restore DX,DY PUSH AF ;save DIX,DIY XOR A OUT (C),D ;DX OUT (C),A OUT (C),E ;DY OUT (C),A OUT (C),H ;NX OUT (C),A OUT (C),L ;NY OUT (C),A OUT (C),A ;dummy POP AF OUT (C),A ;DIX and DIY LD A,11010000B ;HMMM command OUT (C),A EI RET GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET
END
6.5.4 HMMV(長方形の高速塗りつぶし)
VRAMの指定された領域をバイト単位の色コードデータで塗りつぶします(図4.82)。
図4.83に示したパラメータをセットした後、R#46にCOHを書き込むとコマンドを実行します。コマンド実行中はS#2のCEビットが1になります。リスト4.11にHMMVのサンプルを示します。
図4.82 HMMVコマンドの動作
図4.83 HMMVコマンドのレジスタ設定
リスト4.11 HMMVコマンド実行例
;================================================== ; List 4.11 HMMV sample ; to use, set H,L,D,E,B and go ; B ---> VRAM (H,L)-(D,E) fill ;================================================== ; RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- HMMV: DI ;disable interrupt CALL WAIT.VDP ;wait end of command LD A,(WRVDP) LD C,A INC C ;C := PORT#1's address LD A,36 OUT (C),A LD A,80H+17 OUT (C),A ;R#17 := 36 INC C INC C ;C := PORT#3's address XOR A OUT (C),H ;DX OUT (C),A OUT (C),L ;DY OUT (C),A LD A,H ;make NX and DIX SUB A,D LD D,00000100B JP NC,HMMV1 LD D,00000000B NEG HMMV1: LD H,A ;H := NX LD A,L ;make NY and DIY SUB A,E LD E,00001000B JP NC,HMMV2 LD E,00000000B NEG HMMV2: LD (C),H LD H,A ;H := NY XOR A OUT (C),A OUT (C),H OUT (C),A OUT (C),B XOR A OR D OR E OUT (C),A LD A,11000000B OUT (C),A EI RET GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET END
6.5.5 LMMC(CPU→VRAM論理転送)
CPUからVRAMの指定された領域にデータをドット単位で転送します(図4.84)。このとき転送先とのロジカルオペレーションを指定することが可能です。なお、このLMMCを始めとする論理転送コマンドではデータはドット単位で転送され、どの画面モードにおいても1ドットの情報につき1バイトを必要とします。
図4.85のデータをセットした後、R#46にコマンドコードB0Hを書き込みます。また、その時コマンドレジスタの下位4ビットを用いて、ロジカルオペレーションの指定が可能です。データの転送方法はHMMCと同様、S#2のTRビットとCEビットを参照しながら行います(図4.86)。リスト4.12にLMMCの例を示します。
図4.84 LMMCコマンドの動作
図4.85 LMMCコマンドのレジスタ設定
図4.86 LMMCコマンド実行のフローチャート
リスト4.12 LMMCコマンドの実行例
;============================================================ ; List 4.12 LMMC sample ; to use, set H,L,D,E,IX,A and go ; RAM [IX] ---> VRAM (H,L)-(D,E) (logi-OP : A) ;============================================================ ; RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- LMMC: DI ;disable interrupt LD B,A ;B := LOGICAL OPERATION CALL WAIT.VDP ;wait end of command LD A,(WRVDP) LD C,A INC C ;C := PORT#1's address LD A,36 OUT (C),A LD A,80H+17 OUT (C),A ;R#17 := 36 INC C INC C ;C := PORT#3's address XOR A OUT (C),H ;DX OUT (C),A OUT (C),L ;DY OUT (C),A LD A,H ;make NX and DIX SUB A,D LD D,00000100B JP NC,LMMC1 LD D,00000000B NEG LMMC1: LD H,A ;H := NX , D := DIX LD A,L ;make NY and DIY SUB A,E LD E,00001000B JP NC,LMMC2 LD E,00000000B NEG LMMC2: LD L,A ;L := NY , E := DIY XOR A OUT (C),H ;NX OUT (C),A OUT (C),L ;NY OUT (C),A LD A,(IX+0) OUT (C),A ;first DATA LD A,D OR E OUT (C),A ;DIX and DIY LD A,B ;A := LOGICAL OERATION OR 10110000B ;LMMC command OUT (C),A DEC C DEC C ;C := PORT#1's address LOOP: LD A,2 CALL GET.STATUS BIT 0,A ;check CE bit JP Z,EXIT BIT 7,A ;check TR bit JP Z,LOOP INC IX LD A,(IX+0) OUT (C),A JP LOOP EXIT: LD A,0 CALL GET.STATUS EI RET
GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET
WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET
END
6.5,6 LMCM(VRAM→CPU論理転送)
VRAMの指定された領域からCPUにデータをドット単位で転送します(図4.87)。
図4.88に示したパラメータをセットした後、R#46にコマンドコードA0Hを書き込むとコマンドの実行が開始され、MSX-VIDEOからデータが転送され始めます。CPU側では、まずS#2のTRビットを参照し、この値が“1”ならばMSX-VIDEOのデータが用意できたことを示すので、S#7か月データを読み出します。S#2のCEビットが“O”になれば、データが終了したことを示します(図4.89)。リスト4.13にLMCMの例を示します。
図4.87 LMCMコマンドの動作
図4.88 LMCMコマンドのレジスタ設定
図4.89 LMCMコマンド実行のフローチャート
リスト4.13 LMCMコマンドの実行
;============================================================ ; List 4.13 LMCM sample ; to use, set H,L,D,E,IX,A and go ; VRAM (H,L)-(D,E) ---> RAM [IX] ;============================================================ ; RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- LMCM: DI ;disable interrupt LD B,A ;B := LOGICAL OPERATION CALL WAIT.VDP ;wait end of command LD A,(WRVDP) LD C,A INC C ;C := PORT#1's address LD A,32 OUT (C),A LD A,80H+17 OUT (C),A ;R#17 := 32 INC C INC C ;C := PORT#3's address XOR A OUT (C),H ;SX OUT (C),A OUT (C),L ;SY OUT (C),A OUT (C),A ;dummy OUT (C),A ;dummy OUT (C),A ;dummy OUT (C),A ;dummy LD A,H ;make NX and DIX SUB A,D LD D,00000100B JP NC,LMCM1 LD D,00000000B NEG LMCM1: LD H,A ;H := NX , D := DIX LD A,L ;make NY and DIY SUB A,E LD E,00001000B JP NC,LMCM2 LD E,00000000B NEG LMCM2: LD L,A ;L := NY , E := DIY XOR A OUT (C),H ;NX OUT (C),A OUT (C),L ;NY OUT (C),A LD A,(IX+0) OUT (C),A ;dummy LD A,D OR E OUT (C),A ;DIX and DIY LD A,7 CALL GET.STATUS LD A,B OR 10100000B OUT (C),A LD A,(RDVDP) LD C,A LOOP: LD A,2 CALL GET.STATUS BIT 0,A JP Z,EXIT BIT 7,A JP Z,LOOP LD A,7 CALL GET.STATUS LD (IX+0),A INC IX JP LOOP EXIT: LD A,0 CALL GET.STATUS EI RET GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET END
6.5.7 LMMM(VRAM→VRAM論理転送)
VRAMの指定された領域のデータをVRAMの他の領域にドット単位で転送します(図4.90)。
図4.91に示すパラメータをセットした後、R#46にコマンドコード9XH(Xはロジカルオペレ
ーション)を書き込むとコマンドが実行されます。S#2のCEピットが“1”の間はコマンド実行
中であることを示します。リスト4.14にLMMMの例を示します。
図4.90 LMMMコマンドの動作
図4.91 LMMMコマンドのレジスタ設定
リスト4.14 LMMMコマンドの実行例
;============================================================ ; List 4.14 LMMM sample ; to use, set H,L,D,E,B,C,A and go ; VRAM (H,L)-(D,E) ---> VRAM (B,C) (logi-OP : A) ;============================================================ ; RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- LMMM: DI ;disable interrupt PUSH AF ;save LOGICAL OPERATION PUSH BC ;save DESTINATION CALL WAIT.VDP ;wait end of command LD A,(WRVDP) LD C,A INC C ;C := PORT#1's address LD A,32 OUT (C),A LD A,80H+17 OUT (C),A ;R#17 := 32 INC C INC C ;C := PORT#3's address XOR A OUT (C),H ;SX OUT (C),A OUT (C),L ;SY OUT (C),A LD A,H ;make NX and DIX SUB A,D LD D,00000100B JP NC,LMMM1 LD D,00000000B NEG LMMM1: LD H,A ;H := NX , D := DIX LD A,L ;make NY and DIY SUB A,E LD E,00001000B JP NC,LMMM2 LD E,00000000B NEG LMMM2: LD L,A ;L := NY , E := DIY LD A,D OR E POP DE ;restore DX,DY PUSH AF ;save DIX,DIY XOR A OUT (C),D ;DX OUT (C),A OUT (C),E ;DY OUT (C),A OUT (C),H ;NX OUT (C),A OUT (C),L ;NY OUT (C),A OUT (C),A ;dummy POP AF OUT (C),A ;DIX AND DIY POP AF ;A := LOGICAL OPERATION OR 10010000B ;LMMM command OUT (C),A EI RET GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET END
6.5.8 LMMV(VRAM論理塗りつぶし)
VRAMの指定された領域をドット単位の色コードで塗りつぶします(図4.92)。この時VRAM上のデータと指定したデータの間でロジカルオペレーションを行うことができます。
図4.93に示すパラメータをセットした後、R#46にコマンドコード8XH(Xはロジカルオペレーション)を書き込むとコマンドが実行されます。S#2のCEビッFが“1”の間はコマンド実行中であることを示します。リスト4.15にLMMVの例を示します。
図4.92 LMMVコマンドの動作
図4.93 LMMVコマンドのレジスタ設定
リスト4.15 LMMVコマンドの実行例
;============================================================ ; List 4.15 LMMV sample ; to use, set H,L,D,E,B,A and go ; data B ---> fill VRAM (H,L)-(D,E) (logi-OP : A) ;============================================================ ; RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- LMMV: DI ;disable interrupt PUSH AF ;save LOGICAL OPERATION PUSH BC ;save FILL DATA CALL WAIT.VDP ;wait end of command LD A,(WRVDP) LD C,A INC C ;C := PORT#1's address LD A,36 OUT (C),A LD A,80H+17 OUT (C),A ;R#17 := 36 INC C INC C ;C := PORT#3's address XOR A OUT (C),H ;DX OUT (C),A OUT (C),L ;DY OUT (C),A LD A,H ;make NX and DIX SUB A,D LD D,00000100B JP NC,LMMV1 LD D,00000000B NEG LMMV1: LD H,A ;H := NX , D := DIX LD A,L ;make NY and DIY SUB A,E LD E,00001000B JP NC,LMMV2 LD E,00000000B NEG LMMV2: LD L,A ;L := NY , E := DIY XOR A OUT (C),H ;NX OUT (C),A OUT (C),L ;NY OUT (C),A POP AF OUT (C),A ;FILL DATA LD A,D OR E OUT (C),A ;DIX AND DIY POP AF ;A := LOGICAL OPERATION OR 10000000B ;LMMV command OUT (C),A EI RET GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET
END
6.5,9 LINE(直線の描画)
VRAM上の任意の座標に直線を描きます。指定するパラメータは基準点の座標と直線の伸びる方向、そして直線を対角線とする長方形の長辺と短辺の長さです(図4.94)。MajとMinを設定する時は、その前にかならず両辺の比較を行って、長い方をMajに設定してください。
図4.95に示すパラメータを設定した後。R#46に7XH(Xはロジカルオペレーション)を書き込むとコマンドが実行されます。S#2のCEピットが1の間はコマンド実行中であることを示します。リスト4.16にLINEの例を示します。
図4.94 LINEコマンドの動作
図4.95 LINEコマンドのレジスタ設定
リスト4.16 LINEコマンドの実行例
;============================================================ ; List 4.16 LINE sample ; to use, set H,L,D,E,B,A and go ; draw LINE (H,L)-(D,E) with color B, log-OP A ;============================================================ ; RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- LMMV: DI ;disable interrupt PUSH AF ;save LOGICAL OPERATION PUSH BC ;save FILL DATA CALL WAIT.VDP ;wait end of command LD A,(WRVDP) LD C,A INC C ;C := PORT#1's address LD A,36 OUT (C),A LD A,80H+17 OUT (C),A ;R#17 := 36 INC C INC C ;C := PORT#3's address XOR A OUT (C),H ;DX OUT (C),A OUT (C),L ;DY OUT (C),A LD A,H ;make DX and DIX SUB A,D LD D,00000100B JP NC,LINE1 LD D,00000000B NEG LINE1: LD H,A ;H := NDX , D := DIX LD A,L ;make DY and DIY SUB A,E LD E,00001000B JP NC,LINE2 LD E,00000000B NEG LINE2: LD L,A ;L := DY , E := DIY CP H ;make Maj and Min JP C,LINE3 XOR A OUT (C),L ;long side OUT (C),A OUT (C),H ;short side OUT (C),A LD A,00000001B ;MAJ := 1 JP LINE4 LINE3: XOR A OUT (C),H OUT (C),A OUT (C),L OUT (C),A LD A,00000000B ;MAJ := 0 LINE4: OR D OR E ;A := DIX , DIY , MAJ POP HL ;H := COLOR OUT (C),H OUT (C),A POP AF ;A := LOGICAL OPERATION OR 01110000B OUT (C),A LD A,8FH OUT (C),A EI RET GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET END
6.5.10SRCH(色コードのサーチ)
VRAM上の任意の座標から右または左に向かって、指定した色または指定した以外の色が存在するか否かを調べます(図4.96)。ペイントルーチンなどに使用するとたいへんに便利なコマンドです。
図4.97に示すパラメータを設定した後、R#46に60Hを書き込むとコマンドを実行します。コマンドは目的の色が見つかるか、あるいは画面の端までサーチしても見つからなかった場合終了します。S#2のCEピットが“1”の間はコマンド実行中であることを示します(図4.98)。
コマンド終了後、S#2のBDピットが“1”であれば目的の色コードが発見できたことを示し、その座標がS#8とS#9に格納されています。リスト4.17にSRCHの例を示します。
図4.96 SRCHコマンドの動作
図4.97 SRCHコマンドのレジスタ設定
図4.98 SRCHコマンド実行のフローチャート
リスト4.17 SRCHコマンドの実行例
;=================================================== ; List 4.17 SRCH sample ; to use, set H,L,E,A as follows ; srch((x:H,y:L,color:E,arg(reg#45):A) ; returns: Z (not found) ; NZ (A := X) ;=================================================== ; PUBLIC SRCH RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- LMMV: DI ;disable interrupt PUSH AF ;save arg CALL WAIT.VDP ;wait end of command LD A,(WRVDP) LD C,A INC C ;C := PORT#1's address LD D,0 LD A,32+80H OUT (C),H OUT (C),A ;R#32 := H INC A OUT (C),D OUT (C),A ;R#33 := 0 INC A OUT (C),L OUT (C),A ;R#34 := L INC A OUT (C),D OUT (C),A ;R#35 := 0 LD A,44+80H OUT (C),E OUT (C),A ;R#44 := E INC A LD E,A POP AF ;A := ARG OUT (C),A OUT (C),E ;R#45 := A LD A,01100000B OUT (C),A INC E OUT (C),E ;R#46 := SRCH command LOOP: LD A,2 CALL GET.STATUS BIT 0,A JP NZ,LOOP LD E,A LD A,8 CALL GET.STATUS LD D,A LD A,0 CALL GET.STATUS LD A,D BIT 4,E EI RET GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET
END
リスト4.18 SRCHとLINEを利用した簡易PAINTルーチン
;============================================================ ; List 4.18 SRCH and LINE sample ; search color to right and left. ; then draw line between the two point ;============================================================ ; EXTERN SRCH EXTERN LINE X EQU 0A800H Y EQU 0A801H COL EQU 0A802H ARG EQU 0A803H PCOL EQU 0A804H ;----- program start ----- MAIN: LD (STK),SP LD SP,AREA LD HL,(Y) LD A,(COL) LD E,A LD A,(ARG) PUSH HL PUSH DE SET 2,A CALL SRCH POP DE POP HL JP NZ,S1 LD A,(X) DEC A S1: INC A PUSH AF LD A,(ARG) RES 2,A CALL SRCH JP NZ,S2 LD A,(X) INC A S2: DEC A LD D,A POP AF LD H,A LD A,(Y) LD L,A LD E,A LD A,(PCOL) LD B,A LD A,0 ;PSET CALL LINE LD SP,(STK) RET ;----- work area ----- STK: DS 2 DS 200 AREA: $ END
リスト4.19 簡易PAINTルーチンの使用例
1000 '=============================================== 1010 ' list 4.19 SRCH and LINE sample 1020 ' スペースバー ヲ オシナガラ カーソル ヲ ソウサ シテ クダサイ 1030 '=============================================== 1040 ' 1050 SCREEN 5 1060 FOR I=0 TO 50:LlNE -(RND(1)*255,RND(1)*211),15:NEXT 1070 1=&HA000 ;DEF USR=I 1080 READ A$ 1090 IF A$="END" THEN l130 1100 POKE I.VAL("&H",A$):I=I+1 1110 READ A$ 1120 GOTO 1090 1130 X=128:Y=100:COL=15:PCOL=2:ARG=0 1140 CURS=0 1150 A=STICK(0) 1160 CURS=(CURS+1) AND 1 1170 LINE (X-5,Y)-(X+5,Y).15,,XOR 1180 LINE (X,Y-5)-(X,Y+5),15,,XOR 1190 IF CURS=1 THEN 1290 1200 IF A=1 THEN Y=Y-1 1210 IF A=2 THEN Y=Y-1:X=X+1 1220 IF A=3 THEN X=X+I 1230 IF A=4 THEN X=X+1:Y=Y+1 1240 IF A=5 THEN Y=Y+1 1250 IF A=6 THEN Y=Y+1:X=X-1 1260 IF A=7 rHEN X=X-1 1270 IF A=8 THEN X=X-1:Y=Y-1 1280 IF STRIG(0) THEN GOSUB 1300 1290 GOTO 1150 1300 POKE &HA800,Y 1310 POKE &HA801,X 1320 POKE &HA802,COL 1330 POKE &HA803,ARG 1340 POKE &HA804,PCOL 1350 A=USR(0) 1360 RETURN 1370 DATA ED,73,80,A8,31,4A,A9,2A,00,A8,3A,02 1380 DATA A8,5F,3A,03,A8,E5,D5,CB,D7,CD,AD 1390 DATA A0,D1,E1,C2,21,A0,3A,01,A8 1400 DATA 3D,3C,F5,3A,03,A8,CB,97,CD,AD,A0,C2 1410 DATA 32,A0,3A,01,A8,3C,3D,57,F1,67,3A 1420 DATA 00,A8,6F,5F,3A,04,A8,47,3E 1430 DATA 00,CD,49,A0,ED,7B,80,A8,C9,F3,F5,CD 1440 DATA 0D,A1,C5,3A,06,00,4F,0C,3E,24,ED 1450 DATA 79,3E,91,ED,79,0C,0C,AF,ED 1460 DATA 61,ED,79,ED,69,ED,79,7C,92,16,04,D2 1470 DATA 72,A0,16,00,ED,44,67,7D,93,1E,08 1480 DATA D2,7E,A0,1E,00,ED,44,BC,DA 1490 DATA 90,A0,ED,79,AF,ED,79,ED,61,ED,79,26 1500 DATA 01,C3,9C,A0,ED,61,67,AF,ED,79,ED 1510 DATA 61,ED,79,26,00,7C,B2,B3,E1 1520 DATA ED,61,ED,79,F1,E6,0F,F6,70,ED,79,FB 1530 DATA C9,F5,F3,CD,0D,A1,ED,4B,06,00,0C 1540 DATA 3E,A0,16,00,ED,61,ED,79,3C 1550 DATA ED,51,ED,79,3C,ED,69,ED,79,3C,ED,51 1560 DATA ED,79,3E,AC,ED,59,ED,79,3C,5F,F1 1570 DATA ED,79,ED,59,3E,60,ED,79,1C 1580 DATA ED,59,3E,02,CD,FD,A0,CB,47,C2,E2,A0 1590 DATA 5F,3E,08,CD,FD,A0,57,3E,00,CD,FD 1600 DATA A0,7A,CB,63,FB,C9,C5,ED,4B 1610 DATA 06,00,0C,ED,79,3E,8F,ED,79,ED,78,C1 1620 DATA C9,3E,02,CD,FD,A0,E6,01,C2,0D,A1 1630 DATA AF,CD,FD,A0,C9,END
6.5.11 PSE丁(点の描画)
VRAM上の任意の座標に点を描きます(図4.99)。
図4.100に示すパラメータを設定した後、R#46に5XH(Xはロジカルオペレーション)を書き込むとコマンドを実行します。S#2のCEビットが“1”の間はコマンド実行中であることを示します。リスト4.20にPSETの例を示します。
図4.99 PSETコマンドの動作
図4.100 PSETコマンドのレジスタ設定
リスト4.20 PSETコマンドの実行例
;================================================== ; List 4.20 PSET sample ; to use, set H,L,E,A as follows ; pset(x:H, y:L), color:E, logi-OP:A ;================================================== ; PUBLIC PSET RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- PSET: DI PUSH AF CALL WAIT.VDP INC C LD A,36 OUT (C),A LD A,80H+17 OUT (C),A PUSH BC INC C INC C XOR A OUT (C),H OUT (C),A OUT (C),L OUT (C),H POP BC LD A,44 OUT (C),A LD A,80H+17 OUT (C),A INC C INC C OUT (C),E XOR A OUT (C),A LD E,01010000B POP AF OR E OUT (C),A EI RET GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET END
6.5.12POINT(色コードの読み出し)
VRAM上の任意の座標の色コードを読み出します(図4.101)。
図4.102に示すパラメータを設定した後、R#46に40Hを書き込むとコマンドを実行します。S#2のCEピットが“1”の間はコマンド実行中であることを示します。コマンド終了後、S#7に指定した座標の色コードが格納されています。リスト4.21にPOINTの例を示します。
図4.101 POINTコマンドの動作
図4.102 POINTコマンドのレジスタ設定
リスト4.21 POINTコマンドの実行例
;================================================== ; List 4.21 POINT sample ; to use, set H,L as follows ; point ( x:H, y:L ) ; returns: A := COLOR CODE ;================================================== ; PUBLIC POINT RDVDP EQU 0006H WRVDP EQU 0007H ;----- program start ----- POINT: DI CALL WAIT.VDP LD A,(WRVDP) LD C,A INC C LD A,32 OUT (C),A LD A,80H+17 OUT (C),A INC C INC C XOR A OUT (C),H OUT (C),A OUT (C),L OUT (C),A DEC C DEC C OUT (C),A LD A,80H+45 OUT (C),A LD A,01000000B OUT (C),A LD A,80H+46 OUT (C),A CALL WAIT.VDP LD A,7 CALL GET.STATUS PUSH AF XOR A CALL GET.STATUS POP AF EI RET GET.STATUS: PUSH BC LD BC,(RDVDP) INC C OUT (C),A LD A,8FH OUT (C),A IN A,(C) POP BC RET WAIT.VDP: LD A,2 CALL GET.STATUS AND 1 JP NZ,WAIT.VDP XOR A CALL GET.STATUS RET END
リスト4.22 PSETとPOINTを利用したPAINTルーチン
;============================================================ ; List 4.22 paint toutine with POINT and Pset ; ENTRY: X;H, Y:L, BORDER COLOR:D, PAINT COLOR:E ;============================================================ ; EXTRN PSET EXTRN POINT Q.LENGTH EQU 256*2*2 MAX.Y EQU 211 ;----- paint main routine ----- PAINT: CALL POINT CP D RET Z CALL INIT.Q LD (COL),DE CALL PUT.Q LD A,(COL) LD E,A XOR A ;logi-OP : PSET CALL PSET PAINT0: CALL GET.Q RET C INC H CALL NZ,PAINT.SUB DEC H JP Z,PAINT1 DEC H CALL PAINT.SUB INC H PAINT1: DEC L LD A,-1 CP L CALL NZ,PAINT.SUB INC L INC L LD A,MAX.Y CP L CALL NC,PAINT.SUB JP PAINT0 ;----- check point and pset ----- PAINT.SUB: CALL POINT LD D,A LD A,(BORD) CP D RET Z LD A,(COL) CP D RET Z LD E,A XOR A CALL PSET CALL PUT.Q RET ;----- init Q.BUFFER pointer ----- INIT.Q: PUSH HL LD HL,Q.BUF LD (Q.TOP),HL LD (Q.BTM),HL POP HL RET ;----- put point to Q.BUF (X:H , Y:L) ---- PUT.Q: EX DE,HL LD HL,(Q.TOP) LD BC,Q.BUF+Q.LENGTH+1 OR A ;clear CARRY PUSH HL SBC HL,BC POP HL JP C,PUT.Q1 LD HL,Q.BUF PUT.Q1: LD (HL),D INC HL LD (HL),E INC HL LD (Q.TOP),HL EX DE,HL RET ;----- take point data to D,E ----- ; returns: NC H:x , L:y ; C buffer empty GET.Q: LD HL,(Q.BTM) LD BC,(Q.TOP) OR A SBC HL,BC JP NZ,GET.Q0 SCF RET GET.Q0: LD HL,(Q.BTM) LD BC,Q.BUF+Q.LENGTH+1 OR A PUSH HL SBC HL,BC POP HL JP C,GET.Q1 LD HL,Q.BUF GET.Q1: LD D,(HL) INC HL LD E,(HL) INC HL LD (Q.BTM),HL OR A EX DE,HL RET ;----- work area ----- COL DS 1 BORD DS 1 Q.TOP DS 2 Q.BTM DS 2 Q.BUF DS Q.LENGTH END
リスト4.23 PAINTルーチンの使用例
1000 '================================================ 1010 ' list 4.23 paint routine with POINT and PSET 1020 ' ペイント カイシ イチ ニ カーソル ヲ アワセテ スペースバー ヲ オシテ クダサイ 1030 '================================================ 1040 ' 1050 SCREEN 5 1060 FOR I=0 TO 50 1070 LlNE -(RND(1)*255,RND(1)*211),15 1080 NEXT 1090 1=&HA000 :DEF USR=I 1100 READ A$ 1110 IF A$="END" THEN l150 1120 POKE I.VAL("&H",A$):I=I+1 1130 READ A$ 1140 GOTO 1110 1150 X=128:Y=100:COL=15:PCOL=2 1160 CURS=0 1170 A=STICK(0) 1180 CURS=(CURS+1) AND 1 1190 LINE (X-5,Y)-(X+5,Y).15,,XOR 1200 LINE (X,Y-5)-(X,Y+5),15,,XOR 1210 IF CURS=1 THEN 1310 1220 IF A=1 THEN Y=Y-1 1230 IF A=2 THEN Y=Y-1:X=X+1 1240 IF A=3 THEN X=X+I 1250 IF A=4 THEN X=X+1:Y=Y+1 1260 IF A=5 THEN Y=Y+1 1270 IF A=6 THEN Y=Y+1:X=X-1 1280 IF A=7 rHEN X=X-1 1290 IF A=8 THEN X=X-1:Y=Y-1 1300 IF STRIG(0) THEN GOSUB 1320 1310 GOTO 1170 1320 POKE &HA8CA,Y 1330 POKE &HA8CB,X 1340 POKE &HA8CD,COL 1350 POKE &HA8CC,PCOL 1360 A=USR(0) 1370 RETURN 1380 DATA ED,73,00,A8,31,CA,A8,2A,CA,A8,ED,5B,CC,A8,CD,67 1390 DATA A0,ED,7B,00,A8,C9,E5,21,D4,A8,22,D0,A8,22,D2,A8 1400 DATA E1,C9,EB,2A,D0,A8,01,D5,AC,B7,E5,ED,42,E1,DA,34 1410 DATA A0,21,D4,A8,72,23,73,23,22,D0,A8,EB,C9,2A,D2,A8 1420 DATA ED,4B,D0,A8,B7,ED,42,C2,4C,A0,37,C9,2A,D2,A8,01 1430 DATA D5,AC,B7,E5,ED,42,E1,DA,5D,A0,21,D4,A8,56,23,5E 1440 DATA 23,22,D2,A8,B7,EB,C9,CD,B8,A0,BA,C8,CD,16,A0,ED 1450 DATA 53,CE,A8,CD,22,A0,3A,CE,A8,5F,AF,CD,F4,A0,CD,3D 1460 DATA A0,D8,24,C4,A1,A0,25,CA,8F,A0,25,CD,A1,A0,24,2D 1470 DATA 3E,FF,BD,C4,A1,A0,2C,2C,3E,D3,BD,D4,A1,A0,C3,7E 1480 DATA A0,CD,B8,A0,57,3A,CF,A8,BA,C8,3A,CE,A8,BA,C8,5F 1490 DATA AF,CD,F4,A0,CD,22,A0,C9,F3,CD,3A,A1,ED,4B,06,00 1500 DATA 0C,3E,20,ED,79,3E,91,ED,79,0C,0C,AF,ED,61,ED,79 1510 DATA ED,69,ED,79,0D,0D,ED,79,3E,AD,ED,79,3E,40,ED,79 1520 DATA 3E,AE,ED,79,CD,3A,A1,3E,07,CD,2A,A1,F5,AF,CD,2A 1530 DATA A1,F1,FB,C9,F3,F5,CD,3A,A1,ED,4B,06,00,0C,3E,24 1540 DATA ED,79,3E,91,ED,79,C5,0C,0C,AF,ED,61,ED,79,ED,69 1550 DATA ED,79,C1,3E,2C,ED,79,3E,91,ED,79,0C,0C,ED,59,AF 1560 DATA ED,79,1E,50,F1,B3,ED,79,FB,C9,C5,ED,4B,06,00,0C 1570 DATA ED,79,3E,8F,ED,79,ED,78,C1,C9,3E,02,CD,2A,A1,E6 1580 DATA 01,C2,3A,A1,AF,CD,2A,A1,C9 1590 DATA END
6.6 コマンドの高速化
MSX-VIDEOは与えられたコマンドの実行のほかに目に見えない各種の処理を行っており、これらの作業のために多少コマンドの実行速度が遅くなっています。したがってこれらの処理を止めることにより、コマンドの実行速度を速めることができます。その方法を以下に示します。
- スプライト表示の禁止
この方法は画面を表示したまま速度を上げられるので有用です。具体的には、R#8のピット1を“1”にします。 - 画面表示の禁止
この方法は画面が消えてしまうので、画面の初期設定時以外には、あまり使えません。この方法を実行するには、R#1のピット6を“1”にします。
6.7 コマンド終了時のレジスタの状態
各コマンドごとのコマンド終了時におけるレジスタの状態を表4.7に示します。
SY*、DY*およびNYBの値は、Y方向実行ドット数をNとすると次のように計算されます。
SY*=SY+N、DY*=DY+N……DIYビットが0のとき
SY*=SY-N、DY*=DY-N……DIYビットが1のとき
NYB=NY-N
注 LINEでMAJビットが0のときはN=N-1になります。
コマンド名 | SX | SY | DX | DY | NX | NY | CLR | CMR H | CLR L | ARG |
---|---|---|---|---|---|---|---|---|---|---|
HMMC | − | − | − | * | − | # | − | 0 | − | − |
YMMM | − | * | − | * | − | # | − | 0 | − | − |
HMMM | − | * | − | * | − | # | − | 0 | − | − |
HMMV | − | − | − | * | − | # | − | 0 | − | − |
LMMC | − | − | − | * | − | # | − | 0 | − | − |
LMCM | − | * | − | − | − | # | * | 0 | − | − |
LMMM | − | * | − | * | − | # | − | 0 | − | − |
LMMV | − | − | − | * | − | # | − | 0 | − | − |
LINE | − | − | − | * | − | − | − | 0 | − | − |
SRCH | − | − | − | − | − | − | − | 0 | − | − |
PSET | − | − | − | − | − | − | − | 0 | − | − |
POINT | − | − | − | − | − | − | * | 0 | − | − |
−:変化なし
* :コマンド終了時の座標(SY*,DY*)およびカラーコード。
# :画面端を検出したときはそのときのカウント数(NYB)となる。
表4.7 コマンド終了時のレジスタの状態