<span class="section">Overview</span><br><br>
What's DMA? DMA stands for Direct Memory Access. There are 3 types of
DMA: 68k memory to VDP memory copy, VDP memory to VDP memory copy, VDP
memory fill.<br><br><br>


<span class="section">68k to VDP copy</span><br><br>
It's used to copy data from 68000 memory (meaning ROM, SRAM, RAM etc.,
all 68k memory =P) to VDP memory (Video RAM, Vertical Scroll RAM or
Color RAM). Remember to set the auto increment register ($F) to $2
before doing this. First, you need to specify the DMA length using
registers $13 and $14:<br><br>

<pre>$13: L07 L06 L05 L04 L03 L02 L01 L00
$14: L15 L14 L13 L12 L11 L10 L08 L08
</pre>

Length = number of bytes transferred / 2 (or &gt;&gt;1)<br><br>

Next, you need to specify the source address (in 68k). Here's how you should set registers $15-$17:<br><br>

<pre>$15: S08 S07 S06 S05 S04 S03 S02 S01
$16: S16 S15 S14 S13 S12 S11 S10 S09
$17:  0  S23 S22 S21 S20 S19 S18 S17
</pre>

The source address is also shifted to the right by one (divided by 2).<br><br>

Now, to begin the DMA, you write a longword command to the control port:<br><br>

<pre>Bits 31-24:  CD1 CD0 A13 A12 A11 A10 A09 A08
Bits 23-16:  A07 A06 A05 A04 A03 A02 A01 A00
Bits 15-08:   0   0   0   0   0   0   0   0 
Bits 07-00:   1   0   0  CD2  0   0  A15 A14
</pre>

A15-A00 is the destination address in VRAM, VSRAM or CRAM.<br><br>
CD2-CD0:<br><br>
001 - VRAM<br>
011 - CRAM<br>
101 - VSRAM<br><br>

After doing the above, the DMA will start and until it's done, 68000 will be frozen. For the lazy, the code:<br><br>

<pre class="68k">;length = length (original, not shifted)
;source = source addr (not shifted)
;dest = destination addr
;x = %001 if VRAM, %011 if CRAM, %101 if VSRAM
;
;btw, you can just write it like that:

length = $100	;etc.

		move.w	#$9400+(((length)&amp;$FF00)&gt;&gt;9),($C00004).l
		move.w	#$9300+(((length)&amp;$FF)&gt;&gt;1),($C00004).l
		
		move.w	#$9600+(((source&gt;&gt;1)&amp;$FF00)&gt;&gt;8),($C00004).l
		move.w	#$9500+((source&gt;&gt;1)&amp;$FF),($C00004).l
		move.w	#$9700+((((source&gt;&gt;1)&amp;$FF0000)&gt;&gt;16)&amp;$7F),($C00004).l

move.l	#($80+((dest&amp;$3FFF)&lt;&lt;16)+((dest&amp;$4000)&gt;&gt;14)+((x&amp;$4)&lt;&lt;2)+((x&amp;$3)&lt;&lt;30)),($C00004).l


</pre>

If you're too lazy to even do that, use the calculator...

<br><br><br>
<span class="section">VRAM copy</span><br><br>
This DMA is used to copy VRAM to VRAM. <br><br>
Note: auto increment register ($F) has to be set to $01 before the DMA.<br><br>
Register $14 contains the higher 8 bits of fill length (shifted by one
to the right), register $13 contains the lower 8 bits. Registers $16
and $15 are the source address in VRAM. Register $17 has to be set to
$C0. The DMA is started when this command is written to the
VDP:<br><br>
<pre>Bits 31-24:  0   0  A13 A12 A11 A10 A09 A08
Bits 23-16: A07 A06 A05 A04 A03 A02 A01 A00
Bits 15-08:  ?   ?   ?   ?   ?   ?   ?   ?
Bits 07-00:  1   1   0   0   ?   ?  A15 A14
</pre>
A15-A00 - Destination address in VRAM
<br><br>
The code for the lazy:<br><br>

<pre class="68k">		move.w	#$8F01,($C00004).l
		
		move.w	#$9400+(((copylength)&amp;$FF00)&gt;&gt;9),($C00004).l
		move.w	#$9300+(((copylength)&amp;$FF)&gt;&gt;1),($C00004).l
		
		move.w	#$9600+(((src)&amp;$FF00)&gt;&gt;8),($C00004).l
		move.w	#$9500+((src)&amp;$FF),($C00004).l
		
		move.w	#$97C0,($C00004).l
		
		move.l	#($C0+((dest&amp;$3FFF)&lt;&lt;16)+((dest&amp;$4000)&gt;&gt;14)),($C00004).l
		
		move.w	#$8F02,($C00004).l</pre>
		
<span class="section">VRAM fill</span><br><br>

If you dreamed about filling VRAM with a random word, VRAM fill is for you. It fills VRAM with a specified byte:<br><br>
Registers $14, $13 - how many bytes to fill<br>
Register $17 - #$80<br>
Register $F - #$01<br><br>
After setting the registers, you have to write a command to the VDP:<br><br>
<pre>Bits 31-24:  0   1  A13 A12 A11 A10 A09 A08
Bits 23-16: A07 A06 A05 A04 A03 A02 A01 A00
Bits 15-08:  ?   ?   ?   ?   ?   ?   ?   ? 
Bits 07-00:  1   0   0   0   ?   ?  A15 A14
</pre>
<br><br>
A15-A00 - the address in VRAM where the fill will start<br><br>
Finally, you have to write a word to the <b>data port</b> ($C00000). First byte is the byte that will be copied everywhere, the
other byte is written to the address (only once).<br><br>

The code:<br><br>
<pre class="68k">		move.w	#$8F01,($C00004).l
		
		move.w	#$9400+(((length)&amp;$FF00)&gt;&gt;9),($C00004).l
		move.w	#$9300+(((length)&amp;$FF)&gt;&gt;1),($C00004).l
		
		move.w	#$9780,($C00004).l
		
		move.l	#($40000080+((addr&amp;$3FFF)&lt;&lt;16)+((addr&amp;$4000)&gt;&gt;14)),($C00004).l
		
		move.w	#$xx00,($C00000).l
		
		move.w	#$8F02,($C00004).l
</pre>

That's all folks. If you have problems with calculating all the stuff, use the calculator.