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

Sprite vs. BG layering priority

Sprite vs. BG layering priority
by on (#86882)
This weekend I started playing Majou Densetsu 2 - Daimashikyou Galious and found that Konami was somehow adjusting sprite vs. BG priority order in some areas on-screen. It's easiest to just provide a Youtube video of what I'm talking about:

How this came to light: in Nestopia (and any other emulator -- they all behave identically with this game), I tend to leave no-sprite-limit enabled since it often relieves sprite flicker in games (e.g. River City Ransom). I kept wondering why Poporon (main character) would go through the floor when entering a door (meaning it looked like he was just floating downwards atop the floor) -- then it occurred to me the no-sprite-limit option might be causing it. Sure enough it was.

Two questions -- but keep reading before answering. :-)

1) How does the no-8-sprite-per-scanline-limit feature actually affect things like this?

2) How exactly is Konami giving background tiles higher priority than sprites (e.g. the background now, visually, looks like it has higher priority ("closer to the foreground") than a sprite).

Poporon is indeed a sprite, by the way -- I verified this in FCEUX by disabling the OBJ layer.

I also tried disabling the BG layer to see if Konami was doing it by effectively using the floor tiles and part of the background wall tiles in sprites with a higher (lower?) index value compared to Poporon, placing them where the BG tiles would be, then simply incrementing Poporon's Y coordinate -- nope, doesn't seem to be it either. Hmm.

