
しかしここで重要なのは、誤動作に繋がる状況とは、基本的にVDPコマンドの手順が狂った場合です。
つまり、VDPコマンドの手順を狂わせないレジスタへのアクセスなら、いつ実行しても構わないことになります。そのような例として以下のものが挙げられます。
VDPマクロのデータの作成方法については、「第3章 VDPマクロを組む」をご覧ください。
※ パレット機能を利用しない場合は省略できます。
書式は基本的に「コマンド」と「ウェイト」を交互に並べて行きます。「コマンド」は1回に限らず、連続して発行できます。「ウェイト」が指定された時点でそのタイマー割り込みでのコマンド発行を終了し、通常の処理へ復帰します。
パレット関連については、DMシステム2のパレット機能をそのまま活用できるようにしました。00H〜3FHは10進法で0〜63ですし、80H〜BFHは10進法で128〜191です。CALL CHGPLT の「通常モード」と「一気モード」の数値を、そのままVDPマクロで割り当ててあります。
VDPのモードレジスタ3(R#9)のbit7には、画面表示サイズを設定するフラグがあります。縦192ライン(0)にするか、縦212ライン(1)にするかで、画面表示が変化するわけです。気が付けばテキストモードでは192ラインで表示されていますし、ビットマップモードでは212ラインで表示されていますよね。
モードレジスタ (R#9)
その状態でスクリーンモードをちょこちょこ変えてみたり、リスト中のウェイトを変えてみたりすると面白いと思います。
なお、このVDPマクロは永久ループで動いています。マクロを止めるには CALL VMOFF または CALL SYSON を実行してください。
普通にVDPコマンドでパレットを変更しようとすると、VDPマクロではサポートできません。そこでパレット操作に関しては、DMシステム2がパレット変更専用のルーチンを用意していますので、これをVDPマクロで利用します。
ちなみに「パレット機能」で紹介したBASICプログラムはこんな感じでした。
マクロに「ウェイト」が無いと、一瞬のうちにパレットが7段階変化してしまいます。これではフェード・インをやる意味がありません。よって、コマンドの最後に必ず「ウェイト」を通るようにしてください。
また、マクロ終了コードを付けないと、ループ後のメモリの内容をそのままVDPマクロと解釈してしまい、勝手な数値が次々とVDPへ書き込まれてしまいます。画面が正常を保てないばかりか、場合によっては暴走の危険性もあります。VDPマクロの終了コードも必ず付けてください。
BASICのプログラムでは、こんな感じで組むと良いのではないでしょうか。
もしPAUSEキーやCAPSキーを押してみてまだマシンに反応があるようなら、慌てず次の手順で画面を復帰させてください。
DMシステム2のインフォメーションエリアに存在する INTERL (4300h+10) は、インターレースのON・OFFを設定するエリアで、DMシステム2の漢字表示機能などで利用しています。しかしVDPのモードレジスタ3(R#9)に何かしらの数値を書き込むことで、それまでのインターレース環境が不定(おそらくほとんどの場合OFF)になります。
残念ながらVDPマクロでは特定のビットをマスク(保護)して数値を書き込むなんて真似はできません。事前にビット計算して「自己書き換え」のような方法で解決するか、始めから無視するくらいしか方法が無いでしょう。
以上の理由から、モードレジスタへアクセスした際は、できるだけ元の状態に戻すように努力してください。
第1章 概要
1.1 VDPマクロとは
VDPマクロは1/60秒のタイマー割り込みを利用してVDPコマンドを発行するという、前代未聞の簡易マクロ言語です。画面のフェードイン・アウトやスクロールなどの効果を自動運転にすることが可能で、BASICのプログラムと平行して実行することができます 。
1.2 可能なことと不可能なこと
VDPコマンドというものは非常にデリケートで、一定の手順を踏まないと絶対に実行されません。一般の処理でVDPコマンドを発行していた場合、タイマー割り込み中に新たなVDPコマンドを発行すると本来の処理が実行できなくなることがあったり、ましてやVDPのステータスレジスタの読み出し中に割り込みがかかった状態で別のVDPコマンドを発行したりすると即暴走につながります。よってタイマー割り込みでVDPコマンドを発行しないのが無難とされています。
このような類のVDPコマンドはVDPの「コマンドレジスタ(R#32〜R#46)」を用いてVDPへアクセスしますが、レジスタを常にインクリメントしながら連続してデータを書き込まなければならないので、タイマー割り込みで別のコマンドを発行するとそれまでのコマンドの手順が狂い、本来の処理が実行できなくなる可能性が非常に高くなります。
VDPマクロは画面の描画はできませんが、例えばこれらのような処理は簡単に実現できます。そしてBASIC上での自動運転も可能なのです。
第2章 DMシステム2からの利用方法
2.1 VDPマクロデータを配置する
まずはVDPマクロのデータをどこかのメモリ(RAM)へ配置しなければなりません。call load や bload などでファイルから転送したり、プログラムでデータを作成するのも良いでしょう。
CALL LOAD ("ファイルネーム")
← ファイルの読み込み
BLOAD "ファイルネーム" ← BSAVE形式ファイル
マクロデータを配置するエリアはあらかじめCLEAR文で宣言しておく必要があります。
ex.)
call load ("a.mgs",&h3000) ← 3000hへロード
bload "a.bgm" ← BSAVE形式ファイルをロード
ex.)
clear 200,&hc000 ← c000h以降をBASICが使わない
2.2 パレットテーブルの設定
マクロでパレットを変更する場合はパレット機能と同じく、RAM上に配置したパレットテーブルの先頭アドレスを宣言する必要があります。
CALL SETPLT (address)
ex.)
call setplt (&HD000) ← D000hを宣言
2.3 VDPマクロの実行
RAMに配置したVDPマクロを実行します。
CALL VMON (address)
VDPマクロはハードウェアを直接操作できるマクロ言語です。ちょっとしたデータミスでも暴走の危険性があります。必要なデータはあらかじめディスクに保存してからVDPマクロを実行するようにしてください。
ex.)
call vmon (&HC800) ← C800hからVDPマクロを実行
2.4 VDPマクロの強制終了
VDPマクロの実行を強制的に終了させます。
CALL VMOFF
スクリーンモードは自動判定しますので、スクリーンモードに関係なくこの命令を利用できます。
ex.)
call vmoff ← VDPマクロの強制終了
2.5 VDPマクロの終了待ち
VDPマクロが内部的に終了したかチェックします。VDPマクロを利用した的確な時間待ちに便利ですです。
CALL VMWAIT
ex.)
call vmwait ← VDPマクロの終了チェック
第3章 VDPマクロを組む
3.1 仕様
VDPマクロは0〜255の数値にそれぞれ意味があり、内容は次の通りです。
オフセット
内容
nの最大値
00H+n
パレット変更 → _CHGPLT (n)
0〜63
40H+n, <data>
VDP(n) に <data> を書き込む
0〜46
70H+n
ループ指定
0〜14
0=無限ループ
7FH
ループ終了フラグ
80H+n
パレット変更・一気モード
0〜63
0C0H
n/60秒のウェイト → _WAIT (n)
0〜59
0=256カウント
0FDH, <下位>,<上位>
<address> の第2スレッドを実行
0FFH
VDPマクロの終了
3.2 マクロデータを作成する
ここでは更に分かりやすく、ASM形式によるアセンブルリストを使って機能の紹介をします。
主なラベル
----------
chgplt equ 0 ;0+n(0~63)
vdp equ 40h ;40H+n(0~46), xx
loop equ 70h ;70H+n(0~14)
looped equ 7Fh
wait equ 0C0h ;0C0H+n (0~59)
newmcr equ 0FDh ;0FDh,xx,xx
mcrend equ 0FFh
----------
アセンブル作業がよく分からないという方は、上ちゃんだよ@京都産大さん製作のエディタをご利用ください。

