Super NES Programming/DMA tutorial

From Wikibooks, open books for an open world
Jump to: navigation, search

Direct memory access is a process whereby memory is dynamically copied to another location, independently of the CPU. In any modern computer, DMA is an essential requirement. Relating to the SNES, DMA can be used to quickly copy tile and palette data to the video RAM. Knowledge of DMA is a requirement for creating larger SNES programs, so this tutorial will cover just that.

DMA is used for copying graphics data, such as 8x8 tiles and tile maps, to the video RAM(VRAM), and palette data to the CGRAM. These locations can only be accessed by reading or writing to certain registers repeatedly. Note that while this could more easily be accomplished without using DMA, it would be several times slower.

When the DMA process is initialized, the CPU is halted until the DMA is complete. There are in total 8 DMA channels, but for the purposes of simply loading palette or graphics data, only one channel is necessary.

NOTE: This tutorial is incomplete and untested.

DMA registers[edit]

where x is from 0 to 7.

size address description
Byte $420B DMA Control Register
Byte $43x0 DMA channel x control register
Byte $43x1 DMA channel x destination($21xx)
Word $43x2 DMA channel x source address offset(low)
Word $43x3 DMA channel x source address offset(high)
Byte $43x4 DMA channel x source address bank
Word $43x5 DMA channel x transfer size(low)
Word $43x6 DMA channel x transfer size(high)

NOTE: A DMA channel's transfer size, when set to #$0000, is read as a transfer of 65536 bytes, not 0 bytes.

some code[edit]

Loading Palettes[edit]

Here is a macro for loading a palette data into the CGRAM(the place where palettes are stored):

 ;macro for loading palette data into the CGRAM
 ;only use if SIZE is less than 256 bytes
 ;syntax SetPalette LABEL CGRAM_ADDRESS SIZE
 .macro SetPalette
 pha
 php
 
 rep	#$20		; 16bit A
 lda	#\3
 sta	$4305		; # of bytes to be copied
 lda	#\1		; offset of data into 4302, 4303
 sta	$4302
 sep	#$20		; 8bit A
 
 lda	#:\1		; bank address of data in memory(ROM)
 sta	$4304	
 lda	#\2
 sta	$2121		; address of CGRAM to start copying graphics to
 
 stz	$4300		; 0= 1 byte increment (not a word!)
 lda	#$22
 sta	$4301		; destination 21xx   this is 2122 (CGRAM Gate)
 
 lda	#$01		; turn on bit 1 (corresponds to channel 0) of DMA channel reg.
 sta	$420b		;   to enable transfer
 
 plp
 pla
 .endm

Loading VRAM[edit]

Here is a macro for loading a data into the VRAM(the place where tiles and tile maps are stored):

 ;macro for loading graphics data into the VRAM
 ;only use if SIZE is less than 256 bytes
 ;syntax LoadVRAM LABEL  VRAM_ADDRESS  SIZE
 .macro LoadVRAM
 pha
 phy
 php
 
 rep	#$20		; 16bit A
 sep	#$10		; 8bit Y
 ldy	#$80
 sty	$2115		; VRAM address increment value designation
 lda	#\2
 sta	$2116		; address for VRAM write(or read)
 lda	#\3
 sta	$4305		; number of bytes to be copied
 sep	#$20		; 8bit A
 lda	#\1		
 sta	$4302		; data offset in memory
 
 ldy	#:\1		; bank address of data in memory
 sty	$4304	
 ldy	#$01
 sty	$4300		; 1= word increment
 ldy	#$18
 sty	$4301		; 2118 is the VRAM gate
 
 ldy	#$01		; turn on bit 1 (channel 0) of DMA
 sty	$420b
 
 plp
 ply
 pla
 .endm