DMA Ending prematurely
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
-
- Posts: 775
- Joined: Mon Jul 02, 2012 7:46 am
DMA Ending prematurely
After getting my MSU-1 video player working, I'm trying to integrate it into a ROM hack, and I'm having issues with DMA transfers into VRAM ending prematurely. I've already disabled interrupts via stz $4200 and sei, and I'm inside of a forced blank, what else might cause this? Watching the VRAM viewer, I can see that data is getting uploaded into VRAM, it's just incomplete and not aligned properly, resulting in a seizure-inducing flash of random full-screen colors instead of the video I'm trying to play.
Re: DMA Ending prematurely
Can you give more details...
What settings are you giving the DMA transfer (ie, DMA registers) ?
What emulator are you using?
What settings are you giving the DMA transfer (ie, DMA registers) ?
What emulator are you using?
nesdoug.com -- blog/tutorial on programming for the NES
-
- Posts: 775
- Joined: Mon Jul 02, 2012 7:46 am
Re: DMA Ending prematurely
I'm using bsnes-plus and higan v101. Here is the relevant section of code. I can paste more if you need it. It works fine in my own standalone test ROM, but inserting it into the ROM hack results in almost nothing getting transferred in the first frame, and then subsequent frames which upload only about 1/4 of the data per frame seem to be mostly completing, but they're still getting cut short, as I can see that the tiles in VRAM are not aligned from one frame to the next (I have to use the VRAM viewer because nothing is visible on screen except a solid color that flashes rapidly, no tile data is visible).
Code: Select all
macro SCREEN_OFF() {
php
sep #$20
pha
lda #$80 // screen off
sta $2100 // brightness + screen enable register
pla
plp
}
macro SCREEN_ON() {
php
sep #$20
pha
lda #$0F // screen on, full brightness
sta $2100 // brightness + screen enable register
pla
plp
}
macro MSU_TO_VRAM(count) {
lda #$80
sta $2115 // VRAM single word transfer, word increment
ldx #$1809
stx $4300 // DMA destination: VMDATAL/VMDATAH, fixed source
ldx #{REG_MSU_DATA}// MSU-1 data read port
stx $4302 // Low DMA source address
lda #$00
sta $4304 // High DMA source address
ldx.w {count}
stx $4305 // Transfer 2048 bytes
lda #$01
sta $420B // Start DMA transfer
}
macro MSU_TO_CGRAM() {
stz $2121 // Start at color 0
ldx #$2208
stx $4300 // DMA destination: CGDATA, byte increment
ldx #{REG_MSU_DATA}// MSU-1 data read port
stx $4302 // Low DMA source address
lda #$00
sta $4304 // High DMA source address
ldx #$0200
stx $4305 // Transfer 512 bytes
lda #$01
sta $420B // Start DMA transfer
}
// First frame upload, almost nothing from this transfer gets uploaded
stz $4200
sei // Disable interrupts
SCREEN_OFF()
// Load tilemap and tile data
stz $2116
lda #$0C
sta $2117 // VRAM address $1800
tay
// MSU_TO_VRAM(#$9840)
lda #$03
sta $2105 // Set video mode 3, 8x8 tiles, 256 color BG1, 16 color BG2
lda #$0C
sta $2107 // Set BG1 tilemap offset to $1800 and size to 32x32
lda #$01
sta $210B // Set BG1 tile data offset to $2000
lda #$FF
sta $210E // Set BG1 scroll register
sta $210E
lda #$01
sta $212C // Enable BG1
// Load CGRAM via DMA transfer
// Only 3-4 palettes get transferred successfully here
MSU_TO_CGRAM()
// Wait for scanline 39
WAIT_FOR_SCANLINE(#39)
+; SCREEN_ON()
Re: DMA Ending prematurely
The only thing that can prematurely terminate DMA is HDMA running on the same channel. If you have stz $420c in your code, then that won't happen.
Otherwise, the only reason a transfer wouldn't complete would be due to VRAM writes during active display, but you already have bit 7 of $2100 set, so that is all you need there.
Otherwise, the only reason a transfer wouldn't complete would be due to VRAM writes during active display, but you already have bit 7 of $2100 set, so that is all you need there.
-
- Posts: 775
- Joined: Mon Jul 02, 2012 7:46 am
Re: DMA Ending prematurely
That did the trick, thanks!byuu wrote:If you have stz $420c in your code, then that won't happen.
Re: DMA Ending prematurely
I'm running into a similar issue with my MSU player, after triggering DMA by writing to $420b the SNES sometimes just doesn't do the DMA transfer. It does its preparation stuff (halt the CPU, assert some seemingly random address) but then resumes CPU operation without copying a single byte of data.
I wonder if that's a same-cycle collision with HDMA or something but I am definitely using separate channels for DMA and HDMA exclusively. Definitely need to check this more thoroughly. Turning off HDMA fixes this every time but it's not a real alternative...
I wonder if that's a same-cycle collision with HDMA or something but I am definitely using separate channels for DMA and HDMA exclusively. Definitely need to check this more thoroughly. Turning off HDMA fixes this every time but it's not a real alternative...
Re: DMA Ending prematurely
I'm not a SNES expert but if you are testing on a real SNES there is a bug affecting first revisions where HDMA and DMA could not be used at same time. The solution is to not use HDMA and DMA at same time, or to have very cleverly designed code so timing avoid conflict between the 2 (but that seems to be very complicated from what i read here and there).
Re: DMA Ending prematurely
I know, it happens to me on all revisions though