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

Dissecting Super Mario Bros.

Dissecting Super Mario Bros.
by on (#94265)
As the topic indicates, I've been looking through the Super Mario Bros. source code (and some related posts) to better understand how it works. A few questions:

- Sprite 0's tile is the bottom sliver of the status bar coin, which appears to sit behind the coin tile that color cycles. However, when Mario breaks through the upper boundary (e.g. 1-2) and stands in front of the coin, that small sliver appears in front of his leg. What is the priority of sprite 0 and what exactly is showing through? It seems to be the only portion of the status bar that Mario doesn't obscure. I am not clear on tile priorities in this case. Does sprite 0's collision still work if it is behind BG tiles?

- When I load the ROM in FCEUX and watch the name tables, the scroll bar never moves. In most other scrolling games, it tracks along the name tables as expected. Is this a FCEUX anomaly or something else I'm missing?

- tepples has mentioned previously that SMB uses a 32x13 metatile sliding window in RAM for collision purposes. In certain cases, Mario can kick a Koopa shell offscreen and follow it until it rebounds from a nearby obstacle but without colliding with enemies directly offscreen. Are enemy objects spawned in a tighter perimeter than the collision buffer so that a ricocheting shell can miss them on the way out but collide on the way back (once they are visible)?

- I'm not very experienced with debugging tools. How could I experiment with repositioning sprite 0 (e.g. move it further down the screen)?

- I understand how the coins/question blocks use palette cycling to 'shimmer' but I can't figure out how the fire flower works. In Nintendulator it looks like the sprites are quickly changing, but I don't see any palette changes.
Re: Dissecting Super Mario Bros.
by on (#94274)
noattack wrote:
- Sprite 0's tile is the bottom sliver of the status bar coin, which appears to sit behind the coin tile that color cycles. However, when Mario breaks through the upper boundary (e.g. 1-2) and stands in front of the coin, that small sliver appears in front of his leg. What is the priority of sprite 0 and what exactly is showing through?

That's the triple overlap condition. Sprite 0 is in front of everything else. The priority bit in each OAM entry doesn't really mean "put this sprite in back"; it means "replace pixels in this sprite with pixels from the background if they aren't transparent". So because sprite 0 is in front of Mario, and its pixels have been replaced with the background pixels that it overlaps, it brings the background pixels in front of Mario.

Super Mario Bros. 3 uses this on purpose in order to cover up items sprouting from blocks. It can't just turn on the item's priority bit because sometimes the space above the block might not be completely flat background color. Notice that when you get something out of a note block, the note block turns squarish. That square is the mask sprite placed "behind" the note block but in front of the item, so that the mask sprite can bring background pixels to the front.

Quote:
Does sprite 0's collision still work if it is behind BG tiles?

Yes, the PPU still detects the overlap. The priority flag just tells which pixel to use in case they do overlap.

Quote:
- When I load the ROM in FCEUX and watch the name tables, the scroll bar never moves. In most other scrolling games, it tracks along the name tables as expected. Is this a FCEUX anomaly or something else I'm missing?

I can't use the Name Table Viewer myself because my laptop's screen isn't tall enough. But does FCEUX let you tell which scanline to watch for the map display? If so, perhaps it's set to watch line 0 and base the scroll bar on that. If not, perhaps it's hardcoded to line 0.

Quote:
In certain cases, Mario can kick a Koopa shell offscreen and follow it until it rebounds from a nearby obstacle but without colliding with enemies directly offscreen. Are enemy objects spawned in a tighter perimeter than the collision buffer so that a ricocheting shell can miss them on the way out but collide on the way back (once they are visible)?

Perhaps the enemy-to-enemy collision detection is just programmed differently from the enemy-to-background collision detection.

Quote:
- I understand how the coins/question blocks use palette cycling to 'shimmer' but I can't figure out how the fire flower works. In Nintendulator it looks like the sprites are quickly changing, but I don't see any palette changes.

Does it change what palette number (0 through 3) is written to bits 1-0 of attribute 2?
Re: Dissecting Super Mario Bros.
by on (#94279)
tepples wrote:
That's the triple overlap condition. Sprite 0 is in front of everything else. The priority bit in each OAM entry doesn't really mean "put this sprite in back"; it means "replace pixels in this sprite with pixels from the background if they aren't transparent". So because sprite 0 is in front of Mario, and its pixels have been replaced with the background pixels that it overlaps, it brings the background pixels in front of Mario.

Super Mario Bros. 3 uses this on purpose in order to cover up items sprouting from blocks. It can't just turn on the item's priority bit because sometimes the space above the block might not be completely flat background color. Notice that when you get something out of a note block, the note block turns squarish. That square is the mask sprite placed "behind" the note block but in front of the item, so that the mask sprite can bring background pixels to the front.


That's fascinating - never knew it worked that way. Thanks!

tepples wrote:
I can't use the Name Table Viewer myself because my laptop's screen isn't tall enough. But does FCEUX let you tell which scanline to watch for the map display? If so, perhaps it's set to watch line 0 and base the scroll bar on that. If not, perhaps it's hardcoded to line 0.


Yep, that was the problem. Once I set it to scanline 32, it worked as expected.


tepples wrote:
Does it change what palette number (0 through 3) is written to bits 1-0 of attribute 2?


I'm not sure how to check that. Still grappling with understanding attributes...