professional games industry web engineer and games hater


nathanisbored
@nathanisbored

Inspired by RGME, this is going to be a series (hopefully) about things in the Super Mario World engine that I find interesting. Let's look at some code! So to start off, take a look at this innocuous looking GIF:

Would you believe there's actually two distinct programming bugs on display here? Just from sliding down this pipe!

...OK well they are almost completely unnoticeable, and you wouldn't be able to guess there's anything fishy going on here without looking at the code. But that's what makes this pointless trivia interesting to me! Let's dive deeper.


What you might notice if you squint really hard is that as Mario is sliding, he is producing dust behind him! You might have already guessed it's related to that (or you might have noticed the image filename). In fact, both of the bugs are related to this little dust graphic:

The second frame here is also used as the eyeballs when a Koopa is hiding in its shell after being stunned

OK, first of all, "dust"? Well actually often times people refer to these little particles as "smoke", since they're all white and opaque. Y'know, like Mario's sliding or skidding so fast the friction is making the ground below him heat up, like a screeching car (he's a cartoon, we can exaggerate). Fine, you can call it smoke if you want, but I've always thought of it like dust that he kicks up, like running bases around a baseball field. I'm gonna go with dust for this post, but just know that other resources that talk about these little sprites might use "smoke" instead. Anyway...

So these dust particles appear when Mario skids too, meaning he turns around when running and does a little skidding animation. These particles also show up if you start crouching while running, like he's sliding into home base. So yeah, you don't even need a slope. But a slope is good for what I'm trying to demonstrate. By the way, of course Mario can slide down a slope on his butt, but did you know he can also do a belly slide? Check it out:

If you didn't know, this has all the same properties as a regular slide, except you can't cancel it by pressing a direction. And here's the other two animations that cause this dust effect:

OK so both bugs are a result of this subroutine, which runs during each of those animations:

Let's break this code down one piece at a time. First of all, this part:

You can think of this as basically an IF/THEN statement. It checks IF:

  • the frame counter is not a multiple of 4
  • or Mario is airborne
  • or he's too close to the edge of the screen horizontally
  • or he's too close to the edge of the screen vertically
  • or an animation is playing that freezes gameplay

THEN just return and don't run any of the following code.

Makes sense right? The notable thing here is that the code only runs if the frame counter is a multiple of 4. In fact this is the global frame counter, so you can manipulate when the dust spawns by pausing the game! But that's not actually one of the bugs I wanted to talk about. Consider it a bonus.

So looking at this GIF again:

That explains why the dust particles are spaced out every 4 frames. But wait, why's there that big gap every 3 dust sprites? We'll that's actually just a limitation the developers posed on how many of these sprites can be loaded at a time. They only allocated 4 slots for them. So you might be wondering why there's only 3, if there's 4 memory slots. That's actually one of the two bugs in action! But I'll get to that shortly.

First, let's talk about the next bit of code, because there's something interesting happening there too:

The execution flow here is a bit nonlinear, so I won't go through this line by line. But what's happening here is, first it checks if the player is holding down on the d-pad, and if so it checks if their speed is too low to spawn dust. The speed range is from -8 to +7 subpixels per frame, but you don't need to know what those units mean. The point here is it is intended to have the effect of preventing the dust from spawning if his speed is too low while sliding.

So why does it check if the player is holding down? After all, this code only runs in the first place if he's in a crouching or sliding animation. Well remember that this code also runs if he's in the skidding animation from turning around while running. The developers wanted the dust from the skid to still show while turning around, even though he would inevitably have low speed during the skid. So in this subroutine, it has to distinguish whether he's turning around or sliding/crouching, and it does so by checking if we got here by holding down or not.

And herein lies the first bug. You don't have to be holding down when sliding! Mario will continue his butt slide even if you let go, unless you cancel it by pressing another direction. Not to mention, you never need to press down if he's sliding on his belly! So what does this mean? What effect does this have in game? Well it just means dust will spawn when it's not supposed to, when his speed is super low! Here's a comparison: Top: holding down as intended. Bottom: not holding down.

Subtle, right? Well let's talk about that other bug...

Here's the next part of the code, and the last part we'll talk about:

This is a simple loop. After all the conditions are met for dust to spawn, we still need to check that there's memory available for it. That's what this loop does. It checks all 4 of the memory slots, starting from slot 03 and working down to slot 00, until it finds one that is empty, and then it exits the loop to go spawn the dust. If it doesn't find any, it returns instead.

...Only there's a problem: It doesn't actually check slot 00 at all! The loop counter here is also used as the slot index to check, and it decrements the loop counter before the loop condition is checked. And since the loop condition is only checking for a nonzero value, only slots 03, 02, and 01 actually get checked, so dust can only spawn in those 3 slots. So that explains why we saw the dust spawning in sets of 3 before.

But wait, how do we know this is a bug? After all, they deliberately only allocated 4 dust slots to begin with, how do we know only using 3 of them wasn't deliberate? Maybe they only wanted 3 to spawn at a time, to make the sets of dust feel more spaced out. Well here's the thing: there's other effect sprites that use those same memory slots too! In fact, when you collect a coin, the sparkle spawner also uses these slots. But only the dust is unable to use slot 00, which can lead to some weirdness when both effects are present at once.

Take a look at this: Now the dust spawning is even more erratic! In short, having that one extra sparkle spawner in the mix shuffles things around a lot. But importantly, the first gap happened after only 2 dust this time. That's because the dust sprites were squeezed into slots 02 and 01, since they couldn't use 03 or 00. Slot 03 was already taken by the sparkle spawner.

Going back to the code, here's a simple fix they could have used:

And that's it for now! I hope to do more of these when I feel inspired, because I love looking at quirks of SMW's code. Thanks for reading!


You must log in to comment.

in reply to @nathanisbored's post: