GIGAMIX DM-SYSTEM2
VDPマクロ
updated: Apr 3, 1998

  1. 概要
    1. VDPマクロとは
    2. 可能なことと不可能なこと

    3. DMシステム2からの利用方法
      1. VDPマクロデータを配置する
      2. パレットテーブルの設定
      3. VDPマクロの実行
      4. VDPマクロの終了
      5. VDPマクロの終了待ち

    4. VDPマクロを組む
      1. 仕様
      2. マクロデータを作成する
      3. VDPレジスタを変化させる
      4. パレット操作

    5. 補足
      1. 画面が崩れて困ったとき
      2. VDP操作による画面環境の変化について


    第1章 概要

    1.1 VDPマクロとは

     VDPマクロは1/60秒のタイマー割り込みを利用してVDPコマンドを発行するという、前代未聞の簡易マクロ言語です。画面のフェードイン・アウトやスクロールなどの効果を自動運転にすることが可能で、BASICのプログラムと平行して実行することができます 。

    1.2 可能なことと不可能なこと

     VDPコマンドというものは非常にデリケートで、一定の手順を踏まないと絶対に実行されません。一般の処理でVDPコマンドを発行していた場合、タイマー割り込み中に新たなVDPコマンドを発行すると本来の処理が実行できなくなることがあったり、ましてやVDPのステータスレジスタの読み出し中に割り込みがかかった状態で別のVDPコマンドを発行したりすると即暴走につながります。よってタイマー割り込みでVDPコマンドを発行しないのが無難とされています。

     しかしここで重要なのは、誤動作に繋がる状況とは、基本的にVDPコマンドの手順が狂った場合です。

    • ステータスレジスタの読み出し
    • LINEやBOXなど、描画命令
    • COPYなどのブロック転送
     このような類のVDPコマンドはVDPの「コマンドレジスタ(R#32〜R#46)」を用いてVDPへアクセスしますが、レジスタを常にインクリメントしながら連続してデータを書き込まなければならないので、タイマー割り込みで別のコマンドを発行するとそれまでのコマンドの手順が狂い、本来の処理が実行できなくなる可能性が非常に高くなります。

     つまり、VDPコマンドの手順を狂わせないレジスタへのアクセスなら、いつ実行しても構わないことになります。そのような例として以下のものが挙げられます。

    • パレットの変更
    • MSX2の縦スクロール、MSX2+の横スクロール
    • VRAM構成の変更
     VDPマクロは画面の描画はできませんが、例えばこれらのような処理は簡単に実現できます。そしてBASIC上での自動運転も可能なのです。

    第2章 DMシステム2からの利用方法

    2.1 VDPマクロデータを配置する

     まずはVDPマクロのデータをどこかのメモリ(RAM)へ配置しなければなりません。call load や bload などでファイルから転送したり、プログラムでデータを作成するのも良いでしょう。

     VDPマクロのデータの作成方法については、「第3章 VDPマクロを組む」をご覧ください。

      CALL LOAD ("ファイルネーム") ← ファイルの読み込み
      BLOAD "ファイルネーム" ← BSAVE形式ファイル
      ex.) call load ("a.mgs",&h3000) ← 3000hへロード
      bload "a.bgm" ← BSAVE形式ファイルをロード
    マクロデータを配置するエリアはあらかじめCLEAR文で宣言しておく必要があります。
      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マクロの終了

     書式は基本的に「コマンド」と「ウェイト」を交互に並べて行きます。「コマンド」は1回に限らず、連続して発行できます。「ウェイト」が指定された時点でそのタイマー割り込みでのコマンド発行を終了し、通常の処理へ復帰します。

     パレット関連については、DMシステム2のパレット機能をそのまま活用できるようにしました。00H〜3FHは10進法で0〜63ですし、80H〜BFHは10進法で128〜191です。CALL CHGPLT の「通常モード」と「一気モード」の数値を、そのまま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マクロを組んでみましょう。まずは簡単なところから、画面を意味も無く広げたり狭めたりしてみましょう。

     VDPのモードレジスタ3(R#9)のbit7には、画面表示サイズを設定するフラグがあります。縦192ライン(0)にするか、縦212ライン(1)にするかで、画面表示が変化するわけです。気が付けばテキストモードでは192ラインで表示されていますし、ビットマップモードでは212ラインで表示されていますよね。

    モードレジスタ (R#9)

       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マクロで表記すると、こうなります。
      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
      → ループ終了
     それでは、簡単なBASICプログラムを組んでみましょう。
    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):'マクロ実行
     どうですか?画面が上下に揺れていませんか?その状態でカーソルが動くのはもちろん、listだってfilesだって表示できます。画面が揺れている以外は普通の状態と一緒です。VDPマクロがタイマー割り込み内で動いていることを実感していただけたでしょうか。

     その状態でスクリーンモードをちょこちょこ変えてみたり、リスト中のウェイトを変えてみたりすると面白いと思います。

     なお、このVDPマクロは永久ループで動いています。マクロを止めるには CALL VMOFF または CALL SYSON を実行してください。


    3.3 パレット操作

     慣れてきたところで、パレットのフェード・インをVDPマクロで自動運転するマクロを紹介します。

     普通にVDPコマンドでパレットを変更しようとすると、VDPマクロではサポートできません。そこでパレット操作に関しては、DMシステム2がパレット変更専用のルーチンを用意していますので、これをVDPマクロで利用します。

     ちなみに「パレット機能」で紹介したBASICプログラムはこんな感じでした。

      call chgplt (128+0)
      → パレット#0にしておく
      for i=1 to 7
      → 7回ループ
      call chgplt (1)
      → パレット#1へRGB各輝度を1段階ずつ変化
      call wait (10)
      → 10/60秒の時間稼ぎ
      next i
      → ループ終了
     これをVDPマクロで表記すると、こうなります。
      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マクロ終了
     この場合、すべてDEFB(1バイト)なので、計6バイトでフェード・インの自動運転が実現することになります。

     マクロに「ウェイト」が無いと、一瞬のうちにパレットが7段階変化してしまいます。これではフェード・インをやる意味がありません。よって、コマンドの最後に必ず「ウェイト」を通るようにしてください

     また、マクロ終了コードを付けないと、ループ後のメモリの内容をそのままVDPマクロと解釈してしまい、勝手な数値が次々とVDPへ書き込まれてしまいます。画面が正常を保てないばかりか、場合によっては暴走の危険性もあります。VDPマクロの終了コードも必ず付けてください

     BASICのプログラムでは、こんな感じで組むと良いのではないでしょうか。

    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へ与えた数値が不正な場合、画面がぐちゃぐちゃになって見えなくなることがあります。最悪の場合はマシンが暴走してしまい、リセット以外に方法が無いかもしれません。

     もしPAUSEキーやCAPSキーを押してみてまだマシンに反応があるようなら、慌てず次の手順で画面を復帰させてください。

    1. CALL SYSON でDMシステム2を初期化する(暴走したVDPマクロを停止)
    2. SCREEN 0など、SCREEN命令を実行する

    5.2 VDP操作による画面環境の変化について

     VDPのレジスタへダイレクトに数値を代入することにより、それまで続いていたMSXの環境を変化させることがあります。特にモードレジスタ(R#1,R#8,R#9)へ数値を代入することで、思わぬ変化を起こします。

     DMシステム2のインフォメーションエリアに存在する INTERL (4300h+10) は、インターレースのON・OFFを設定するエリアで、DMシステム2の漢字表示機能などで利用しています。しかしVDPのモードレジスタ3(R#9)に何かしらの数値を書き込むことで、それまでのインターレース環境が不定(おそらくほとんどの場合OFF)になります。

      ※ DMシステム2では何かしらの漢字表示を行うと、インターレース環境が復帰します

     残念ながらVDPマクロでは特定のビットをマスク(保護)して数値を書き込むなんて真似はできません。事前にビット計算して「自己書き換え」のような方法で解決するか、始めから無視するくらいしか方法が無いでしょう。

     以上の理由から、モードレジスタへアクセスした際は、できるだけ元の状態に戻すように努力してください。

    [Back]
    Copyright (c) 1998 GIGAMIX, All rights reserved.