Possible to DMA large amounts of data during vblank?

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
ndiddy
Posts: 33
Joined: Tue Oct 24, 2017 11:07 pm

Possible to DMA large amounts of data during vblank?

Post by ndiddy »

I have a mirror of the contents of one of my backgrounds in WRAM so I can change it and not have to worry about only writing to it in vblank. However, I'm running into strange timing errors where I'm not able to DMA my OAM mirror and my tilemap mirror in the vblank period (I'm assuming it's a timing error anyway, the amount of data that actually gets transferred seems to change depending on the number of nops I add to the vblank routine). If that's the case, and there's not enough time to transfer the whole mirror, how am I supposed to DMA it over in vblank? You don't have random access to VRAM so you can't just DMA using multiple channels with offsets, and interleaving the tilemap mirror seems like a huge pain. Any help would be appreciated.

In case I'm doing something wrong, here's my WRAM-VRAM macro:

Code: Select all

.macro WRAMToVRAM source, destination, size
	lda #$80
	sta $2115 ;word-access,increment by one
	ldx #destination
	stx $2116
	ldx #source
	stx $4312 ;dma source address
	lda #$7e
	sta $4314 ;bank
	ldx #size
	stx $4315
	lda #$18 ;dest = $2118, vram write register
	sta $4311
	lda #$1 ;word increment on dest, src increment
	sta $4310 
.endmacro
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Possible to DMA large amounts of data during vblank?

Post by koitsu »

Edit: ignore what I've written in this paragraph -- it's for NES, not SNES. VBlank on NTSC lasts somewhere between 2273 and 2387 CPU cycles. Reference: viewtopic.php?t=7878 -- this thread may interest you in other ways, such as how to visually display on-screen how much time something is taking through some cute/quirky methodologies (the NES can do this a bit easier, but there are ways on the SNES as well, such as, say, by changing the background colour palette entry to an alternate colour at the start of a routine, then back to what it originally was at the end of the routine. The thread I reference has some other methodologies though)

Anomie's timing doc outlines how long DMA takes per byte, however the cycle counts you see in that doc are not equivalent to CPU cycles.

nocash's SNES document probably has the answer as well, but may still require bits of math be done.

I can't remember how to do the whole "master cycle" to "CPU cycle" conversion ordeal. Someone else should be able to do the math for that (right now I am too lazy to go read + figure it out). Maybe nocash or someone else can provide that. (I should add: this is a very common question when doing NES or SNESdev -- "how much time is available in VBlank" + "how much time does X/Y/Z" take (esp. DMA), so it should be answered in such a way that is very friendly/easy for the software programmer to understand)

The macro you pasted is "general purpose", so how much time it takes is ultimately going to depend on the size argument.

Speaking generally: the bottom line is, with classic consoles, you cannot update an *entire screen* worth of data (including CHR, if applicable) in a single frame. I don't know if you're doing that, your post is simply too vague. The SNES is not designed for this (full layout + CHR data is the equivalent of full-motion video playback); it's designed so that you update only what needs to be changed. A lot of games that need large amounts of transfers do so across multiple frames (multiple NMIs), as long as visually it won't impact what you're trying to achieve; for example, if you're trying to update some tile map data for animating trees, maybe do some updates in one NMI, then the next do some more, essentially making the animation rate for the trees ~30fps. You get the idea. In general, you have to track/maintain all of this in software. Welcome to game development. :-)
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Possible to DMA large amounts of data during vblank?

Post by tepples »

Here are the numbers.

On Super NES, a scanline (minus DRAM refresh time) is 1324 master clocks.
A fast cycle is 6 master clocks. There are 220.7 fast cycles per line.
A slow cycle is 8 master clocks. There are 165.5 slow cycles per line.
DMA copies one byte per slow cycle.
On NTSC with overscan mode turned off, there are 262 - 224 = 38 scanlines in vblank. Subtract one scanline for prerender time, and you may end up with 165.5 * 37 = a smidge under 6 KiB per vblank.
This means you can replace one-third of the 16 KiB sprite tile area per vblank.

