Thursday, August 4, 2011
Falling barrel glitch (the wonders of uninitialized variables)
Today, I decided to investigate some strange behavior that occurs occasionally when DK throws a barrel. Normally when a barrel is thrown, it lightly bounces as it lands on each girder. If you watch carefully, you’ll see that occasionally the thrown barrel will miss a girder and bounce off the next girder instead.
This is due to a check at $20F0 that causes ground hits to be ignored if they happen too close together. How close? Less than 26 pixels (a little over three tile rows). It does this by recording the Y-coordinate every time the barrel hits a girder, and by comparing the current value with the last value. Despite this check, occasionally a barrel will be thrown that drops straight from DK’s hands to the bottom girder without ever hitting any girders in between.
There’s nothing intentional in the code to cause a barrel to do this. There are definitely different ways that the game will direct a thrown barrel as it touches down on successive girders, but no instructions to actually ignore them altogether.
Why does it happen? For one simple reason. The Y-coordinate mentioned above is only initialized (zero’d) at the beginning of the board. This means that once a barrel is thrown, it retains the Y-coordinate of the last girder it landed on (this is usually, if not always, the second to last girder). So, when a new thrown barrel reuses a record previously owned by another thrown barrel, the check at $20F0 causes all girders except the last to be ignored. The more barrels that are thrown, the more likely a new barrel will use an old thrown barrel’s record, and the more likely this behavior will occur.
Watch for it!