Writing to VRAM during HBlank

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.
SNES AYE
Posts: 201
Joined: Mon Nov 07, 2022 11:28 am

Re: Writing to VRAM during HBlank

Post by SNES AYE »

Assuming there are no sprites in play at all for now then, is that you saying it would be possible to use this method to help animate say a large boss character made with a background layer where there may not have been enough time to change all the required tiles during only VBlank normally, or would the glitching of the tilemap and pixel data you mention visually corrupt the boss graphics on-screen in this particular scenario?

Thanks for all that info and the examples.
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: Writing to VRAM during HBlank

Post by 93143 »

The glitching isn't inevitable in all scenarios. Basically, you have to write the data before you need it, but after you stop needing the old data that you're overwriting. Since you can determine more or less freely where data updates go, you can maneuver around the areas that display your updates as long as they're not too unpredictable.

But having no sprites at all is a pretty severe constraint. Are you sure you aren't trading away more than you're gaining?
SNES AYE
Posts: 201
Joined: Mon Nov 07, 2022 11:28 am

Re: Writing to VRAM during HBlank

Post by SNES AYE »

93143 wrote: Fri Jun 02, 2023 5:06 pm But having no sprites at all is a pretty severe constraint. Are you sure you aren't trading away more than you're gaining?
Not for what I'm thinking about. I would actually have sprites in the idea I'm thinking about, just not on any scanlines where the boss would be displayed. :)
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: Writing to VRAM during HBlank

Post by 93143 »

...so that's not ideal. What you want is for there to be no sprites where the boss isn't displayed, so you can use those lines to update without worrying about stomping on live tiles while the boss is being rasterized. It might still be possible, but it's hard to say in the abstract.

Alternately, you could use the boss area where there are no sprites to update other stuff, leaving more VBlank for the boss...

Keep in mind that there's a bunch of other cool stuff you can do with HDMA, and using channels on this is a design tradeoff even if you don't have sprites to worry about.
SNES AYE
Posts: 201
Joined: Mon Nov 07, 2022 11:28 am

Re: Writing to VRAM during HBlank

Post by SNES AYE »

I think I could probably have around 32 scanlines where there's no boss background tiles or sprites tiles at the bottom of the visible screen area, which seems like it would be a decent amount to take advantage of HBlank to switch a bunch of boss tiles (in addition to the standard VBlank time too).

I assume the other backgrounds can be displayed as normal on-screen while using this method, yes?
SNES AYE
Posts: 201
Joined: Mon Nov 07, 2022 11:28 am

Re: Writing to VRAM during HBlank

Post by SNES AYE »

Also, I presume this same method could be used in a game to update more sprite tiles than normal (taking advantage of the time during HBlank), possibly meaning no need to force blank at the top/bottom of the screen in a fighting game with large characters or beat 'em up with lots of enemies just to get enough time to update all the animated sprites on-screen, so long as there's no sprites on the scan lines where I want to use HBlank to help with updating the sprites tiles?
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: Writing to VRAM during HBlank

Post by 93143 »

32 lines is enough for 768 bytes (24 4bpp tiles, or 12 rows of a tilemap), assuming the data can be dumped into VRAM in a single contiguous chunk and that nothing else needs HDMA*. BGs should work fine; it kills sprites because the line buffer renders during HBlank, but you need to force blank during HBlank for the trick to work, and this prevents any rendering tasks from being performed.

It would probably be quite difficult to make this work in your average action game, because sprites could be almost anywhere, so calculating where the safe areas are and building the HDMA tables accordingly could be quite complicated. Especially with a beat-em-up, it's entirely possible for the unsafe area to span nearly the entire vertical extent of the screen just with how the action happens to be going at a given moment. This technique is not a magic bullet; letterboxing is usually far more effective and robust.

Note that there is an HDMA bug that's relevant to this method. If you're going for full bandwidth, your final channel has to write to INIDISP. If the last channel terminates with its B bus address set to $00, it disables DMA. So what you have to do is either use less than 24 bytes per line and have something else on the final channel, or else set the destination address to $FF and use a word write.