![]()
VDPマクロ エディタ ver.1.01
VMED101.LZH (9KB)
3.3 VDPレジスタを変化させる
それでは、実際にVDPマクロを組んでみましょう。まずは簡単なところから、画面を意味も無く広げたり狭めたりしてみましょう。
b7 b6 b5 b4 b3 b2 b1 b0
LN 0 S1 S0 IL EO NT DC
~~ ~~ ~~ ~~ ~~ ~~ ~~ bit0 DLCLK端子 (0:出力 1:入力)
| | | | | +--- bit1 画面周波数 (0:NTSC 1:PAL)
| | | | +------ bit2 Even field/Old field (0:交互 1:同じ絵)
| | | +--------- bit3 Interlace (0:off 1:on)
| | +------------ bit4 同期モード選択
| +--------------- bit5 同期モード選択
|
+--------------------- bit7 画面表示 (0:192ライン 1:212ライン)
VDPマクロで表記すると、こうなります。
それでは、簡単なBASICプログラムを組んでみましょう。
defb loop
→ 永久ループ
defb vdp+9, 0
→ R#9 に 0を書く = 192ラインモード
defb wait+5
→ 6/60秒の時間稼ぎ
defb vdp+9, 128
→ R#9 に 128を書く = 212ラインモード
defb wait+5
→ 6/60秒の時間稼ぎ
defb looped
→ ループ終了
どうですか?画面が上下に揺れていませんか?その状態でカーソルが動くのはもちろん、listだってfilesだって表示できます。画面が揺れている以外は普通の状態と一緒です。VDPマクロがタイマー割り込み内で動いていることを実感していただけたでしょうか。
100 CALL SYSON:CLEAR 200,&HD000
110 '
120 DATA 70 :'loop
130 DATA 49,00 :'vdp+9, 0
140 DATA C6 :'wait+6
150 DATA 49,80 :'vdp+9, 128
160 DATA C6 :'wait+6
170 DATA 7F :'looped
180 '
190 FOR I=0 TO 7:READ A$:POKE &HD000+I,VAL("&H"+A$):NEXT
200 CALL VMON(&HD000):'マクロ実行
3.3 パレット操作
慣れてきたところで、パレットのフェード・インをVDPマクロで自動運転するマクロを紹介します。
これをVDPマクロで表記すると、こうなります。
call chgplt (128+0)
→ パレット#0にしておく
for i=1 to 7
→ 7回ループ
call chgplt (1)
→ パレット#1へRGB各輝度を1段階ずつ変化
call wait (10)
→ 10/60秒の時間稼ぎ
next i
→ ループ終了
この場合、すべてDEFB(1バイト)なので、計6バイトでフェード・インの自動運転が実現することになります。
defb chgplt+128+0
→ パレット#0にしておく
defb loop+7
→ 7回ループ
defb chgplt+1
→ パレット#1へRGB各輝度を1段階ずつ変化
defb wait+10
→ 10/60秒の時間稼ぎ
defb looped
→ ループ終了
defb mcrend
→ VDPマクロ終了
100 CALL SYSON:CLEAR 200,&HD000
110 CALL LOAD("A.PL5",&HD100):CALL SETPLT(&HD100) :'palette load
120 '
130 DATA 80 :'chgplt+128+0
140 DATA 77 :'loop+7
150 DATA 01 :'chgplt+1
160 DATA CB :'wait+10
170 DATA 7F :'looped
180 DATA FF :'mcrend
190 '
200 FOR I=0 TO 5:READ A$:POKE &HD000+I,VAL("&H"+A$):NEXT
210 CALL VMON(&HD000):'マクロ実行
第5章 補足
5.1 画面が崩れて困ったとき
VDPマクロによってVDPへ与えた数値が不正な場合、画面がぐちゃぐちゃになって見えなくなることがあります。最悪の場合はマシンが暴走してしまい、リセット以外に方法が無いかもしれません。
5.2 VDP操作による画面環境の変化について
VDPのレジスタへダイレクトに数値を代入することにより、それまで続いていたMSXの環境を変化させることがあります。特にモードレジスタ(R#1,R#8,R#9)へ数値を代入することで、思わぬ変化を起こします。
※ DMシステム2では何かしらの漢字表示を行うと、インターレース環境が復帰します
Copyright (c) 1998 GIGAMIX, All rights reserved.