codeslinger.co.uk

Gameboy - DMA

Direct Memory Access:

As explained in the LCD chapter the CPU can only access the Sprite Attributes table during the duration of one of the LCD modes (mode 2). The Direct Memory Access (DMA) is a way of copying data to the sprite RAM at the appropriate time removing all responsibility from the main program.

The game launches a DMA when it attempts to write to memory address 0xFF46 so we need to add the following to WriteMemory to trap writing to this address:

else if (address == 0xFF46)
{
   DoDMATransfer(data) ;
}

Implementation of the DMA Transfer:

The code behind the DMA transfer is really very simple but to understand what is needed can be a little tricky. As mentioned earlier the destination address of the DMA is the sprite RAM between memory adddress (0xFE00-0xFE9F) which means that a total of 0xA0 bytes will be copied to this region. The source address is represented by the data being written to address 0xFF46 except this value is the source address divided by 100. So to get the correct start address it is the data being written to * 100 (to make it faster instead of multiplying by 100 we will shift left 8 places, it is the same thing). Now we have all the information to write the DoDMATransfer function like so:

void Emulator::DoDMATransfer(BYTE data)
{
   WORD address = data << 8 ; // source address is data * 100
   for (int i = 0 ; i < 0xA0; i++)
   {
     WriteMemory(0xFE00+i, ReadMemory(address+i)) ;
   }
}

Thats all there is to DMA. The next chapter is on Graphics Emulation. You may want to grab a sandwich and a coke before you start that one.