161 lines
5.4 KiB
Plaintext
161 lines
5.4 KiB
Plaintext
From: LAY@uk.tele.nokia.fi
|
|
To: "Super Famicom Development Group" <famidev@busop.cit.wayne.edu>
|
|
Subject: RE: Assorted questions...
|
|
|
|
>> 2) I asked a question before about HDMA, and I got replies saying that
|
|
>> it has something to do with the horizontal interrupt or horizontal
|
|
>> blank time (I forget which). Later on I saw people talking about
|
|
>> HDMA "channels". Could someone please tell me what the "channels"
|
|
>> are used for, or are they another name for a register or a memory
|
|
>> storage location?
|
|
|
|
It's probably best to start by explaning "normal" DMA. The SNES
|
|
supports 8 DMA channels which allow data to be copied to VRAM
|
|
extremely quickly, bypassing the 65c816 processor. Each channel
|
|
consists of the following registers.
|
|
|
|
Byte $43?0 DMA channel ? control register
|
|
Byte $43?1 DMA channel ? destination
|
|
Word $43?2 DMA channel ? source address offset
|
|
Byte $43?4 DMA channel ? source address bank
|
|
Word $43?5 DMA channel ? transfer bytes
|
|
|
|
where ? is 0..7
|
|
|
|
A value of $01 written to the DMA channel control register at
|
|
$43?0 indicates that we're using "normal" DMA. The graphics
|
|
register destination is formed by using $21 as the high byte
|
|
of the address and using the byte specified at $43?1 as the
|
|
low byte. Hence you can DMA to any of the graphics registers
|
|
between $2100..$21FF.
|
|
|
|
There is also a DMA control register.
|
|
|
|
Byte $420B DMA control register
|
|
|
|
Here bit 0 enables channel 0, bit 1 enables channel 1 etc...
|
|
|
|
For example, suppose I wanted to copy a 32 x 32 character
|
|
screen map (ie. $800 bytes) from location $18000 in ROM into
|
|
location $0000 of VRAM. I could do this using DMA channel 0
|
|
with the following code (A is 8-bits, X & Y are 16-bits).
|
|
|
|
ldx.w #$0000 ; set VRAM pointer to $0000
|
|
stx $2116
|
|
lda #$01 ; control value for "normal" DMA
|
|
sta $4300
|
|
lda #$18 ; dma to $2118
|
|
sta $4301
|
|
ldx.w #$8000 ; source offset
|
|
stx $4302
|
|
lda #$01 ; source bank
|
|
sta $4304
|
|
ldx.w #$0800 ; number of bytes
|
|
stx $4305
|
|
lda #$01 ; enable DMA channel 0
|
|
sta $420B
|
|
|
|
And that's all there is to it. After completion of the last
|
|
instruction "sta $420B" the $800 bytes at $18000 will have
|
|
been copied into VRAM at location $0000.
|
|
|
|
HDMA allows you to use any combination of these DMA channels
|
|
to modify graphics registers just before the start of every
|
|
horizontal scan line.
|
|
|
|
To use HDMA you have to write a value of $00 or $02 to the
|
|
DMA channel control register at $43?0 to indicate "horizontal"
|
|
DMA. Writing $00 indicates a byte is to be DMA'd each scan
|
|
line, writing $02 indicates a word. The DMA channel destination
|
|
at $43?1 works just as before with "normal" DMA. The source
|
|
address offset and bank registers at $43?2 & $43?4 will point
|
|
to a HDMA table. The transfer bytes register at $43?5 is not
|
|
used.
|
|
|
|
The format of the HDMA table depends on the value you have
|
|
written to the DMA channel control register. If you have
|
|
written $00 then a byte will be written to the selected
|
|
graphics register each scan line. The table should have the
|
|
following format.
|
|
|
|
hdma_table
|
|
Byte n ; number of bytes that follow (7-bit value 0..127)
|
|
Byte value_1, value_2, value_3 ... value_n
|
|
Byte n ; number of bytes that follow (7-bit value 0..127)
|
|
Byte value_1, value_2, value_3 ... value_n
|
|
.
|
|
etc
|
|
.
|
|
Byte 0 ; ends list
|
|
|
|
The table is made up of a number of entries. The first byte
|
|
in each entry is a count on the number of bytes that follow.
|
|
The table is terminated by a 0 entry.
|
|
|
|
If you have written $02 to the DMA channel control register
|
|
then a word will be written to the selected graphics register
|
|
each scan line. The table should have the following format.
|
|
|
|
hdma_table
|
|
Byte n ; # times to repeat next word (7-bit value 0..127)
|
|
Word value
|
|
Byte n ; # times to repeat next word (7-bit value 0..127)
|
|
Word value
|
|
.
|
|
etc
|
|
.
|
|
Byte 0 ; ends list
|
|
|
|
The table is made up of a number of entries. The first byte of
|
|
each entry indicates the number of times the following word is
|
|
to be repeated. The table is terminated by a 0 entry.
|
|
|
|
The only other thing you'll need to know is that there is a
|
|
HDMA control register.
|
|
|
|
Byte $420C HDMA control register
|
|
|
|
This is the same format as the DMA control register at $420B,
|
|
ie. bit 0 enables HDMA channel 0, bit 1 enables channel 1 etc...
|
|
|
|
For example, suppose halfway down the screen I want to scroll
|
|
graphics plane 0 left by 128 pixels.
|
|
|
|
lda #$02 ; word format HDMA (count, word)
|
|
sta $4300
|
|
lda #$0D ; plane 0 x-scroll at $210D
|
|
sta $4301
|
|
ldx.w #hdma_table&$FFFF ; hdma table offset
|
|
stx $4302
|
|
lda #hdma_table/$10000 ; hdma table bank
|
|
sta $4304
|
|
lda #$01 ; enable HDMA channel 0
|
|
sta $420c
|
|
|
|
.
|
|
.
|
|
.
|
|
|
|
hdma_table
|
|
dc.b 112 ; for first 112 scan lines
|
|
dc.w 0 ; set plane 0 x-scroll to 0
|
|
dc.b 1 ; on next scan line
|
|
dc.w 128 ; set plane 0 x-scroll to 128
|
|
dc.b 0
|
|
|
|
You can use HDMA channels in combination, ie. you could use HDMA
|
|
channel 0 to select a colour register and HDMA channel 1 to write
|
|
the RGB data for that colour register.
|
|
|
|
I don't have access to any of the official Nintendo documentation
|
|
so I may not have entirely understood everything about HDMA but
|
|
this is a much as I've been able to work out. Maybe there are other
|
|
(H)DMA modes too?
|
|
|
|
I'll should have put a simple HDMA demo with source code on the
|
|
busop.cit.wayne.edu ftp site (in pub/famidev/incoming/hdmademo.zip).
|
|
|
|
Hope that helps.
|
|
|
|
Paul.
|