- UID
- 61
- 阅读权限
- 60
- 精华
- 魅力
-
- 信用
-
- 注册时间
- 2007-6-24
- 在线时间
- 小时
- 最后登录
- 1970-1-1
|
楼主 |
发表于 2009-6-18 07:52
|
显示全部楼层
5.
Research / Megadrive Programming / DMA
Overview
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.
68k to VDP copy
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:
$13: L07 L06 L05 L04 L03 L02 L01 L00
$14: L15 L14 L13 L12 L11 L10 L08 L08
Length = number of bytes transferred / 2 (or >>1)
Next, you need to specify the source address (in 68k). Here's how you should set registers $15-$17:
$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
The source address is also shifted to the right by one (divided by 2).
Now, to begin the DMA, you write a longword command to the control port:
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
A15-A00 is the destination address in VRAM, VSRAM or CRAM.
CD2-CD0:
001 - VRAM
011 - CRAM
101 - VSRAM
After doing the above, the DMA will start and until it's done, 68000 will be frozen. For the lazy, the code:
;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)&$FF00)>>9),($C00004).l
move.w #$9300+(((length)&$FF)>>1),($C00004).l
move.w #$9600+(((source>>1)&$FF00)>>8),($C00004).l
move.w #$9500+((source>>1)&$FF),($C00004).l
move.w #$9700+((((source>>1)&$FF0000)>>16)&$7F),($C00004).l
move.l #($80+((dest&$3FFF)<<16)+((dest&$4000)>>14)+((x&$4)<<2)+((x&$3)<<30)),($C00004).l
If you're too lazy to even do that, use the calculator...
VRAM copy
This DMA is used to copy VRAM to VRAM.
Note: auto increment register ($F) has to be set to $01 before the DMA.
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:
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
A15-A00 - Destination address in VRAM
The code for the lazy:
move.w #$8F01,($C00004).l
move.w #$9400+(((copylength)&$FF00)>>9),($C00004).l
move.w #$9300+(((copylength)&$FF)>>1),($C00004).l
move.w #$9600+(((src)&$FF00)>>8),($C00004).l
move.w #$9500+((src)&$FF),($C00004).l
move.w #$97C0,($C00004).l
move.l #($C0+((dest&$3FFF)<<16)+((dest&$4000)>>14)),($C00004).l
move.w #$8F02,($C00004).l
VRAM fill
If you dreamed about filling VRAM with a random word, VRAM fill is for you. It fills VRAM with a specified byte:
Registers $14, $13 - how many bytes to fill
Register $17 - #$80
Register $F - #$01
After setting the registers, you have to write a command to the VDP:
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
A15-A00 - the address in VRAM where the fill will start
Finally, you have to write a word to the data port ($C00000). First byte is the byte that will be copied everywhere, the
other byte is written to the address (only once).
The code:
move.w #$8F01,($C00004).l
move.w #$9400+(((length)&$FF00)>>9),($C00004).l
move.w #$9300+(((length)&$FF)>>1),($C00004).l
move.w #$9780,($C00004).l
move.l #($40000080+((addr&$3FFF)<<16)+((addr&$4000)>>14)),($C00004).l
move.w #$xx00,($C00000).l
move.w #$8F02,($C00004).l
That's all folks. If you have problems with calculating all the stuff, use the calculator. |
|