There's a new glitch in town. I discovered it while investigating the stun glitch routines, but Masterjun already used a form of this glitch at
Games Done Quick.
Sprite table $C2 is a 12-bytes region used by each possible sprite slot as a miscellaneous sprite table. Its mostly used as a sprite phase pointer or as a mirror of the stun timer ($1540 table) or for some other purpose. Kaizoman666 documented most of the usage in
this link.
When used as a phase pointer, it means that this address serves as an index for the routine that will be executed for said sprite.
As $C2 is expected to be a low value and SMW offers no exception handling, then executing higher values than intended will always result in garbage code being executed.
If you corrupt $C2 for some sprites, the game will likely crash, but sometimes it will execute code from "neighbors" sprites in the ROM. Rarely, it will execute misaligned code without crashing afterward. It's important to state that $C2 is an action pointer when the sprite is in status ($14C8) = 8, which is normal status.
The stun routine has the following code:
Language: asm
CODE_01965C:
LDA.w $1540,X
ORA.w $1558,X ;$01965F |
STA $C2,X ;$019662 |
LDA.w $1558,X ;$019664 |
BEQ CODE_01969C ;$019667 |
CMP.b #$01 ;$019669 |
BNE CODE_01969C ;$01966B |
LDY.w $1594,X ;$01966D |
LDA.w $15D0,Y ;$019670 |
BNE CODE_01969C ;$019673 |
JSL LoadSpriteTables ;$019675 |
JSR FaceMario ;$019679 |
ASL.w $15F6,X ;$01967C |
LSR.w $15F6,X ;$01967F |
LDY.w $160E,X ;$019682 |
LDA.b #$08 ;$019685 |
CPY.b #$03 ;$019687 |
BNE CODE_019698 ;$019689 |
INC.w $187B,X ;$01968B |
LDA.w $166E,X ;$01968E |
ORA.b #$30 ;$019691 |
STA.w $166E,X ;$019693 |
LDA.b #$0A ;$019696 |
CODE_019698:
STA.w $14C8,X
Return01969B:
RTS
It occurs when the sprite is at status 9 (carryable/stationary). It's easy to force this situation with Yoshi, using the double tongue glitch that is present in many TASes.
At the end, it can make this sprite return to status 8 (normal/usual).
At the beginning, it sets $C2 to $1540 OR $1558 = stun timer BINARY OR dying lava timer.
The latter part, that I will call
normalization, only occurs if $1558 is exactly 1.
Therefore we have: if a sprite is in status 9, then $C2 is overwritten. If also $1558 is 1, the sprite status will be set to normal.
If this $C2 is used, a glitch will occur.
If this $C2 is a phase pointer, a severe glitch will occur!
Setting $1558
If a sprite can be burned on lava, $1558 will be set to 0x40.
Usually, you can't do a thing with the sprite after that, unless:
1) you were carrying the sprite and throws it at the last possible frame. This way, the sprite will get status 9 and avoid death.
2) you have this slot on Yoshi's mouth and spit (holding down): the sprite is also going to get status 9, even if it's already burning for a while.
Some rare sprites also use $1558 for other purposes. Putchin' Chuck uses it for throwing baseballs.
Corrupting $C2
In order to corrupt $C2, you have to use the previous methods.
When $1558 reachs value 1, then $C2 will get value $1540 OR 1.
It means that $C2 = $1540 or $1540 + 1, the one the results in odd.
Setting $1540 while $1558 is decrementing
We have many ways to set the stun timer for sprites: hitting it with the cape, stomping some sprites, the sprite sometimes uses $1540 on it own, etc.
In rare cases, we can use a Lakitu on a cloud: hitting it with the cape will set the stun timer for whatever sprite is on slot 9.
$1558 is harder. Even if you set this timer, hitting the sprite with the cape will zero it.
The setup
1) Use the stun glitch method to store a slot X on Yoshi's mouth.
2) Make an interesting sprite spawn on slot X.
3) Set its stun timer using any known method and let it sink on lava: this will set $1540 and $1558.
4) Spit the sprite, making it carryable/stationary. As $1540 decreases slower than $1558, when $1558 gets 1, $C2 will have a higher value than usual.
Without lava
It's possible to do it without lava, IF the sprite uses $1558 on its own.
Example:
Using koopas entering a shell
When a koopa reaches a shell, it jumps into it. That sets $1558 to 0x10 and forces normalization of the shell.
If, however, the shell vanishes after the jump and another sprite spawns on the exact same slot, the the new sprite will be normalized.
We can combine this old glitch with the stun timer and Yoshi spit.
Example:
Side effects
There're thousands of possible side effects. We're interested in the ones that don't crash the game and don't execute any sort of arbitrary code.
We're still studying the good sprites and possible applications. This one deserves attention.
https://twitter.com/Bruno_Visnadi/status/1052081591898558464
Nathan is probably making a long video on this topic soon...