* It's not just a matter of not needing HDMA during those lines - if anything else needs it anywhere in the frame, you need to turn it off, change the channel settings, and restart it, and IIRC there's a one-line lag when restarting. I usually reserve a channel for audio streaming, which would reduce the maximum bandwidth to 20 bytes per line.
SNES AYE
Posts: 201
Joined: Mon Nov 07, 2022 11:28 am

Re: Writing to VRAM during HBlank

Post by SNES AYE »

OK, good to know. Thanks.
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: Writing to VRAM during HBlank

Post by 93143 »

To clarify a point in my previous post: you can send each line's worth of HDMA data to a different location in VRAM by using a channel to set the VRAM address before sending the data. This obviously reduces the amount of data you can send by 4 bytes per line (one channel's worth), and complicates the design of the method.

Theoretically you could even set the address before every 4-byte channel shot, so as to send data to multiple locations during a single HBlank, but this would cut the bandwidth in half and make the complication worse...

It's easier to just leave the VRAM address to auto-increment. This means you can only use HDMA to update one single contiguous area of VRAM per frame, but that's still potentially quite useful if you're having trouble with bulk data fitting into VBlank, as in the Doom example.
SNES AYE
Posts: 201
Joined: Mon Nov 07, 2022 11:28 am

Re: Writing to VRAM during HBlank

Post by SNES AYE »

After reading some of the early posts in this article again, I'm just curious if anyone has created a working demo since then of the SNES playing however many seconds of full-screen video plus audio this method seems to be able to allow, maybe something I can download and view myself on an emulator?

It would be very cool to see and hear a working example of what's possible (with the version that doesn't use MSU1). :)

If I could make a request, I would like to see the '80s-'90s He-Man cartoon intro with the "I have the power!" transformation sequence, both video and audio, if that's possible. :D
SNES AYE
Posts: 201
Joined: Mon Nov 07, 2022 11:28 am

Re: Writing to VRAM during HBlank

Post by SNES AYE »

93143 wrote: Sat Jun 03, 2023 11:28 am To clarify a point in my previous post: you can send each line's worth of HDMA data to a different location in VRAM by using a channel to set the VRAM address before sending the data. This obviously reduces the amount of data you can send by 4 bytes per line (one channel's worth), and complicates the design of the method.

Theoretically you could even set the address before every 4-byte channel shot, so as to send data to multiple locations during a single HBlank, but this would cut the bandwidth in half and make the complication worse...

It's easier to just leave the VRAM address to auto-increment. This means you can only use HDMA to update one single contiguous area of VRAM per frame, but that's still potentially quite useful if you're having trouble with bulk data fitting into VBlank, as in the Doom example.
https://youtu.be/3zfc8pHmi_w?t=445

So, to check something using an actual SNES game like Endless Duel above as a reference, would it be possible to turn off the forced blank and display the background(s) in the areas where the forced blank is currently used while using the HBlank method we've been discussing to help swap in/out the extra frames required for the fighters on the same scanlines where forced blank is currently used, but just cut off/not display the fighters themselves if they ever go into those same scanlines? Effectively, you would still see the fighters being visually cut off near the top or bottom of the screen if they jump too high or the screen moves up/down like now, as if there was forced blank on the same scanlines where it is used in the real game now, but using this HBlank method rather than real forced blank the background tiles would always be displayed regardless. The main idea being that even though the fighters are getting partly visually cut off at the top/bottom of the screen at times, the game still appears full screen on the backgrounds and it's not so obvious there's a technical and visual compromise required in order to have big animated fighters like this on-screen, which I personally feel the forced blanking is an obviously very visible indication of.

Note: Obviously, you would still be trying try to switch in/out as many of the fighter's tiles as possible during normal VBlank, with the Hblank method simply being used to augment this and afford the SNES just a little more time and room to breath.

