DMA とは direct memory access の略で、さまざまなコンピュータに搭載されており、 周辺機器とメモリの通信を、CPU を介すことなく行うことができる。 SNES では、DMA の通信中は CPU が一時的にストップする。
HDMA は DMA と似ていますが、こちらは少しのデータを、 スキャンライン毎の H-Blank 期間中に転送する目的で使われる。 HDMA は、表示を乱れさせることなく 1 フレーム中に PPU のレジスタを 操作する時に非常に役立つ。
DMA, HDMA 共にそれぞれ 8 つのチャネル (0 ~ 7) がある。 HDMA は DMA より優先順位が高く、データの転送が重なった場合は、 全ての DMA チャネルが一時停止され、重なった DMA チャネルはその場で停止される。 また、番号が小さいチャネルが優先されて動作する。
DMA には 3 つの動作モードと、いくつかの設定用ビットがある。
これらの値は、DMA転送前に設定する必要がある。
0x43x0 のモードビットと転送モードは互いに関係している。 注:1つのレジスタに1度書き込むのと、1つのレジスタに2度書き込むのは同じことが起きる。 2つのレジスタに1度書き込むのと、2つのレジスタにそれぞれ交互に1度ずつ書き込むのも 同じことが起こる。 しかし、2つのレジスタに1度書き込むのと、2つのレジスタにそれぞれ交互に1度ずつ書き込むのは違う。 (訳者注:よく分かりません。)
DMAが1バイト転送する間に、マスターサイクルで8クロックの遅延がある。 (FastROM の設定に関係なく) チャネルごとに8クロックの遅延があり、全て転送するまでに12~24の遅延が起こる。
転送プロセス
注:カウント値 (0x43x5 ~ 0x43x6) は通常0になるまで繰り返されるが、 HDMAと衝突した場合、転送は途中で中止 (terminate) される。
HDMAには4つのフラグと、5つの設定項目がある。 (*) の付いている項目はHDMAの転送前にセットする必要があり、 (+) の付いている項目はHDMAの転送が始まったフレーム中に変更する必要がある。
モード値はDMAと同じだが、スキャンライン毎に1度だけ実行される。 One Register Write Once モードはスキャンライン毎に1バイトだけ、 One Register Write Twice モードではスキャンライン毎に2バイト書き込まれる。
スキャンライン毎にHDMAがアクティブになる度に (つまり、そのフレームで少なくとも1つは停止も終了もされていない時)、 マスターサイクルで~18のオーバーヘッドがかかる。 それぞれのチャネルは転送が実際に起こった場合、 スキャンラインごとに追加で8のオーバーヘッドがかかる。 (たぶんテーブルから0x42xAに値がロードされているだろう) 間接アドレスが変更される場合、ロード時に 16のマスターサイクルが必要になる。 そして、1バイトの転送ごとに8サイクルかかる。 結果として、HDMAはスキャンラインごとにマスターサイクルで 合計466サイクルの時間を必要とする。 (8チャネル全てがアクティブ、間接アドレスの変更、4バイトの転送が全て同時に起こった場合)
HDMAの動作には2つの段階があり、 最初の段階はフレーム開始時に (V(垂直)=0, H(水平)=約6)、 全てのアクティブなHDMAチャネルに対して発生する(0x420c 参照)。
CPUはこの動作の間停止される。 マスターサイクルで~18のオーバーヘッドがあり、 それぞれのチャネルが、直接モードのHDMAチャネルにセットされている時は8サイクル、 間接モードのHDMAチャネルにセットされている時は24サイクルが追加で必要となる。
フレーム開始後にHDMAを開始させた場合は基本的に、 間接モードチャネル用に 0x43x8 ~ 0x43xA、0x43x5 ~ 0x43x6 を使って 手動で初期化プロセスを実行する必要がある。 次のステップの4段階目の最初の1回は転送が行われないので注意すること。 それから、フレーム中にチャネルがすでに停止されていた場合、再スタートすることはできない。 (もしくはチャネルを有効にした時に4段階目が自動的に実行されてしまう??)
V=0 から V=0xe0 (オーバースキャンが有効の場合、V=0xef) の H=0x116 くらいの時に次の動作が始まる。
HDMAはV-Blank期間中は起こらない。 画面エフェクトは何も起こらないだろう。 フレーム開始時、(V-Blankの終了時)にアクティブなチャネルはリセットされる。 V-Blank中にHDMAレジスタを更新することで、 書き込み直後に転送されたり、PPUの状態を意図せず変更してしまったり というような、厄介な挙動を避けることができる。
今までHDMAテーブルというものが暗黙的に使われてきたが、 これは項目の配列を指し、行番号と繰り返しフラグから始まる。 繰り返しフラグがFalseの時、1スキャンライン分のデータと、 次の項目が始まる前までの行番号の入ったカウント値が続く。 繰り返しフラグがTrueの時、複数のスキャンラインのデータが続く。 このデータは、ポインタ値(間接HDMA)か即値(直接HDMA)を指す。
以上のことから、フレーム処理中にHDMAを開始する時に なぜ手動で「アドレス」、「繰り返し」、「行番号」を初期化しないと いけないのかが見えてくると思う。 これらはフレーム開始時に初期化されている。 「アドレス」、「繰り返し」、「行番号」はHDMAによって変更されるが、 「Aアドレス」は変更されないことに注意して欲しい。