DMA Ending prematurely

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
qwertymodo
Posts: 775
Joined: Mon Jul 02, 2012 7:46 am

DMA Ending prematurely

Post by qwertymodo »

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.
User avatar
dougeff
Posts: 3080
Joined: Fri May 08, 2015 7:17 pm

Re: DMA Ending prematurely

Post by dougeff »

Can you give more details...
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
qwertymodo
Posts: 775
Joined: Mon Jul 02, 2012 7:46 am

Re: DMA Ending prematurely

Post by qwertymodo »

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()
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: DMA Ending prematurely

Post by Near »

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.
qwertymodo
Posts: 775
Joined: Mon Jul 02, 2012 7:46 am

Re: DMA Ending prematurely

Post by qwertymodo »

byuu wrote:If you have stz $420c in your code, then that won't happen.
That did the trick, thanks!
User avatar
ikari_01
Posts: 141
Joined: Sat Jul 04, 2009 2:28 pm
Location: Wunstorf, Germany

Re: DMA Ending prematurely

Post by ikari_01 »

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...
Stef
Posts: 263
Joined: Mon Jul 01, 2013 11:25 am

Re: DMA Ending prematurely

Post by Stef »

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).
User avatar
ikari_01
Posts: 141
Joined: Sat Jul 04, 2009 2:28 pm
Location: Wunstorf, Germany

Re: DMA Ending prematurely

Post by ikari_01 »

I know, it happens to me on all revisions though :)
Post Reply