This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Sprite mulitplexing / raster effects?

Sprite mulitplexing / raster effects?
by on (#90040)
Is it possible and stable on real hardware to do raster effects with sprites on the NES? Can you change position or other attributes mid frame via $2003/$2004?

When can you change individual sprite positions during a scan line (not via dma)? I read some PPU cycles are dedicated to backgrouns and some to sprites per scan line, but I wonder how it applies?

by on (#90041)
I doubt that sprite multiplexing or raster effects are possibly on the NES, or reliable at least. Even simplest code that sets position of a sprite directly, without DMA, leads to problems on the HW.

by on (#90043)
You can't do sprite raster effects, since the PPU itself is accessing the OAM all the time. (Sprite evaluation and all that)
But you can turn off the screen, send a second set of sprites by DMA, then turn it back on, and it will draw the second set of sprites. But 64 sprites is still a lot before running out of sprites.

by on (#90045)
Do you have to turn off the background and PPU, or would just disabling sprites work to get access to OAM?

by on (#90048)
Need to turn off both. Disabling just sprites or just background only stops it from drawing it, it's still making all the memory accesses it would otherwise make.

by on (#90049)
Dwedit wrote:
But you can turn off the screen, send a second set of sprites by DMA, then turn it back on, and it will draw the second set of sprites.

But even disabling rendering mid-screen can corrupt the sprites later if not done at the correct time. The PPU goes kinda crazy if you interrupt the sprite evaluation process at bad times. I never fully understood how to get around this quirk...

Quote:
But 64 sprites is still a lot before running out of sprites.

If he had to start this topic, he probably doesn't think so. :wink: Also, "a lot" is a concept that varies greatly depending on what you're making.

by on (#90060)
It's pretty much useful only for split screen as seen in Bigfoot. It's not like the GBA, where you can rewrite OAM during horizontal blanking for more blocks (as seen in Super Puzzle Fighter II) or more "bullets that shoot bullets" (as seen in Vulkanon).

by on (#90062)
Quote:
I doubt that sprite multiplexing or raster effects are possibly on the NES, or reliable at least. Even simplest code that sets position of a sprite directly, without DMA, leads to problems on the HW.

I'm getting off topic, but all that the DMA does is do 256 writes to $2004, technically. So if DMA works, direct writes to $2004 should work too ? I have never tried it as there is no advantages in doing it this way (it just takes more time), but if you perform the writes before the end of VBlank (which should be easy with an unrolled loop) then I can't see how it could fail and how it differs from DMA.

Back on the topic, I think you can do odd things with $2004 reading during the frame. This was quite obscure as the behavior was different depending on the model of the NES/Famicom you used and the PPU revision. Most people doesn't have 20 different NESes/Famicoms to test their programs on it for exact behavior of different revisions so this is highly problematic to test.

On some systems like the C64, sprite mulitplexing is common and even essential if you want to display more than 8 sprites at all. I remember writing a cool multiplexing engine for it then loosing both the source code and the compiled result :(
The C64 however is very different as VRAM is shared with RAM (it's the same memory chip, VRAM is just a part of normal RAM) and the acesses are interleaved between the video chip and the CPU, so you can write to any register anytime and it takes effect immediately. Also sprites are part of normal VRAM, there is no such thing as OAM. The price for this is a very slow CPU (1 MHz only).

by on (#90063)
I have no idea why direct OAM access does not work as expected, but it actually happens. Some sprites disappear sometimes, things like this.

by on (#90083)
Shiru wrote:
I have no idea why direct OAM access does not work as expected, but it actually happens. Some sprites disappear sometimes, things like this.

I remember noticing the same but didn't care to figure out the exact reason because the DMA is there and works. It may have something to do with the value that the OAM address (controlled by $2003) ends up with. You could try resetting it to $00 after writing the sprites.

EDIT: typo

by on (#90088)
I guess the only reason for direct writes to $2004 would be to update OAM when you're doing something that can't spare 500+ cycles, such as playing back audio through $4011.

by on (#90091)
Or when you are tight on RAM and don't use that many sprites, so you can use part of the page for other purposes.

by on (#90098)
tokumaru wrote:
Or when you are tight on RAM and don't use that many sprites, so you can use part of the page for other purposes.


Technically you could use almost 3/4 of the page for whatever you want, right? Just make sure to set all the y-coord bytes to an off-screen value, then put data in the other three bytes. Yeah you're DMAing garbage to the PPU but who cares?

Oh...I suppose that might get glitchy though when the PPU hits the 8-sprite-per-sccanline limit and starts picking the wrong bytes as y-coord. Hm.

by on (#90099)
...And the memory can't be used for arrays, because every 3 bytes you must have a certain value.

by on (#90102)
cpow wrote:
Oh...I suppose that might get glitchy though when the PPU hits the 8-sprite-per-sccanline limit and starts picking the wrong bytes as y-coord. Hm.


That stuff simply doesn't matter if the sprites are offscreen anyway. It won't affect the display of visible sprites, or affect how Sprite 0 collision works. It just means you'll get slightly different results from the ever-unreliable sprite collision flag that nobody should use anyway.

by on (#90103)
tokumaru wrote:
...And the memory can't be used for arrays, because every 3 bytes you must have a certain value.

You can if elements of the array are spaced 4 bytes apart. (The first that come to mind are variables associated with channels in my music engine.)

by on (#90114)
Dwedit wrote:
It just means you'll get slightly different results from the ever-unreliable sprite collision flag that nobody should use anyway.


? There's like a zillion games that use it reliably.

by on (#90118)
Maybe Dwedit meant the sprite overflow flag. I'm using this flag in my game, to detect the beginning of the frame (9 sprites are located at the very top of the screen). For that purpose, it seems reliable enough.

by on (#90119)
Ahh, yeah he probably did mean that.