As it will happen eventually, destroying all my previous work for this game, have fun watching even less of this game.
- Emulator used: lsnes rr2-β21
- Aims for fastest time
- Uses game-breaking glitches
- Achieves credits early
Go ahead and watch the TAS first, it doesn't really take that long.
This is basically the reason why I cancelled the Kirby Super Star submission. You can maybe see why I prefer the previous movie over this one. But first...
What happens this time?
Let's start at the basics. In SMW there are sprites which can change the status of Mario called powerups (such as mushrooms, flowers, stars and so on). It's easy enough for the game to just run a routine to change it as soon as Mario touches a sprite which is listed as a powerup. Now the problem comes when Yoshi eats a sprite, because if it is a powerup, it should be applied to Mario. The game checks if the sprite has a specific property that says the game if it should give Mario a powerup when it is being eaten. Interestingly enough, chucks have this property! Normally, this isn't a problem because you can't actually eat chucks because they have another property which ensures that the sprite won't be caught by Yoshi's tongue (it goes right through), making it impossible to get it on Yoshi's tongue and eat it... or is it?
This glitch is also used in the warps run in YI2 to get the goal tape to replace the shell on Yoshi's tongue, getting the level end earlier or in YI1 to replace a sprite on Yoshi's tongue with a chuck so that Yoshi can... eat it!
This is what I'm doing, too. I replace a sprite on Yoshi's tongue with a chuck. How do I do that? Well, it is possible to get a coin by touching it, but it is also possible to get a coin on Yoshi's tongue. Now just do both things at the same time (see pictures on the right) and Yoshi's tongue will hold a nonexistent sprite or simply nothing. All the game now knows is that Yoshi's tongue holds a sprite in a specific slot and if in that moment a sprite such as a chuck wants to spawn in that slot, its position will be overwritten since it's now on Yoshi's tongue. Yoshi is now able to eat the chuck which is apparently a powerup to the game.
Eating a chuck
Since the chuck powerup isn't intended by the developers and accidentally in the game, the code doesn't account for it and incorrectly indexes the sprite to put in the item box (which is a lakitu cloud) and also gets the subroutine location wrong to jump afterwards. Instead of jumping to a routine to change Mario's status, it jumps to $014A13... which is Open Bus.
Open Bus is an area in the SNES which isn't mapped to a location like WRAM or ROM, which means no such device answers the request from the console to get the next instruction to execute. This means that the console will just execute whatever value was the last one on data bus.
The code just jumped to $014A13 so the last value on data bus is 0x01.
|0x01||ORA ($01,x)||X is 0x09, $0A holds 0x0107, $0107 holds 0x17, A turns to 0x17 and data bus is 0x17|
|0x17||ORA ($17),Y||$17 is interesting because $17 and $18 are SMW's controller data, so this is where I can kinda manipulate the outcome|
This is the reason why I pressed X and the next frame AXL just before the glitch started so that $17 is 0xE0 and $18 is 0xA0. The code manages to change the SNES to emulation mode so now it can survive BRKs easily, as the vector changed. Then it managed to reach $4219 which are controller registers.
These are the last 5 frames of input:
1-1 1-2 2-1 2-2 F. 0 0|....u.l.AXL.....|BY..u.lr...R....|.Ys..d..AXLR0.23|................ F. 0 0|...Su...A.L.0..3|BY..u.lr...R....|.Ys..d..AX.R0...|BYsSu...A....... F. 0 0|..sSud.rA....123|BY..u.lr...R....|.Ys..d......0.23|BYsSu...A....... F. 0 0|....u...A.L.0..3|BY..u.lr...R....|.Ys..d..A.L.0.23|BYsSu...A....... F. 0 0|BY...dl.A...01.3|B........XLR..2.|..s........R..23|BYsSu...A.......
or in bytes ($4218 - $421F):
E0 0A FB 64 10 CB 00 00 A9 18 D8 64 10 CB 80 F8 87 3D 0B 64 10 CB 80 F8 A9 08 AB 64 10 CB 80 F8 8D C6 13 20 72 80 80 F8
One thing to notice is that "64 10 CB" and "80 F8" occur often. "64 10 CB" is executed as STZ $10 : WAI which STores Zero to $10 and then WAits for an Interrupt. That effectively advances one frame and lets Auto-Joypad Read finish so that we have new input. Then it executes "80 F8" of the next frame (which is why there isn't one in the first frame). "80 F8" means BRA $F8 or BRAnch -8 bytes (or simply 8 bytes back), so we reach $4218 once again and can execute more code.
(The 0xE0 in the first frame isn't actually executed since we start at $4219, which is good because we needed that for the Open Bus part)
|0A||ASL A||used for clearing carry|
|FB||XCE||to recover to native mode after emulation mode to safely let NMI execute|
|A9 18||LDA #$18||load 0x18 into A for the game mode later|
|D8||CLD||clear decimal mode flag to avoid the game getting confused with calculations|
|87 3D||STA ($3D)||store A to whatever long address is in $3D, which happens to be $000100 which is the game mode|
|0B||PHD||push direct page register so that I have 00's on the stack for later|
|A9 08||LDA #$08||load 0x08 into A for $13C6 later|
|AB||PLB||pull data bank which is now 00 thanks to the PHD before|
|8D C6 13||STA $13C6||store A to $13C6 to complete all necessary steps|
|20 72 80||JSR $8072||jump to the main game routine and free the game from any further gameplay|
Special Thanks to:
- Ilari for explaining Open Bus to me
- Pat for not being able to chuck-glitch
Nach: Accepting as improvement to existing run.