From: LAY@uk.tele.nokia.fi To: "Super Famicom Development Group" 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.