# HDMA ゲームボーイは(OAMに対して)DMA転送を行う機能を備えていますが、ゲームボーイカラーでは、さらにHDMAというDMA転送が使えます。 DMA転送は[別のページ](../video/oam/dma.md)で説明しています。 HDMA転送には - 汎用DMA(GDMA) - HBlank DMA という2つの転送モードがあります。これらのモードについては下の[HDMA制御レジスタ](#ff55---hdma5---hdma制御レジスタ-w)で詳しく説明しています。 ## レジスタ ### FF51 - HDMA1 - HDMAソースレジスタ上位8bit (W) ### FF52 - HDMA2 - HDMAソースレジスタ下位8bit (W) これらの2つのレジスタは、HDMA転送でデータを読み出す際のアドレスを指定します。 通常は、ROM、SRAM、WRAMのいずれかで、`0x0000..7FF0`または`0xA000..DFF0`の範囲で指定します。VRAMを指定しようとすると、ゴミがコピーされてしまいます。Echo RAM、OAM、FEXX、IO、HRAMを指定した時の挙動は不明です。 このアドレスの下位4bitは無視され、0として扱われます。 ### FF53 - HDMA3 - HDMAターゲットレジスタ上位8bit (W) ### FF54 - HDMA4 - HDMAターゲットレジスタ下位8bit (W) これらの2つのレジスタは、HDMA転送によるデータのコピー先となるアドレスを`0x8000..9FF0`の範囲で指定します。 bit4-12のみが利用され、他のbitは無視されます。 bit13-15は`0b100`、bit0-3は`0b0000`として、レジスタのbit4-12と合わせてターゲットアドレスとなります。 ### FF55 - HDMA5 - HDMA制御レジスタ (W) このレジスタに書き込むとHDMA転送が開始されます。 下位7bitは転送サイズ(10hで割った値から1を引いた値)を指定し、つまり、`$00..7F`の値で`$10..800`バイトの長さを定義することができます。 MSB(bit7)は、転送モードを示します。 **bit7が0のとき(汎用DMA, GDMA)** この転送方法では、すべてのデータが一度に転送されます。 転送が完了するまで、プログラムの実行は停止します。なお、汎用DMAは、LCDコントローラがVRAMにアクセス中であっても、それをチェックすることなくデータのコピーを試みます。 そのため、汎用DMAは、ディスプレイが無効な場合、VBlank中、または(かなり短いブロックの)HBlank中にのみ使用する必要があります。 転送が完了すると、プログラムの実行が再開され、`0xFF55`には`$FF`が格納されます。 **bit7が1のとき(HBlank DMA)** HBlank DMAは、各HBlankの間に10hバイトのデータを転送します。VBlankの間はデータが転送されませんが、その後`LY=00`に戻ると転送が再開されます。 転送中は毎回プログラムの実行が停止しますが、各データブロック間のスペースではプログラムの実行が継続されます。 なお、転送が完了するまで、プログラムは転送先のVRAMバンク(`0xFF4F`)や転送元のROM/RAMバンク(バンクを持ったメモリからデータを転送する場合)を変更してはいけません。 レジスタ`0xFF55`を読み出すと、残りの長さ(16で割った値から1を引いた値)が返され、`$FF`の値が読み出された場合は転送が完了したことを示します。 また、`0xFF55`の7bit目に`0`を書き込むことで、アクティブなHBlank転送を終了させることができます。この場合、`0xFF55`を読み出すと下位7bitに残りの転送サイズが返されますが、bit7は1として読み出されます。 ``` Note: HBlank期間中(モード0)にHBlank DMAを開始(FF55への書き込み)してはいけません。 ``` ``` Note: 転送先のアドレスがオーバーフローした場合、転送は途中で停止します。(停止後の状態は不明) ``` ## その他 ### 転送がアクティブであることを確認するには `0xFF55`のbit7を読むことで、DMA転送がアクティブかどうかを確認することができます。0ならアクティブ、1ならアクティブではありません。 これは、汎用またはHBlank転送の完了後や、およびHBlank転送を手動で終了した後など、どのような状況でも機能します。 ### 転送のタイミング 16バイトのデータ(ブロック)を転送するのに、通常速モード、倍速モードともに約8μsかかります。 つまり、通常速では8 [M-cycles](../cpu/cycle.md)、倍速では16 [M-cycles](../cpu/cycle.md)となります。 MBC1~3のような古いMBCコントローラや、遅い(?)ROMでは、汎用DMAやHBlank DMAのサポートが保証されていません。 これは、自身のプログラムが通常速モードで動作していても、1μsあたり常に2バイトの転送、(つまり倍速レベルのスペックが求められる)が行われるためです。