I imagine the same technique is done in Castlevania 1 (when entering the castle the very first time; Simon goes into the door and "behind" the stone), and/or Castlevania 2 (when walking in a swamp, only the top half of Simon's body should be visible).

Some may be surprised that I'm the one asking this question -- please don't be. I can't remember things that happened a few years ago, and I really don't do much NES development any longer.

Thanks guys.

by on (#86883)
I'm guessing they add 8 (or more) transparent high priority sprites at the bottom of the door (only Y coordinate matters). This way, when the (lower priority) player sprites overlap the scanlines where the transparent sprites are, the player sprites become invisible. I have used this same technique to clip sprites to the status bar that's on the top.

This is actually a pretty nice technique, because if one was to use the sprite BG/FG priority bit to do it, the sprite would show up through the black areas of the background.

It looks like they are using more than 8 sprites (on more than one 8/16 pixel row) to accomplish this, as the player sprite doesn't seem to be clipped in software when it gets past a certain point. When using software clipping, no more than 8 sprites are ever needed.

You can verify this by opening the game in Nintendulator, pausing it while he's partway going through the door, and looking for the (presumably) transparent sprites in the PPU viewer.

by on (#86886)
Man, this has nothing to do with BG priority - they just use 8 dummy sprites to hide the player sprite, which is a great classic : Castlevania II Simon's Quest (in marshes), Legend of Zelda (vertical doors in dungeons) and Ninja Gaiden (anime cutsenes) also exploit this trick.

by on (#86896)
I've also been curious how this works. For some reason I was under the impression that the entire sprite would disappear, not just the part that overlaps 8+ sprites.

I can think of a lot of applications where this could be useful.

by on (#86897)
It's not transparent sprites hiding it though. It's putting 8 higher priority sprites so that the character sprites are dropped/not drawn normally.

It's not the trick where you put higher priority sprites that are behind the backgground that effectively clip like in some games.

by on (#86904)
Yep, basically what everyone else is saying.

Notice how all of the sprites except for Popolon disappear; that's likely the game setting up a special case where there are 24 sprites (likely 0-23) with transparent bitmaps (even if the sprite is completely invisible due to it using a completely transparent tile, it still counts towards the limit and is "drawn", even if the result has no effect), arranged such that the 24 scanlines below Popolon each have 8 sprites on them. Then, Popolon is made of sprites #24 and above.

by on (#86910)
I think Legend of Zelda does this to hide line when moving through certain doorways too, which then is wrong when you ignore the sprite limit.

by on (#86918)
Thanks everyone. I think I get it. Related: does anyone know of any emulators which support some kind of fine-grained control over, or visibility into, sprites (e.g. drawing boxes/borders around them, etc.)? Or maybe just viewing the region of RAM dedicated for sprites?

Nestopia, Nintendulator, VirtuaNES, FCEUX, and FCEUXD SP NSF all lack this kind of functionality. Hmm, maybe I should update either that wiki page or that nesdev thread where we were discussing useful features for a "debugging" emulator...

by on (#86922)
VisualBoyAdvance has support for visualizing the GBA's OAM (sprite table), just add PocketNES.

Back to the sprite masking trick...

In order to get row masking of sprites, PocketNES looks at the first 8 sprites (or first 8 after sprite zero), and checks if they are at the same Y coordinate and have the same tile. If they are, it disables sprites for the 8/16 scanlines of that row. (I used to also have a constraint that all 8 sprites must have the same X coordinate as well, but Gremlins 2's cutscenes violated that constraint)

This logic could allow a "Allow more than 8 sprites" feature to not break when games intentionally use 8 sprites for masking.

by on (#86927)
no$nes like his other emulators shows the individual sprites.

by on (#86929)
strat wrote:
no$nes like his other emulators shows the individual sprites.

Woot, thank you for this; had no idea Martin had made a NES emulator. :-) New video for those interested (including OAM data information, capture speed was 60fps as well -- sorry for the lack of audio this time though):

Based on frame-by-frame analysis of the video (meaning looking at what OAM data changes to what), it looks like when Popolon enters the doorway the following things happen (in some order or another):

1) Popolon, whose body normally uses sprite indexes 1-4, has their tile changed to refer to ones where it looks like he's facing the doorway. These happen to be the same tiles used in sprite indexes 17-20. However, sprite indexes 17-20 all have a red slash through them, which I believe means they're either unused or non-visible.

2) Sprite indexes 5-9 (used by the bouncing spherical monsters) are marked non-visible.

3) Sprite indexes 1-16 (possibly 0-16) are changed to refer to tile $FF (PPU address $1FE0). All of those sprite indexes are also changed to have their "Priority" bit set.

4) Sprite indexes 1-4 have their X and Y locations changed to be below where Popolon was standing (e.g. "under" the doorway). Sprite indexes 5-16 might have the same thing done to them, but obviously I can't look at all of them at once.

5) Sprite indexes 17-20 are marked used/visible.

6) I assume some code also changes the Popolon character to therefore start using sprite indexes 17-20.

I haven't examined tile $FF yet, but I'm willing to bet it's all zeros (transparent).

by on (#86930)
koitsu wrote:
I assume some code also changes the Popolon character to therefore start using sprite indexes 17-20.

Since making hardcoded use of the sprite slots is a pretty amateurish thing to do, I sincerely hope that no professionally developed games did this. The game probably uses the sprite slots sequentially (it appears there is no sprite cycling), in which case simply using the high priority sprites for the "mask" first would automatically push Popolon forward.

by on (#86931)
VirtuaNES has a RAM viewer/editer and I'm pretty sure FCEUltra does, then you just have to watch the page this game uses for sprites (for example $200-$2ff).

An unofficial version of Nindendulator have a true Sprite viewer, but it is not very practical due to cycling.

by on (#86932)
Yeah, sprite cycling does make it hard to keep track of what's happening in most cases. Masks must always have high priority though, so even if everything else cycles, masks are likely to remain in the same OAM positions.

This game doesn't seem to have any cycling though, and what's happening is clear: 8 high priority sprites (their patterns don't matter, they don't need to be transparent for this to happen) prevent all others from showing up in the same scanlines. If you tell your emulator to ignore the 8-sprites-per-scanline limit, the other sprites will be displayed and no masking will occur.

The other type of masking, the one where high priority sprites are set to be displayed behind the background, doesn't break when the limit is disabled. Its main disadvantage is that it only fully masks sprites if the background in question doesn't use color 0, but it has the advantages of working horizontally (the other way only works vertically, for obvious reasons) and allowing the use of masks of complex shapes.

by on (#86940)
It could just forgo sprite cycling while traveling through the doors. I would think that is more likely since the game probably wouldn't want sprites being dropped when more than 8 appear on a line during play.

by on (#86941)
Well, in the video koitsu posted, everything is using the same OAM slots for a long time, even before he enters the door.

I don't find it hard to believe that some earlier games used very simple sprite cycling, or even none at all.

by on (#86942)
In some of their games, such as Castlevania I and II, Konami managed to get some "high priority" sprites with fixed slot (including the hero sometimes) while the enemies, bullets, etc... appear in a lower priority in a pseudo-random order.
So I guess it's the same with this game.

by on (#86955)
I've seen OAM separated into a section of non-cycling sprites (starting with sprite 0), and then a section of cycled OAM. I think Goonies II might even do this, but it's been a while since I looked.