If you have watched any Retro Game Mechanics
Explained videos before, you have heard the little jingle that plays at the start of each
video. This sound effect is from Super Mario Bros.
3, a glitched version of the 1up sound. If Mario spins his tail at the same time he
collects a 1up, the two sound effects combine and produce this extended version. The reason this happens can be explained in
less than 10 seconds, but let's look at how SMB3 queues up sound effects that are ready
to be played. We may be able to find an underlying cause
for this programming mistake. Super Mario Bros. 3 fittingly has 3 queues
for sound effects. The first queue is for sound effects that
use the first square wave channel. These include the jump, bump, swim, kick,
pipe, fireball, p-meter, and frog suit hopping sounds. The second queue is for effects that use the
second square wave channel. This includes the coin, powerup out of a block,
vine out of a block, boom, text beep, powerup, 1up, poof, an unused sound, losing Kuribo's
shoe, and tail wagging sounds. The third queue is for effects that use the
noise or triangle wave channels. This includes the breaking brick, fire cannon,
boomerang, airship flight, hammer bro marching, and Mario skidding sounds. Each queue uses two bytes to help with managing
sounds. One byte is used to determine what sound effects
should begin playing on this frame. The other byte is used to tell which sound
effects are currently playing on this channel. Each sound effect in each queue is represented
by a single bit. When a sound should be played, its corresponding
bit will be set. If more than one sound is triggered in one
frame, then both of those bits will be set. When it comes to actually playing the sound,
the entire byte is examined, starting from the least significant bit and working upwards. This means that sounds that are assigned lesser
significant bits are prioritized over higher significant bits. After the sound is initialized, the whole
first byte is copied to the second to keep track of what sound is playing. For example, in the first queue, the jump
sound effect is assigned to bit 0, so it will always play instead of the other sounds in
this group. Jump and throw a fireball at the same time,
and only the jump sound will play. However, jumping on one frame, then throwing
a fireball on the next frame will cause the fireball sound to overwrite the jump sound. This happens because when the value is transferred
from one byte to the other, currently playing sounds are halted. This method of assigning sounds to bits makes
for an easy priority system when more than one sound is played on a single frame. If the sounds were assigned to entire bytes,
triggering one sound could overwrite the other, and this would be dependent on which triggered
first in the game's code. The one downside to this method is that one
byte can only control 8 sound effects--one for each bit. If they were assigned to bytes, 255 different
sounds could be controlled by one memory address (assuming 0 meant no sound). Unfortunately, the second queue has a problem. It has 11 different sound effects assigned
to it. The first 7 sound effects are assigned to
bits, but then the other 4 are assigned to bytes. Combining both systems made for some unintended
side effects. Let's look at this in more detail. The coin, powerup reveal, vine reveal, cannon
boom, text beep, powering up, and 1up sounds were assigned to bits 0 through 6 respectively. However, if the most significant bit was set,
the queue was treated byte-wise instead of bit-wise. The poof sound was assigned to $80, the unused
sound $90, the Kuribo's shoe sound $A0, and the tail wagging sound $B0. Now in general, this system worked fine. But, the priority system and having two sound
effects queued at once breaks down if one of them is treated bit-wise and the other
byte-wise. For example, what would happen if a coin sound
effect and a poof sound were played at the same time? The poof sound is assigned to $80, and then
the coin sound is assigned to the least significant bit. When both queued together, the entire byte
reads $81. Now the most significant bit is set, so this
value is treated as an entire byte when determining what sound to play. But $81 isn't assigned to any sound effect! This is the first flaw of the second sound
effect queue. Let's organize everything into a nice table. The values of this table will be which sound
effect actually ends up playing when the corresponding value is in the queue. We can fill in the 11 sound effects with their
assigned bits and bytes, along with $00 which denotes that no sound will play. First let's look at when the most significant
bit is cleared--which corresponds to just the top half of the table. We know the coin sound plays when the least
significant bit is set. So it will play any time this bit is set,
not just when it is set alone. It makes sense that half of the table fills
with the coin, because it has the highest priority out of all the sound effects. Then we move up to the 2nd bit, the 3rd, 4th,
5th, 6th, and finally 7th. Okay, now the other half of the table, when
the highest bit is set. We have these 4 sounds that are assigned specific
bytes, but out here is what we are interested in. It turns out that while the poof, unused,
and Kuribo's shoe sounds are checked for explicitly, the tail wagging sound is given to any value
that doesn't match any of the others. Therefore, if the value is not $80, $90, or
$A0, the tail wagging sound will play. So the entire rest of the table fills with
this sound effect. And it checks out! It's not too difficult to collect a coin on
the same frame raccoon Mario takes damage. If he does, the tail wagging sound effect
plays even when he doesn't spin his tail. Theoretically, you can get this sound to play
if you combine other sound effects as well. So, let's look at what happens when we queue
up both the tail wagging and the 1up sounds at the same time. Tail wagging is assigned to $B0, then the
1up is assigned to bit 6, so we end up with a value of $F0 when combined. Hmm, this table is missing something. We have to discuss the second flaw of the
second sound effect queue. It turns out the 1up sound is special. Maybe it came up late in development, but
the designers decided that the 1up sound is really important, and it needs to be prioritized
over every other sound effect. It isn't uncommon that the extra life sound
effect in games to be prioritized like this, and many old arcade games even chopped out
the music just to play this sound. However, this feature is quite contradictory
of the priority queue system that is already in place. Not just that, but the 1up is assigned to
bit 6, one of the lowest priority sounds. Now our pristine priority queuing system is
being even more mangled when we implement a special case for the 1up sound. It's implemented a little wonky however. We have to delve a little deeper into the
code if we want to understand it. Earlier it was mentioned that two bytes were
used per queue, one for new sounds to be initialized, and one for the currently playing sound. When a sound is initialized, the value from
the first byte is copied to the second, and the first is reset back to zero. Makes sense, whatever sound we initialized,
keep playing it until it finishes. Once the sound finishes playing, this byte
is reset back to zero as well. But the interesting thing is when more than
one sound is queued at once. Like we already know, only the sound with
the least significant bit assigned to it will play. So it will be initialized, and this byte will
be transferred over, and that sound will keep playing. The same method of determining which sound
to initialize is used to determine which sound will continue to play. So normally the same sound will be found each
time. It would never be the case that one sound
would be initialized, but a different one would be assigned to continue playing. Or would it? The method used to prioritize the 1up sound
over all others only applies to the continue playing byte, and not the initialization byte. For example, if a coin and a 1up were collected
on the same frame, the coin sound would be initialized due to its higher bit priority. But on the next frame and onwards, the 1up
sound will be continued to play, due to the hardcoded 1up priority. You can even hear it a little when you collect
both items at once. The coin plays for a split second, then the
1up takes over. There is one big issue with this disparity. Certain values are loaded into memory when
a sound is initialized. If these values don't match up with the sound
effect that is actually playing, things may mess up. The 1up and coin sounds happen to play nice
with each other, but some of the others don't. The major parameter that causes weird things
to happen is the length parameter, which determines how long the sound effect will play. The 1up and coin happen to be around the same
length, so they work fine, but not all of them sound correct. Here are what each of the other sound effects
sound like when played on the same frame as the 1up sound effect. Let's look back at the table we made. We have to update every entry in the table
that has bit 6 set, which corresponds to the 1up. They all play the 1up sound instead, but a
corrupted version of it, which depends on which sound effect would have played without
the hardcoded priority. Aha! Now we can see that our point of interest,
value $F0, now says it plays a corrupted 1up sound corresponding to the tail wagging sound. But if you think about it, the tail wag sound
is pretty short, why does it produce such a long corrupted 1up sound if the corruption
transfers the length parameter from one sound effect to another? There's one last piece of the puzzle, and
it has to do with these 4 byte-assigned sound effects. These 4 sound effects are stored in a different
format than the 7 bit-assigned sound effects. They are also stored in a different location
in the ROM, actually along with the sound effects for sound queue 3. Instead of using a counter to determine how
long they should play, they use the same memory address as an offset within the sound effect
data. So in the case of this one corrupted 1up sound,
the length of the 1up sound effect is determined by an offset into the tail wagging sound data
instead of its length. The value of this offset can be relatively
large compared to any of the other sound effects' lengths. This is why the sound is so drawn out. The notes that are actually playing are actually
the end of the powering up sound effect, since they are stored next to each other in ROM. The two sounds convert the data into notes
differently, so they don't sound similar, but they do use the same data. Side note here: the powerup sound actually
has a few more notes to it that never play because the length parameter supplied to it
is shorter than the amount of data that actually exists. Here is what it would sound like if it weren't
truncated. At the start of the video I mentioned the
cause of the problem could be explained in less than 10 seconds. Let's look at the third and final flaw of
the second sound effect queue. We'll have to look directly at some assembly
code. We'll start at the point in the code directly
after it is determined that the highest bit has been set in the queue, and the value should
be treated as an entire byte instead of bit-wise. First, the Y index register is loaded with
the value in the sound queue. It's compared to $80, the value of the poof
sound. If it's equal, the corresponding sound data
offset is loaded into the accumulator, then we jump a bit forward. The same comparison is made to $90 for the
unused sound, and $A0 for the Kuribo's shoe sound. Then, before preparing to initialize the tail
wagging sound, we check if any sound is currently playing right now. If there is, we cancel initialization, and
just work on continuing that sound. This means the tail wagging sound will not
overwrite any currently playing sound. However, if there is no sound playing, we
load in the sound data offset for the tail wagging sound, and meet up with all the other
branches. At this point, Y still holds the queue value,
and A holds the data offset. The data offset is stored into its memory
address, then Y and transfered to A. Then, look at this! The accumulator is ANDed with the value $B0. This is done in the accumulator since there
is no instruction for executing an AND on the Y register. This AND operation is done to specifically
mask out bit 6, so that the 1up sound is specifically cancelled out in case it was initialized along
with one of the byte-associated sound effects. Since bits 0 through 3 are also masked out,
there are only 4 possible values the accumulator could hold after this instruction--the 4 IDs
of the 4 byte-assigned sound effects. Then this value is stored into the currently
playing byte. Wait, what? The Y index register is written to this address
instead of the accumulator! What was the point of the AND instruction
then? And then directly afterward A and Y are both
overwritten with other data! They were so close to preventing this glitched
1up sound, they even thought of it! But for some reason this instruction is an
STY instead of an STA, so all the work was for naught. So the 10 second explanation goes like this:
There's a priority queue for sound effects. Except it's really half priority queue, half
hardcoded nonsense. Half of the sound effects conflict with one
another. There was code to prevent it, but the wrong
instruction was used so the conflict persists. Thank you for watching! If you enjoyed the video, please consider
liking it or sharing it with your friends, and consider subscribing to the channel. I have everyone to thank, from every single
viewer, to all of my patrons over on Patreon that help support me and my work. It's thanks to everyone that I am able to
continue doing what I enjoy, making videos. With all the support I am able to justify
spending the time writing and editing. So just the fact you are listening to this,
thank you!