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

How do I make sprites invisible on certain horizontal lines?

How do I make sprites invisible on certain horizontal lines?
by on (#118975)
I'm creating a BG dialogue window for my game. I want Sprites to not appear on the lines where the dialogue window is being displayed. I'm using MMC3 for the scanline IRQs, and thus can't turn off sprites with $2001. I'm also using CHR-RAM, so I can't bank in blank data on those lines (or can I --- does MMC3 have chr-ram banking functionality?).

My best idea currently is to use the SMB3 trick that hides power up sprites using low-index back-priority sprites. However, implementing this would require tracking the positions of all my sprite objects so I could place the hiding sprites. I'm hoping there's a better way which wouldn't require so much time spent tracking objects.

Any ideas?
Re: How do I make sprites invisible on certain horizontal li
by on (#118976)
You could put eight blank sprites on the scanlines that you don't want other sprites to appear on.
Re: How do I make sprites invisible on certain horizontal li
by on (#118977)
zzo38 wrote:
You could put eight blank sprites on the scanlines that you don't want other sprites to appear on.

True. But with a window 64 pixels in height, I'd have to use 8x4 8x16 sprites - half of my OAM.

Could I bank in an empty CHR-RAM bank - does MMC3 allow for CHR-RAM banking?
Re: How do I make sprites invisible on certain horizontal li
by on (#118979)
There are a few ways:

Mask the sprite by putting the BG tiles as sprites and covering the sprite when the priorities get set on it.

Disable sprites between that area.

Put the sprite behind the BG, and use BG color 1 and 0 on each palette the same.
Re: How do I make sprites invisible on certain horizontal li
by on (#118981)
The fact that you're using MMC3 IRQs for other things doesn't prevent you from using them for this as well. You just have to check what comes first, the other split or the text box, so that you can setup the IRQs in the correct order.

But if you really don't want to use IRQs, you can use the good old sprite 0 hit. As long as the top scanline of the text box has solid pixels, a sprite 0 hit can tell you when it starts, at which point you can disable sprite rendering and count cycles until it's time to enable them again. I'm assuming that wasting time on wait loops isn't an issue, since I doubt there will be much action going on while text is being displayed (most games I can think of are practically paused during that time).

The only disadvantage I see is that sprites could still be visible at the top left of the text box before you disable them, but you can solve that by using 7 high priority sprites in addition to sprite 0 to mask out whatever would be visible otherwise.
Re: How do I make sprites invisible on certain horizontal li
by on (#118985)
Ninja Gaiden III at certain points just disables sprites at a particular line to make them appear as though they go behind the background. Ninja Gaiden III also uses the IRQs for the status bar at the top of the screen as well. So you can certainly use IRQs to do what you need.

Given that you have just a box area you want no sprites in I think disabling sprites is the way to go. No need to use other sprites to mask things.
Re: How do I make sprites invisible on certain horizontal li
by on (#118986)
pops wrote:
I'm creating a BG dialogue window for my game. I want Sprites to not appear on the lines where the dialogue window is being displayed. I'm using MMC3 for the scanline IRQs, and thus can't turn off sprites with $2001.

You could use an MMC3 IRQ for the top of the window and timed code for the bottom (may need to detect PAL or NTSC at startup). Or you could use an MMC3 IRQ for the top, timed code to wait about 16 lines before reenabling sprites, and sprite 0 for the bottom.

Quote:
I'm also using CHR-RAM, so I can't bank in blank data on those lines (or can I --- does MMC3 have chr-ram banking functionality?).

Yes. Existing MMC3 boards with CHR RAM (TGROM, TQROM, TNROM) connect A10-A12 of the CHR RAM to the CHR A10-A12 outputs of the MMC3. Given that 128 tiles for all 64 sprites can fit in $1000-$17FF, it's feasible in some cases to leave $1C00-$1FFF of CHR RAM completely unused. Here's one possible way to arrange VRAM:
  • $0000-$0FFF: Background tiles
  • $1000-$17FF: Tiles for sprites 0-63
  • $1800-$1BFF: Alphabet tiles, or VWF plane if you're rendering text that way
  • $1C00-$1FFF: Blank

Homebrew boards or rewired donor boards that use a 62256 (32 KiB) instead of a 6264 (8 KiB) would additionally connect A13-A14 to the MMC3's CHR bank outputs. You can emulate such boards in any emulator that supports NES 2.0 headers by setting the "CHR RAM size" field to 32 KiB.
Re: How do I make sprites invisible on certain horizontal li
by on (#118987)
This is great information. Thanks everyone.

Here's how I'll run my dialogue box:
I'll set IRQ to call at the top of the dialogue window, and then again at the bottom.

Since MMC3 can bank CHR-RAM, I will keep the last 1kb of CHR-RAM empty at all times, and then when the top dialogue IRQ is called, switch all the CHR-RAM sprite banks to the final bank index:
Code:
   lda #%00000111
   ldx #%00000010
   stx $8000
   sta $8001
   inx
   stx $8000
   sta $8001
   inx
   stx $8000
   sta $8001
Tepples, as you pointed out, I may not need to clear the third bank, since I can fit all my sprites into the first two.

Then, when the second dialogue IRQ is called, I'll reset the banks to their original indexes.

Since this code takes more than a hblank to run, I'll probably have some sprites bleeding one line into the dialogue box on the top left (and some sprites missing a line on the bottom left), but I think this is an acceptable compromise, and of course I can always use 8 low priority sprites to hide the glitch at the top of the dialogue box.

Again, thanks everyone!

(Tepples, what's a vwf plane?)
Re: How do I make sprites invisible on certain horizontal li
by on (#118988)
iii iii iii
mmm mmm mmm

Code:
iii iii iii
mmm mmm mmm


A monospace or fixed-width font has glyphs of only one width. A proportional or variable-width font has glyphs of different widths. For example, in a Latin proportional font, m is wider than i. On NES, these would be rendered into a buffer in RAM and then copied as tiles to the PPU.

Here's the difference:
Image

Here's what VWF looks like in a commercially released NES multicart:
Image
Re: How do I make sprites invisible on certain horizontal li
by on (#118991)
I think if you disable only sprites by $2001 it won't affect the scanline counter, because the PPU still fetches them. I might be wrong though.

Other ways to do it :
- Use blank CHR-ROM page
- Abuse 8-sprites per line limitation
- Just do it by software if it's acceptable to get only 8 pixel of accuracty (that's what I do in my game).

Also you don't need as much sprites as you're telling if you want to abuse 8-sprites per line limitation. Just use 8 sprites for the top line and 8 for the bottom line, and mask the sprites in between by software (i.e. just don't put them in OAM). This eats up 1/4 of OAM, sure, so in the worst case where all 64 are used and only one will have to be clipped, this won't be the best solution.
Re: How do I make sprites invisible on certain horizontal li
by on (#118994)
It would be MUCH more simple to just disable sprites before the line of your dialog box and reenable them after it. Banking CHR to empty patterns takes more time too. I don't think there is any reason not to just disable sprites and reenable them after the break. Why are you opposed to doing that?
Re: How do I make sprites invisible on certain horizontal li
by on (#118997)
I believe that disabling sprites in 2001 also disables MMC3 IRQ line counting. Am I wrong?
Re: How do I make sprites invisible on certain horizontal li
by on (#119002)
Who wants to be the first to post a test ROM for this? It'd have to disable sprites, enable the background, set up IRQs, and display an IRQ counter on the screen.
Re: How do I make sprites invisible on certain horizontal li
by on (#119003)
I can check it tomorrow, although I won't be able to post a test rom.
Re: How do I make sprites invisible on certain horizontal li
by on (#119005)
There is no need for a test ROM. We can just look at Ninja Gaiden III again. Stage 2, IRQs are continued to be used after disabling sprites. Sprites are disabled on line 175. This hides sprites like they sink into the ground. However after this is done, another IRQ fires at line 206, to parallax scroll the very bottom portion of the screen. So the IRQ counter most definitely works with the sprites disabled.
Re: How do I make sprites invisible on certain horizontal li
by on (#119007)
We know for sure that all VRAM/CHR-ROM fetches are still performed if only one layer (background or sprites) is disabled, don't we? As long as that's the case, MMC3's scanline counter will surely keep working when sprites are disabled.
Re: How do I make sprites invisible on certain horizontal li
by on (#119026)
I just tested this. MottZilla and tokumaru are correct: so long as either the sprite display bit or background display bit in $2001 are set to 1, the MMC3 IRQ will fire.

Thanks again everyone!