This is a glitch originally discovered by Yuzuhara (color me surprised), and it was pretty exciting when it first made its rounds. It provided a couple decent improvements to a potential NMG TAS, but after a couple weeks, it fell off everyone's radar. Except for mine. Due to its obscurity, I had implemented it into a glitch puzzle that would end up being released for the Fall 2020 Randomizer. The puzzle was built back in January of that year, so I had been sitting on it for a while for 2 reasons:
Unfortunately for me, this tech was rediscovered by otherTom in April, and it managed to stick this time, at least somewhat. Ironically, the obscure glitch I thought would be easiest for people to figure out (specifically, I assumed fsg would get it immediately) was what stumped everyone. No one managed to figure out how to light the walled off torch. After 1 week, I had won.
I had originally planned to write an explication for this "when we get closer to release", but never did. Then I suddenly felt motivated to write this.
The most glaringly obvious, easy-to-see, couldn't-miss-it-if-you-tried consequence of carrying a bomb with spinspeed armed is that Link has a funny walk where he changes directions every few frames. This is caused by errors in calculating
$2E, which controls Link's current animation step.
Link's animations are handled by using a handful of variables to determine a specific pose ID. This pose ID is then used to look up the placement of Link's head/extremities relative to his body, their properties, and the location in ROM to copy their character data from. This pose index table begins at
$0D:85FB. We want to specifically look at the "carrying item walk" animation, at these addresses in ROM:
|Animation||Animation step ($2E)|
From this table, it's reasonable to conclude that each of these animations has 6 steps in its cycle. This makes data bleed a very likely explanation. If we watch
$2E while carrying an item with superspeed, we see this value is actually reaching as high as 8. The culprit of this erroneous animation step cycle is the routine at
$07:E68F. This code performs various checks to handle the step to use, and the short answer is: it just happens to check
$0372 for dashing before it checks
$0308 for carrying.
So this explains why the animation is weird, but why does that mess with the bomb?
It messes with the bomb because, as you may have noticed, the bomb (or whatever ancilla you're carrying; I'm just going to keep saying "bomb"), moves up and down along with Link's head and arms. This is tied to Link's animation step at
$2E, which is used to index a particular table at
$08:993F for a signed 16-bit Z-position offset:
|Animation step ($2E)|
But this table only has 6 values, so we need to look at the next table to see what it bleeds into. The table that follows the Z-offset happens to be the velocity of the bomb on the Y-axis, based on what direction you're facing. But the problem is made messier by the fact that this velocity table supplies signed 8-bit values. If we treat them as signed 16-bit values and append them to our Z-offset table, we end up with this (we also need to read even further to the next table, which is the X-axis velocity):
|Animation step ($2E)|
Oh me, oh my. That's a big number. The Y-velocity table ends with
32, or, in hexadecimal:
0x20. To treat this as a 16-bit number, we swap the order of the bytes (because the 65c816 is a little-endian processor), and concatenate them, giving us
0x02E0, or, as I put in the table above:
On a related note, this animation step indexing also explains the prayer animation you can get while walking in tall grass with spinspeed or a well-timed dash buffer. The animation looks normal most of the time because dashing or walking in tall grass or water only has 6 animation steps, but, if you can reach the tall grass on the same frame your animation counter hits a number higher than 5 while facing right, it will keep that value for the next frame (because the animation steps every other frame). And, by a beautiful miracle of some benevolent god, the prayer pose index table immediately follows the tall grass table.
The dashing variable set when arming superspeed is checked first for indexing animation steps. The dash animation has more animation steps than the carrying item animation, so data is read out of bounds for Link's poses, as well as for the carried ancilla's altitude, which also uses animation step as an index. Two of the values in this overflow area are 0, but one happens to be a large, positive number when interpreted by the code.
Grass prayer works on a similar principle: the dashing flag overflows the animation step counter for walking in grass, but only when not in grass. This means it's only visible if you happen to be in the grass on the 1 frame of animation stepping delay for a higher value.