Does what I'm asking makes sense, and do you think that would be technically possible (even if somewhat convoluted and fiddly to implement)?

Edit: I actually wonder how bad any glitching might be where the fighters cross into the scanlines where the HBlank method is being used and whether it would be fine just leaving the fighters visible there even with the glitching, given it would only be noticeable at the top and bottom of the screen anyway, or if it would indeed be better to not display them at all on those scanlines as I've suggested? It could be this glitching actually isn't as bad as I imagine, but I've not seen it in practice, so I'm not actually sure and just imagining it's so bad that it would want to be avoided at all costs.
Last edited by SNES AYE on Wed Jun 07, 2023 3:11 am, edited 1 time in total.
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: Writing to VRAM during HBlank

Post by 93143 »

It should be possible, but I think it would actually look way worse. With letterboxing, it's clear that the game window is what it is, and your brain disregards the black areas as not worth paying attention to. With your scheme, the sprites inexplicably don't get drawn over some of the visible area, and it looks like those emulated widescreen modes where objects suddenly pop in at the edges of what would have been the screen on the real SNES. The presence of the BG layers indicates that the game world is visible there, but the consistent lack of sprites means you can't actually trust what you see in those areas, causing cognitive tension.

Also, please note that forced blank is worth 165.5 bytes per scanline, while VRAM writes during HBlank can manage maybe 29.5 (this requires the CPU be tied up during those lines to get the timing good enough). Unless the game uses way more letterboxing than it needs, you'd probably have to cut sprites on significantly more lines than the current letterboxing takes up.
SNES AYE
Posts: 201
Joined: Mon Nov 07, 2022 11:28 am

Re: Writing to VRAM during HBlank

Post by SNES AYE »

93143 wrote: Wed Jun 07, 2023 2:58 am It should be possible, but I think it would actually look way worse. With letterboxing, it's clear that the game window is what it is, and your brain disregards the black areas as not worth paying attention to. With your scheme, the sprites inexplicably don't get drawn over some of the visible area, and it looks like those emulated widescreen modes where objects suddenly pop in at the edges of what would have been the screen on the real SNES. The presence of the BG layers indicates that the game world is visible there, but the consistent lack of sprites means you can't actually trust what you see in those areas, causing cognitive tension.

Also, please note that forced blank is worth 165.5 bytes per scanline, while VRAM writes during HBlank can manage maybe 29.5 (this requires the CPU be tied up during those lines to get the timing good enough). Unless the game uses way more letterboxing than it needs, you'd probably have to cut sprites on significantly more lines than the current letterboxing takes up.
OK, I never realised there was so much more space/time with forced blanking. That would indeed make using this HBlank method in this particular scenario difficult.

So, regarding the last bit I added there about the glitching, what are we talking about here. Is it like the whole sprite would look a jumbled mess on the scanlines where the HBlank method is used, or maybe more like a little line glitch or flickering now and then but still bearable, similar to what you see on some systems when dynamically switching color palettes part way down the screen or now and then in some games where sprites go over their scanline limits for a moment?
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: Writing to VRAM during HBlank

Post by 93143 »

The method works by forced blank during HBlank, so as to free up VRAM for writes. HBlank is where the PPU loads sprite graphics from VRAM into its line buffer. But the PPU doesn't load sprite graphics while the screen is blanked for writes (or perhaps just while the writes are happening? The 1CHIP seems to behave funny in this regard), and the line buffer doesn't get filled properly.

With the version of hvdma.sfc that allows me to turn off layers, what I see on my real SNES is that there are multiple regions of sprites, no sprites, and flickering sprites. It looks like about a quarter of the line is solid sprite colour, another quarter is flickering, and maybe half is black. Since I didn't add any detail to the sprite layer (it's just a solid-colour layer of 64x64 sprites), I can't tell whether the sprite graphics that are displayed are stale or not (though I'd imagine not). I'd have to modify the test, and I don't really have time for that at the moment.
Post Reply