NES Sprites, OAM, and the Battle for Priority - Behind the Code
Вставка
- Опубліковано 6 лип 2023
- Let's dive into how Sprites are prioritized and limited by Object Attribute Memory (OAM) and Secondary OAM on the NES. The journey toward understanding flicker has begun.
If you would like to support this channel, here is a link to the Displaced Gamers Patreon page - / displacedgamers
Twitter: / displacedgamers
Facebook: / displacedgamers
Instagram: / displacedgamers
Music by:
/ hariboosx
/ @wolfandraven
#NES #Programming #graphics - Ігри
OK! That was OAM and Priority. This project was nuts! I hope you enjoyed it.
That said, I hope I didn't miss anything important or make any notable mistakes. If you are part of the NES development community, jump into the comments.
A few notes on this episode:
1: I cut out some details and trivia for the sake of pacing. < 20 minutes was the goal.
2: The > 8 Sprites on a line section that kicks off with Castlevania II originally started with details about the sprite overflow flag bug. It is an interesting bug, but slowed the video down for the sake of explaining something trivial for any viewers not programming NES games. That got cut.
3: Details about partially visible Sprites on the left side of the X-Axis and usage of PPUMASK were also omitted.
4: Some of my illustrations (palette indices, backdrop color, etc.) may not be presented in the same manner when viewed using the debug features in various emulators.
Finally - I really have a huge appreciation for those that have contributed to the nesdev wiki over the years. It really helped me with some sanity checks of the "no... wait... yes... right?" variety while making this video. So a huge thanks to any of you with forum posts or edits that are forever tied to that wiki.
FLICKER
(also, amazing video!)
Yes, I would also like to understand flicker more for the NES compared to say the Atari 2600. Also very good video.
dude, the captions are broken, it just displays every single caption at the start of the video and then nothing for the rest of it
I liked the NESDev wiki's example of where the odd priority collision can occur in Super Mario Bros.' normal gameplay, a level where Bullet Bills appear to shimmer as they fly across pipes because Piranha Plants are hidden inside pipes with background priority but have higher priority than Bullet Bills and so cut a Piranha-Plant-shaped chunk of graphics out of the Bullet Bill to render pipe graphics on top.
Would love, love, LOVE to hear details about NES Sprite Flicker!
Ah. So in SMB3, when Mario ducks on a white background block and is moved to the background layer, that's why his outline is still visible through enemies that pass in front of him.
This was the first example I thought of when he brought that quirk up.
Ayup.
It's hard to understand if you consider the background to be at just another priority level, but what's actually going on is that the hardware does all sprite priority checks before doing the sprite/background priority checks. So it's a different set of priorities, and by the time the background comes into play the "hidden" sprite pixels have already been discarded.
@@michaelcalvin42 yeah same, as soon as he showed the mario 1 example with the foreground goomba being masked by a background-occluded sprite I thought "this is what they figured out how to abuse in Mario 3"
I think there are few people in the world who can convey these technical subjects as well as you do. You really fit ideas into a coherent 'narrative': starting the viewer off with good foundational knowledge and disambiguation of terms, and then presenting concepts in a logical order where each new idea builds off of what the viewer has already just learned. 10/10
Thanks!
@@DisplacedGamers Legendary people like you get Legendary comments like these. You rock!
I rarely comment on videos, but I think I speak for a big part of your audience when I say: There's no need to apologize for things getting screwily precise and technical, that's exactly what we're here for. Your explanations are clear and excellent.
A year or two ago, I was super obsessed with this stuff and wrote "flicker enders" for Mega Man 2 and Recca. I had to reverse engineer the drawing routines and emulate them in Lua, minus any sprite flicker and OAM limitations. To properly emulate sprite on sprite priority, I drew them in reverse order. I had to figure out that front priority obscured by back priority quirk just to emulate an obscure interaction with the energy bars in Airman's stage.
Can't wait for the video about sprite flicker! I've rewatched so many of these videos multiple times and each time a new concept or idea *clicks* for me in a way it didn't previously. This series really should be mandatory viewing for anyone getting into NES development
BABE WAKE UP!! Displaced Gamers video just dropped!!
My wife : WTF are talking about?
I'm surprised you didn't use the smb 3 white block platform method to show the background/foreground priority in game, when you mentioned that you were going to show how this applies to in game mechanics.... Because you can hold down, changes mario to background, and then will be in the background and that interferes with koopa shell sprites much the same way you showed the goomba/mario/bush conflict stack for smb1
Fully expected that too, but I think once he showed that effect in SMB1 we all immediately said "OH yeah that thing with the white blocks in SMB3!". So it was like, completely obvious.
Where the block trick was not obvious even though it very quickly made sense to anyone that has ever seen that speedrunning skip to ending trick that glitches out the world 7 level. When you go into an up pipe from above and to the side. You see the "fake" sprites used behind the pipe because mario is "entering" it from next to it instead of actually into it. Never really completely knew what those were until now.
@@nickfarace9339the moment I saw the sprite that blocks view of power ups leaving blocks I about pointed at the screen "THATS THE THING YOU ENTER IN WORLD 7" 😂
love sprites...it's fascinating what programmers were able to do w/ the NES, GB, Master System, etc. limited capabilities
Separating the concepts of "sprite" and "entity" the way you did makes you one of my favorite kind of people. I do a lot of technical communication for my job and this is what I do when opportunities for confusion occur. A+ from me, you're cool.
I do hope the potential follow up video that might talk about flicker talks about how certain games, like the Gauntlet games, get around some of those limits.
That trick with stuffing the scanline with 8 dummy sprites makes me angry with how well it works.
An elegant trick. I would never have thought of doing that.
A downside being the 8 dummy sprites have to be to the left of the "disappeared" sprite.
Wait, then how does Link go behind the door on the left in dungeons?
OMG I can see it in Zelda 1! Link's sprites go to the background on the side doors. And now I can't unsee parts of Link's head disappearing... :(
@@briankarcher8338 I think the only thing that actually matters is that the masking sprites are earlier in OAM than the masked sprites - you can see Simon move to the left of the dummy cluster at 16:33 and remain hidden.
Dummy sprites can only mask sprites horizontally, which is why LoZ edits Link's background priority instead when vertical strips of him need to be hidden
These videos really give me a greater appreciation for programmers on these old consoles. There are so many little things that modern developers rarely have to think about.
YES, PLEASE TALK ABOUT FLICKER!
Thanks for this. I'm studying NES development at present, and I just went over OAM last night in a separate tutorial.
This series is one of the best in over a decade on YT. TO have had these resources as a kid would have been great.
Amazing video, it is crazy to think that they were willing to clog up the rendering pipeline with so many sprites from the OAM. I guess unless you are making a bullet hell shooter game there really is no need to use all 64 sprites at the same time. With the use of mappers that provide scanline interrupts this OAM sacrifice stops being necessary because you can time switching sprite rendering on and off at the desired locations instead of those 8 dummy clog-up sprites.
I'm wondering if you are ever planning to make a video on the "DPCM interrupts for video timing" subject because it is quite fascinating. I have done my fair share of messing around with it and it really is a gamechanger for parallax scrolling, hiding sprites in the HUD area and so on without needing advanced mappers.
I'm always up for more stuff about how video processors worked… Today you'd just draw one item on top of another. If you didn't have to blend, you don't even have to sort the priorities, just let the Z buffer do that for you. This is much more interesting.
Seeing examples of this type of thing in action was awesome, in the beginning I was thinking it was just going to be a cautionary tale about how you can overload the sprite limit but then seeing actual practical tricks using it is so cool
Yes please, do a video on flicker. Also, could you talk about emulators and their ability to remove sprite limits? (And how that affects games)
This explains why when SMB3 speedrunners glitch into pipes that weird block sprite shows up. It's for Mario's pipe entry animation!
Another request: in Super Mario Bros. and Super Mario Bros. 2 (Japan), the area change timer data.
As originally coded, right after the offset for the initial value is loaded into Y (which corresponds to value $A0 in the area change timer data table), a flag for the left page location is loaded into A. This was supposed to apply only to the pipe intro scene (Worlds 1-2, 2-2, 4-2 and 7-2), but due to the RAM address for the left page location being used, this check applies to the leftmost page for every area, which is why when you leave the first underground coin room (in Worlds 1-1, 2-1 and 7-1) there is a longer time delay before returning to the level proper.
In Super Mario All-Stars, both values in the area change timer data table are $34, which fixes the time delay for leaving the first underground coin room, but it also shortens the time delay for the transition between the pipe intro scene and the level proper (Worlds 1-2, 2-2, 4-2 and 7-2).
I love that you can take a topic, call it complicated, and then somehow break it down to be 100% understandable. It's really impressive! Thanks for the video!
So that's how Uncle Scrooge goes into the secret passages thru certain fake walls in Duck Tales - his sprite changes priority from the overlapping backdrop to being drawn behind that certain portion of BG tiles. Now I see exactly HOW it was done from a tech standpoint. Excellent explanation! 👍
P.S. though I still wonder why some pixels of such a "concealed" sprite do flicker from time to time? 🤔
Man, I wish sprite render priority worked like that on the GB. Priority is based on sprite index on the GBC (I think), but on the GB, priority is determined by each sprite's x position. No idea what they were thinking with that one. Also, I never knew about those scanline overloading tricks in Zelda. Such an inspired idea. I'll definitely see if I can incorporate that tech in any of my games.
Great vid overall.
13:17 - Wait! Wait *I've seen that sprite before!* That...yeah, when messing some some game glitches, at least those caused by Game Genie codes, I've seen that exact sprite come up with Mario going down pipes incorrectly - specifically when I've seen him go down a pipe (or at least invoke the animation for going down a pipe, along with the screen transition to another area of the stage) while *very noticeably off center* or even on some solid yet invisible pipe - that sprite seems to get called up in that situation. Fascinating! So that's where it comes from.
All the stuff you'd never think to even think about playing these games as a kid.
I have never seen that explained before. It makes so much sense but I would've never guessed the eight-sprite limit would be used to do the cutoff effects like that! Generally I think it's easy to go, "Oh, they wouldn't throw away 16 sprites to do a simple visual effect!" Especially given the limits of just 64 available! Until you realize the alternative was not to do the effect at all. Super interesting stuff. I love learning about these old technological hurdles and solutions because I think we have a lot to learn from them. These are the things that made these games feel special, it's what made them stand out. It shows thoughtfulness in the mechanical and technical design. Love it!
I can’t believe how thoroughly you understand this stuff, and how well you can explain it. It’s awesome and inspiring.
Thanks!
After watching this, what you said about the fester’s quest key glitch makes so much more sense! Thanks for yet another great informative video!
11:23 - Oh yeah! So that would explain why, when messing with Game Genie codes (or playing certainly mean hacks...) - if you grab the flagpole, and a Lakitu is current active, and they drop Spinies on the right side of the pole, whenever the Spinies walk by Mario, you'll see a "shadow" of Mario walking in place after he "disappears" into the door way of the end-of-level fort (or whatever that building is supposed to be, anyway). (I don't recall for sure if this happens in X-3 levels with the castle structure at the end, but I've certainly observed it in X-1 and X-2 levels, so I imagine it would be the same there.) It also helps reveal the *one single solid block,* among the mass of non-solid tiles in the end-of-level structure, so that Mario doesn't have to be stopped, he can just run in place once he hits the spot where he's supposed to disappear. (That block is probably also why GameGenie codes that mess with the solidity of that block will prevent a stage from properly ending, as Mario will happily just walk off into the sunset, so to say, and the game never adds the timer to his score, and thus the game never completes the transition to the next level.)
I want to work in a GameBoy game in the near future. I feel like videos like this can help me in the future understand how the pros did things and try them out myself when I’m ready. Thanks for the video.
Oh yeah. Let's look into that flicker. I always wondered how shooters overcame this limitation.
Great video! I think this is once again showcasing your ability in making complex topics both easy to understand and interesting. I enjoyed this deep technical dive.
Love your tech dives into classic consoles. Back when game devs had to be clever about everything. :)
Informative! I had no idea that The Legend of Zelda and Castlevania used a limitation of the hardware as a feature to produce smooth layering of entities and background elements. I'm eager to see your discussion of sprite flickering.
As someone attempting to learn coding specifically for retro gaming videos like this are essential. I've always been curious about sprite priority and I'm glad you're touching on it. Thanks.
I'm also fascinated with the use of AND function you mentioned in your MSX video where, rather than priority, two overlapping pixels show up with a different pallette. I'm wondering if more games utilised this and if it puts any kibd of burden of memory usage or processing. Because I got so many ideas to play with since learning about that.
As usual, it's a joy to watch and learn, awesome videos!
Mario is actually 8 sprites rather than just 4. He's the same height as Super Mario in terms of number of sprites, they're just blank tiles when he's not super.
Excellent video! Your way of showing things via emulation debugging makes everything crystal clear. I would definitely be very interested in seeing a video on sprite flickering. Thank you very much for your work.
awesome just how much work was done to get all those subtle details correct! i would have never even given it a second thought- just like a lot of NES code procedures- if it weren't for this channel!
I really enjoy your videos - sometimes I even get some ideas for my hobby projects - of course, not on NES hardware, but Python and JavaScript :)
Awesome! Even more prime example on how to prioritize sprites is a game of "Gun Nac" - there in options you can choose how a render should behave 😎
Leave it to you to make a video on OAM and priority and not even mention flickering till the end. Id love to see what interesting bits you could tease out of that topic.
Great video as always I had no idea these games used priority as a feature. So cool!
Fantastic video, as always. One of the great remaining mysteries that may make for a good future video would be what exactly changes in subsequent loops of games such as Contra, Ghosts & Goblins, etc.
Ah, I understand now... The SMB3 part explains why, in credits warp speedruns, we see a red pipe outline when the runner clips into the pipe in 7-1 to go out of bounds. It's putting those sprites earlier in OAM than Mario, but behind the pipe on the background layer, so as to hide Mario as he goes into the pipe.
The only reason we see them here is that the pipe is being entered in a very unintended manner, from the side instead of from below, and going down instead of up. As a result, the sprites get drawn to a different place than usual. The game probably checks the tile underneath and to the left of Mario first, sees a pipe entry tile, and just assumes that there's another one to the right of it.
Awesome video.
Love this channel, such great content!
I love your technical dives. Keep it up!
Amazing how great this channel is. Love it! ❤
16:00 Very clever to use a hardware limitation as a feature!
Nice segue about flicker using Mario 2’s eyes. I always wondered about that.
Great video, really loved all the illustrations of how the limitations are used as features. I used to wonder why emulators don't just draw all sprites on a scan line because the flicker is quite annoying, but I see now that it's not that simple.
Of note: The "mushroom hiding behind blocks" thing in Mario 3 could also have been accomplished by simply assigning the sprite version of the block (used when it animated up and down) top priority and keeping it on screen until the mushroom was done emerging. And I wonder why they didn't just do that. I _can_ think of situations where you wouldn't want to, like you want your sprites to go behind some background element that _doesn't_ ever move and you don't have room in the sprite palette space to incorporate those colors. But in Mario 3, you already have the tiles' palette reserved in your sprite space for when they get hit.
I would think most NES programmers had just learned to use as few sprites as possible simply due to the severe limitations of the OAM. Like, its easier to just get rid of it asap and save space both in both OAM sections. Better that then having to review every single situation it could become an issue. Like they probably had to with powerups in SMB1 and background tiles.
It's also used for pipes, that's probably why
My familiarity is more with SNES stuff, but a surprising amount of this seems to still be applicable (including the "foreground sprite obscured by background sprite" oddity).
Too bad you can only like a video once. There were multiple times during the video when I wanted to put a like, but realized I'd already done it. Massive work was done! I hope such comments motivate you to carry on :)
Behind the Code is my favourite thing you do, this video is amazing
Awesome explanation! ⭐⭐⭐⭐
This was pretty interesting, nice video!
man this should be linked in the nesdev wiki page about OAM and such
Man, after that primer, you don't know how badly I want to know about sprite flickering.
Nice touch pointing out the tree tooth at the end!
Excellent! Bring on the flicker!
incredible work!
This was pretty interesting, Great video.
I love stuff like this. Thanks!
Thank you for great video again!
Thank you!
Going in detail on flicker would be really nice to learn about. I also want to point out the GB's way of handling more sprites than what it normally can (i forgot how much). For example, on Pokemon Yellow, having many sprites on a scanline causes one to simply disappear vs flicker. All I remember is seeing the Pikachu sprite disappear since you can control where it walks to a degree. IDK if that's just a game program thing or if that's actually the hard limit on the Game Boy.
Bring on the flicker!
I’m ready for that video about sprite flicker! I’ve got an idea for a 4-player game and this will help me determine if it’s even feasible the way I want to do it. Thanks!
Lovely explanation!
Great work!
I enjoyed this video, and would like to touch upon sprite flicker in a future video.
In Sonic 3 there is a graphics glitch in.Marble Garden Zone that looks exactly like your example of the goomba overlapping Mario in the background. I never knew what was causing that but I wouldn't be surprised if it's the exact same logic.
Very neat how they used the hardware "limitations" to their advantage, in a way.
MORE!!! Great vid!!
Another great video
Amazing video.
Amazing video, come on flicker video next let's gooooo
Nice! This is gold
I love your channel
“I told you this was gonna get technical.”
*9 whole minutes after it being technical*
Seeing how the two elements of Zelda use different methods, and do feel a bit different in game, I tend to think that they're not made by the same person. If it is, then maybe they came up with the sprite overflow one later on and didn't change the code for Link's stairs animation
Good video.
"Please sir, may we have..." MOAR videos, Displaced Gamers? (Wow, there is more than one of you? :D )
Lol is "grab a taco. This will get technical." Your catch phase.
"time to grab a taco, this one's about to technical"
I once saw in a video that the term for assembled sprites is "meta sprite", and assembled meta sprites is a "meta meta sprite". I'm not sure if I got this from one of your previous videos or from someone else's. It's possible the subject could have been about background tiles and I may have assumed the term to be used for sprites as well.
I've got a question regarding the 8 sprite limit per scanline. Why in the cases mentioned (Castlevania / Zelda) wasn't there put a single "mask" rectangular sprite same as SMB3? Wouldn't putting 8 sprites into the OAM hindrance the run of CPU?
Regards, great material!
Finally! Ive been checking every night, while I eat my bowl of raisin brand, for weeks now lol
Good dive. I'm curious why you went with "entity" and "sprite" when it probably should be "sprite" and "object". OAM holds info for Objects. Sprites are made up of Objects.
Hmm. I would say sprites and objects are synonymous. You could refer to a single 8x8 tile graphic that is placed on the screen as an object or a sprite.
"Entity" seemed to be a word that isn't used too often, and could serve as a single word to represent a "group of sprites" or "group of objects."
Since there is ambiguity regarding the definition of sprite in more ways than one, I elected to define the words at the start of the video so the narration would be clear and consistent.
So even if I change my mind on what I want to call them in the future, at least the video sets the table. Ha!
5:23 It is such a miracle that we have any games at all today. Jesus christ there are so many things going on with the TV and it's timing.
Are you open to topic suggestions? If so, I'd love to see a breakdown of how the Skydiving minigame in Pilotwings (SNES) works. It can't be very complicated, yet any time I've tried to conceptually wrap my head around how it should work it gives me a headache.
I hope I haven't commented this before and am just forgetting lol
Gotta love the Doug Demuro references :)
I get the feeling Gauntlet could have used that extra memory to mask the player & enemy tiles better. Seems like they just PRINT'ed the tiles over the walls and floor.
BRING ON THE FLICKER! ❤️ ❤️ ❤️
Could you talk a bit about animating those sprites - some games seem to have very simply 2-frame walk cycles, while others go to much greater lengths to depict smoother animation - is it simply a matter of those additional frames of animation taking up more memory and requiring more work, or is it a matter of how many frames you can play per second, etc? Cheers!
Cool 😎
We often called the assembled sprites and their associated state a "metasprite"
Interesting😁
Cool gaming