You can replace more if you force blanking in the top and bottom of the screen by changing the master rendering enable bit in $2100. Let's say you add 24 lines of letterbox on the top and bottom making the middle 176 pixels tall, which covers the entirety of a widescreen TV when zoomed in. In that case, you might be able to push (262-176-1)*165.5 = over 13.5 KiB.
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: Possible to DMA large amounts of data during vblank?

Post by psycopathicteen »

I had too write a lot of code just to get sprites to animate automatically without black bars. My game incorporates an animation frame delay feature if not all animated sprites can be updated on time. It even checks for duplicates, so if there are 4 animation frames of explosions but 20 explosion sprites onscreen, it would just use the duplicates.
User avatar
TOUKO
Posts: 306
Joined: Mon Mar 30, 2015 10:14 am
Location: FRANCE

Re: Possible to DMA large amounts of data during vblank?

Post by TOUKO »

psycopathicteen wrote:I had too write a lot of code just to get sprites to animate automatically without black bars. My game incorporates an animation frame delay feature if not all animated sprites can be updated on time. It even checks for duplicates, so if there are 4 animation frames of explosions but 20 explosion sprites onscreen, it would just use the duplicates.
I think this is the big mistake nintendo did,thinking a 8/16 kbytes of VRAM for sprites was enough :?
With all the VRAM available for sprites, everything (or at least most things) could have been easier .
ndiddy
Posts: 33
Joined: Tue Oct 24, 2017 11:07 pm

Re: Possible to DMA large amounts of data during vblank?

Post by ndiddy »

koitsu wrote:Speaking generally: the bottom line is, with classic consoles, you cannot update an *entire screen* worth of data (including CHR, if applicable) in a single frame. I don't know if you're doing that, your post is simply too vague. The SNES is not designed for this (full layout + CHR data is the equivalent of full-motion video playback); it's designed so that you update only what needs to be changed. A lot of games that need large amounts of transfers do so across multiple frames (multiple NMIs), as long as visually it won't impact what you're trying to achieve; for example, if you're trying to update some tile map data for animating trees, maybe do some updates in one NMI, then the next do some more, essentially making the animation rate for the trees ~30fps. You get the idea. In general, you have to track/maintain all of this in software. Welcome to game development. :-)
I figured that I would keep my scope small for my "first project" and make a game where you jump on randomly placed platforms and get powerups to increase your speed, that sorta thing. However, so far I've only done development on consoles where either the CPU is fast enough to DMA an entire tilemap over in one vblank or you can just access vram during draw without screwing stuff up, so this is kinda new for me. I guess that because I'd not be adding a new platform to more than one "screen" at once (I keep track of locations in the 64x64 tilemap as "screens" because of the strange way they're stored in memory), I can just make my DMA code only send over the screen where the last added platform was.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Possible to DMA large amounts of data during vblank?

Post by tepples »

You can certainly DMA a whole non-scrolling tile map. That's only 32*28*2 = 1792 bytes. You can also DMA in new columns or rows as the scrolling window reaches them. It's just DMAing in new tiles that might cause delay.
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: Possible to DMA large amounts of data during vblank?

Post by 93143 »

Do you mean you're using a maximum-sized 8 KB quad tilemap, and trying to DMA that into VRAM in one shot? Yeah, that's not going to fly without letterboxing.

Like tepples says, what most games did was update rows and columns as they scrolled into view. Since the screen is only 224 lines high, you don't actually need more than two "screens" worth of tilemap in VRAM for seamless scrolling if you do it right. Look into what $2115 does, and maybe take a second look at $2107-210A if you don't already know how to make the map smaller.
Last edited by 93143 on Thu Mar 22, 2018 9:53 pm, edited 1 time in total.
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: Possible to DMA large amounts of data during vblank?

Post by psycopathicteen »

You can turn off rendering between levels.
Post Reply