VDP/VRAMアクセスタイミングに注意


「MSX2テクニカルハンドブック(以下テクハン)」(アスキー)などには、BIOSを使わずにVDP/VRAMをアクセスする方法が書かれています。MSXでは、I/O操作は原則としてBIOSを使わなければならないのですが、速度アップのため、VDP/VRAM操作に限っては、I/Oを直に操作することが認められています。

ところで、VDP(レジスタ)/VRAMの内容は、I/Oに書き込んだ瞬間に変わるものではありません。一度VDP/VRAMへI/O入出力したら、次の入出力には、少し時間を空けてやらなければなりません。
BIOSで操作する場合は、内部でタイミングを取ってくれるのですが、直にI/Oを操作する場合は、ユーザーがタイミングを取ってあげなければなりません。

というわけで、VDP/VRAMのI/O操作は、必ず以下の間隔で行ってください。

※便宜上、Z80本来のステート数(M1サイクルなどを考慮しない)で表現します(例:OUT(c),r => 12ステート)。1ステート=1/CPUのクロック周波数 (秒)。各命令のステート数は、Z80の解説書などを御覧下さい。「Simple ASM」(コーラル)のマニュアルにも、ステート数の一覧があります。


1.VDPのレジスタ操作の場合は、最低12ステートの間隔を開ける。

        OUT     (n),A
  を連続して書くと十分な間隔が取れず、VDPのレジスタアクセスに
  失敗することがあります。
        OUT     (C),r
  については連続して書いてもいいようです。

  また、VDP/VRAMのI/Oアドレスは必ずMAIN ROMの6,7番地から情報を
  得てください。おうちゃくはしないように(^^)。詳しくはテクハンを
  参照してください。


2.VRAMの(アドレス指定後の)読み書きは、最低21ステートの
  間隔を開ける。

  OUTI/INI/OUTD/INDを連続して書くと、データを取りこぼすことが
  あります。
  ブロック転送の際は原則として、OTIR/INIR/OTDR/INDRを使うのがいいでしょう。

    悪い例)        良い例)
      OUTI            LD      B,4
      OUTI            OTIR
      OUTI
      OUTI

  またOTIR/INIR/OTDR/INDRの場合でも、連続して書くと、最後の1バイト
  転送は16ステートになるので、やはりデータを取りこぼすことが
  あります。この場合もNOPなどでウエイトをとるがいいでしょう。

    悪い例)        良い例)
      OTIR            OTIR
      OTIR            NOP
                      OTIR

参考

OUT(n),A:11ステート
OUT(c),r/IN r,(C):12ステート
OUTI/INI/OUTD/IND:16ステート
OTIR/INIR/OTDR/INDR:1バイトあたり21ステート、ただし最後の1バイトは16ステート。
NOP:4ステート
※Z80では、4ステートより短い時間で実行できる命令はありません。
実のところ、VDP/VRAM のI/O操作時の必要間隔は、機種によってまちまちで、VDP(レジスタ)アクセスにしても、OUT (n),A 命令を連続で使っても問題ない機種もあります。
上に挙げたものは、すべての機種で動かすための最低ラインであり、できればこの間隔を守って操作した方がいいでしょう。 これは MSX turbo R(標準モード)も例外ではありません(VDPのレジスタを、OUT (n),A 命令連続で操作したら失敗したという報告がありました)。

そんなわけで、テクハンの VDP/VRAM 関係のサンプルプログラムは、機種によっては動かないという報告があります。VRAMへの読み書き(OUT命令)の前後に、適当にNOP命令などを挟んでやれば動くようになるはずです。

テクハンのサンプルプログラムには、もうひとつ重大な間違いがあります。VDP/VRAMのI/Oは、入力用と出力用の2種類があり(テクハン参照)、入力時と出力時では、2つのI/Oを使い分けなければなりません。ところがサンプルでは、入力も出力用のI/Oで操作しています。入力用と出力用のI/Oが同じ機種なら、これでも問題はありませんが、別々になっている機種では動作の保証がありません。ただ、今まで出てきたMSXは、(幸か不幸か)すべて入力用と出力用のI/Oが共通らしいので、問題ないといえばそれまでかも知れませんが。

MSX2+ には、VDPのコントロール/ステータスレジスタのアクセス(操作)間隔が短い場合は、CPUを一時停止する機能があると言われていますが、この機能は実際には使われていないようです。VDPが信号を出しても、その信号がCPUに届かないようです。また、パレットレジスタには、もとからこの機能はありません。

MSX2+ 用プログラムであっても、VDP/VRAMの操作間隔には気をつけましょう。


I/Oを直接操作してVRAMアクセスする際の注意を述べてきましたが、この問題はソフトウェア会社でも頭を抱えていた問題のようで、あるMSX用ソフトのマニュアルには、VRAMアクセスをI/O直で操作しているため、一部機種でうまくVRAMの読み書きができない可能性があるという内容のことが書かれていました。

通常はこのページで述べたアクセス間隔を守っていれば問題はないと思いますが、より確実にVRAMの読み書きを行いたい場合は、おとなしくBIOSを使った方がいいかもしれません。

また、もしこのページで紹介したアクセス間隔を守っても、うまくVDP/VRAMの読み書きができない、データが抜け落ちる、あるいは重ねて出るといった症状が起こる場合は、私宛に電子メールを下されば幸いです。 そのさい、使用機種と症状、VDP/VRAM操作部分のソースリストを書いて下さるようお願いします。


MSXの適当手帳 MSX駅 西山駅