Difference between revisions of "Sega Mega Drive/DMA"

From Sega Retro

Line 27: Line 27:
 
Sending the following longword to the [[Sega Mega Drive/VDP general usage#Control port|control port]] will both set the target VRAM/CRAM/VSRAM address and trigger the DMA:
 
Sending the following longword to the [[Sega Mega Drive/VDP general usage#Control port|control port]] will both set the target VRAM/CRAM/VSRAM address and trigger the DMA:
  
{{bitfield|CD1|1|A13-A8;6}}{{bitfield|A7-A0;8}}{{bitfield|0|0|0|0|0|0|0|0}}{{bitfield|1|0|CD3|CD2|0|0|A15|A14}}
+
{{bitfield|CD1|1|A13-A8;6}}{{bitfield|A7-A0;8}}{{bitfield|0|0|0|0|0|0|0|0}}{{bitfield|1|0|0|CD2|0|0|A15|A14}}
 
* '''A15-A0:''' VRAM/CRAM/VSRAM address.
 
* '''A15-A0:''' VRAM/CRAM/VSRAM address.
 
* '''CD2-CD1:''' 00 = VRAM; 01 = CRAM; 10 = VSRAM.
 
* '''CD2-CD1:''' 00 = VRAM; 01 = CRAM; 10 = VSRAM.
Line 46: Line 46:
 
| <tt>move.l #$40000090+($zz<<16),($C00004).l</tt>
 
| <tt>move.l #$40000090+($zz<<16),($C00004).l</tt>
 
|}
 
|}
 +
 +
==VRAM to VRAM copy==
 +
===1: Set length and source===
 +
[[Sega Mega Drive/VDP registers|Registers]] $13 and $14 set the DMA length:
 +
 +
{{bitfield|L7-L0;8}}{{bitfield|H7-H0;8}}
 +
* '''L7-L0:''' Low byte of DMA length in bytes, divided by 2.
 +
* '''H7-H0:''' High byte of DMA length in bytes, divided by 2.
 +
 +
Registers $15, $16 and $17 set the DMA source (VRAM address):
 +
 +
{{bitfield|L7-L0;8}}{{bitfield|H7-H0;8}}{{bitfield|1|1|0|0|0|0|0|0}}
 +
* '''L7-L0:''' Low byte of DMA source address.
 +
* '''H7-H0:''' High byte of DMA source address.
 +
 +
The following code will set the appropriate registers:
 +
 +
: <tt>move.w #$8F01,($c00004).l</tt>
 +
: <tt>move.w #$9300+(($xxxx>>1)&$FF),($c00004).l</tt><br><tt>move.w #$9400+((($xxxx>>1)&$FF00)>>8),($c00004).l</tt>
 +
: <tt>move.w #$9500+($yyyy&$FF),($c00004).l</tt><br><tt>move.w #$9600+(($yyyy&$FF00)>>8),($c00004).l</tt><br><tt>move.w #$97C0,($c00004).l</tt>
 +
 +
===2: Set destination===
 +
Sending the following longword to the [[Sega Mega Drive/VDP general usage#Control port|control port]] will both set the target VRAM address and trigger the DMA:
 +
 +
{{bitfield|0|0|A13-A8;6}}{{bitfield|A7-A0;8}}{{bitfield|0|0|0|0|0|0|0|0}}{{bitfield|1|1|0|0|0|0|A15|A14}}
 +
* '''A15-A0:''' VRAM address.
 +
 +
The following code will set the target VRAM address and trigger the DMA:
 +
 +
: <tt>move.l #$000000C0+(($zzzz&$3FFF)<<16)+(($zzzz&$C000)>>14),($C00004).l</tt>
  
 
[[Category:Sega Mega Drive|DMA]]
 
[[Category:Sega Mega Drive|DMA]]
 
[[Category:Unofficial documentation]]
 
[[Category:Unofficial documentation]]

Revision as of 16:06, 9 June 2018

DMA (Direct Memory Access) is a method for transfering data from the 68k RAM or ROM to VRAM, CRAM or VSRAM without needing to write code to send it via the data port. It can also be used to fill VRAM with a specified value, or perform a VRAM to VRAM copy.

DMA is generally faster than the equivalent 68k code, though during transfer the 68k CPU is frozen. For this reason, it is recommended only to use DMA during VBlank. The 68k is not frozen during VRAM fill and VRAM to VRAM copy operations, and the Z80 CPU will run as normal during any DMA operation unless it attempts to access the bus.

68k to VRAM/CRAM/VSRAM copy

1: Set length and source

Registers $13 and $14 set the DMA length:

7
6
5
4
3
2
1
0

L7-L0
7
6
5
4
3
2
1
0

H7-H0
  • L7-L0: Low byte of DMA length in bytes, divided by 2.
  • H7-H0: High byte of DMA length in bytes, divided by 2.

Registers $15, $16 and $17 set the DMA source (68k address in RAM, ROM or SRAM):

7
6
5
4
3
2
1
0

L7-L0
7
6
5
4
3
2
1
0

M7-M0
7
6
5
4
3
2
1
0

0
H6-H0
  • L7-L0: Low byte of DMA source address, divided by 2.
  • M7-M0: Middle byte of DMA source address, divided by 2.
  • H6-H0: High byte of DMA source address, divided by 2.

The following code will set the appropriate registers:

move.w #$8F02,($c00004).l
move.w #$9300+(($xxxx>>1)&$FF),($c00004).l
move.w #$9400+((($xxxx>>1)&$FF00)>>8),($c00004).l
move.w #$9500+(($yyyyyy>>1)&$FF),($c00004).l
move.w #$9600+((($yyyyyy>>1)&$FF00)>>8),($c00004).l
move.w #$9700+((($yyyyyy>>1)&$7F0000)>>16),($c00004).l

2: Set destination

Sending the following longword to the control port will both set the target VRAM/CRAM/VSRAM address and trigger the DMA:

7
6
5
4
3
2
1
0

CD1
1
A13-A8
7
6
5
4
3
2
1
0

A7-A0
7
6
5
4
3
2
1
0

0
0
0
0
0
0
0
0
7
6
5
4
3
2
1
0

1
0
0
CD2
0
0
A15
A14
  • A15-A0: VRAM/CRAM/VSRAM address.
  • CD2-CD1: 00 = VRAM; 01 = CRAM; 10 = VSRAM.
Memory space CD2-CD1 Code
VRAM 00 move.l #$40000080+(($zzzz&$3FFF)<<16)+(($zzzz&$C000)>>14),($C00004).l
CRAM 01 move.l #$C0000080+($zz<<16),($C00004).l
VSRAM 10 move.l #$40000090+($zz<<16),($C00004).l

VRAM to VRAM copy

1: Set length and source

Registers $13 and $14 set the DMA length:

7
6
5
4
3
2
1
0

L7-L0
7
6
5
4
3
2
1
0

H7-H0
  • L7-L0: Low byte of DMA length in bytes, divided by 2.
  • H7-H0: High byte of DMA length in bytes, divided by 2.

Registers $15, $16 and $17 set the DMA source (VRAM address):

7
6
5
4
3
2
1
0

L7-L0
7
6
5
4
3
2
1
0

H7-H0
7
6
5
4
3
2
1
0

1
1
0
0
0
0
0
0
  • L7-L0: Low byte of DMA source address.
  • H7-H0: High byte of DMA source address.

The following code will set the appropriate registers:

move.w #$8F01,($c00004).l
move.w #$9300+(($xxxx>>1)&$FF),($c00004).l
move.w #$9400+((($xxxx>>1)&$FF00)>>8),($c00004).l
move.w #$9500+($yyyy&$FF),($c00004).l
move.w #$9600+(($yyyy&$FF00)>>8),($c00004).l
move.w #$97C0,($c00004).l

2: Set destination

Sending the following longword to the control port will both set the target VRAM address and trigger the DMA:

7
6
5
4
3
2
1
0

0
0
A13-A8
7
6
5
4
3
2
1
0

A7-A0
7
6
5
4
3
2
1
0

0
0
0
0
0
0
0
0
7
6
5
4
3
2
1
0

1
1
0
0
0
0
A15
A14
  • A15-A0: VRAM address.

The following code will set the target VRAM address and trigger the DMA:

move.l #$000000C0+(($zzzz&$3FFF)<<16)+(($zzzz&$C000)>>14),($C00004).l