DMA Ending prematurely

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
DMA Ending prematurely
by on (#181084)
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
by on (#181085)
Can you give more details...
What settings are you giving the DMA transfer (ie, DMA registers) ?

What emulator are you using?
Re: DMA Ending prematurely
by on (#181086)
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:
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
by on (#181088)
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.
Re: DMA Ending prematurely
by on (#181090)
byuu wrote:
If you have stz $420c in your code, then that won't happen.


That did the trick, thanks!
Re: DMA Ending prematurely
by on (#181105)
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...
Re: DMA Ending prematurely
by on (#181114)
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
by on (#181115)
I know, it happens to me on all revisions though :)