Super NES Programming/DMA tutorial
From Wikibooks, the open-content textbooks collection
Direct memory access is a process whereby memory is dynamically copied to another location, independantly 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.
Contents |
[edit] DMA registers
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.
[edit] some code
[edit] Loading Palettes
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
[edit] Loading VRAM
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 php rep #$20 ; 16bit A 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 lda #:\1 ; bank address of data in memory sta $4304 lda #$80 sta $2115 ; VRAM address increment value designation lda #$01 sta $4300 ; 1= word increment lda #$18 sta $4301 ; 2118 is the VRAM gate lda #$01 ; turn on bit 1 (channel 0) of DMA sta $420b plp pla .endm