For a while now I've had the theory that many of the more exotic crashes we can get in A Link to the Past were not just a crash, but something we could take full control of. Previously, the only known and confirmed way to gain total control of the game was a method that took a lot longer to perform than the non-ACE method. This new route uses a completely different technique to utterly quash ACE's previous inferiority. Best of all, it must be mentioned that we completely skip over the ending text that normally precedes the credits. That text would be about 45% of the run were it included, taking around 3000 frames to sit through.
Categories:
Major skip glitch
Executes arbitrary code
Heavy glitch abuse
Fastest completion
Genre: Action
Genre: Adventure
Uses lsnes rr2-β23 (bsnes v085 compatibility core). Rerecord count is inaccurate. It's actually probably like 2000, but most of it was lost in the conversion. Not something we really care about though.
Route
Beginning
The beginning is boring. The same nonsense you see at the start of every run. "Link, save me!" Blah blah blah. Uncle walks out and tells us to stay put, but we ignore him.
Outside
Outside we use a teleport to reach the cliff and then jump off of it to almost wrap the screen, allowing us to walk eastwards to the other cliff. A teleport directly to the other cliff would have been faster, but the guards make it impossible to reach the corner. As there is no way to clip into other parts of a ◢ slope without boots, this was the only option.
We need to move up 4 pixels before transitioning south, or else we will get a funny auto-walk thing. A few frames are saved on the third overworld screen by transitioning to land inside of the cliff, where a couple snaps are used by moving down 2 pixels then moving up to get booted down 6. We then hop down the cliff back in bounds and enter the fortune teller's house.
ACE
Inside the fortune teller, we do 1 pixelport south followed by v, <^v> 7 times to move us down 7 pixels such that we'll be stuck a little into the wall. At that height, we move as far right as possible then down to trigger a south supertile transition.
That's where things break badly. The fortune teller is a single entrance building, meaning it appears on the secondary underworld map. This map is smaller and will get confused when we go south, which, in this case, attempts to load room 0132. As this room doesn't exist, it ends up reading outside the table for room data and proceeds to load random garbage values into the memory locations where room data is stored. One of the corrupted values read is $FF into memory location $AD (Hold the value for special room "effects). This value is later used by the game to determine if there are any special effects, but since this value is way out of bounds it causes the CPU to jump to "open bus" and eventually end up executing a "BRK" instruction. This instruction in turn jumps to $00FFFF in ROM where there's the value for a "branch long" instruction that executes a jump. The location from this jump will be read from $000000-$000002 because of a wraparound from $00FFFF. As luck would have it, those addresses contains the controller inputs left there by the controller reading routine that executed just before this crash happened. From there on it's business as usual when it comes to ACE on the SNES. A jump to controller registers is done and execution is kept there in a loop by executing code entered by 4 controllers, waiting for the next frame and then looping back. This code ends up storing $1A to $10 and $00 to $11 to set the game mode to credits and then jumping back into the main game loop and letting the game resume from there.
Do doo ♫ do doo ♫ do do doo do doo
Do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫ do doo ♫ do doo ♫ do do doo do doo ♫
Credits
Unfortunately, we lose. Ganon's music begins playing during credits, signifying the bad ending that no one knew existed.
That's it
Thanks to
Yuzuhara for working on this movie and optimizing the route ~10% by moving the game crash from the dam to the fortune teller.
total for even looking at this and getting the ACE working and converting to lsnes. Was not expecting him to chime in.
Pinkus for discussing a lot of things I honestly don't understand that well with total.
Acmlm for his previous ACE shenanigans and looking at this method initially when pinged.
Myramong gave 1 suggestion. Hello Myramong.
Tompa for being Tompa.
Stuff
Suggested screenshots:
3238
7649
feos: As explained in this post, everything this movie claims to be doing it is indeed doing the way it is described.
The value that arbitrary code ends up setting is a condition that defines the credits routine; that address contains the same value in other ALttP movies right before they roll.
After the ending I can reset the game and use the save that is created, and its contents are fundamentally the same as in other ALttP movies, aside from the Pyramid top not being broken, which isn't a requirement, just a leftover when final boss is reached normally.
So everything happens and functions as it should, and this movie is legitimate.
I remember that previous ACE control used on Acmlm's submission (back from 2016), and now, it's another game defeated. And even more broken than before.
Yes vote.
My homepage
--Currently not much motived for TASing as before...--
But I'm still working.
Remember when you said you had no idea how to improve the game end glitch?
Well congrats on finding an idea on how to improve the game end glitch.
Yes vote.
[14:15] <feos> WinDOES what DOSn't
12:33:44 PM <Mothrayas> "I got an oof with my game!"
Mothrayas Today at 12:22: <Colin> thank you for supporting noble causes such as my feet
MemoryTAS Today at 11:55 AM: you wouldn't know beauty if it slapped you in the face with a giant fish
[Today at 4:51 PM] Mothrayas: although if you like your own tweets that's the online equivalent of sniffing your own farts and probably tells a lot about you as a person
MemoryTAS Today at 7:01 PM: But I exert big staff energy honestly lol
Samsara Today at 1:20 PM: wouldn't ACE in a real life TAS just stand for Actually Cease Existing
Joined: 4/17/2010
Posts: 11476
Location: Lake Chargoggagoggmanchauggagoggchaubunagungamaugg
I've read the trace log.
tl;dr:
00:03:40 <Masterjun> lol nice bug
Actual explanation:
The fortune teller is a single entrance building, meaning it appears on the secondary underworld map. This map is smaller and will get confused when we go south, which, in this case, attempts to load room 0132.
$a0 was #$0122, then was blindly incremented by #$10, which means we're in room #$0132.
As this room doesn't exist, it ends up reading outside the table for room data and proceeds to load random garbage values into the memory locations where room data is stored. One of the corrupted values read is $FF into memory location $AD (Hold the value for special room "effects).
Room value #$0132 is used to calculate an offset to read the room data pointer from $04f1e2. It is then stored to $0d. Some values are being loaded as offset (y register) is increasing, and finally we get to $04fcd3. It wasn't supposed to be read and stores #$ff, which goes to $ad.
This value is later used by the game to determine if there are any special effects, but since this value is way out of bounds it causes the CPU to jump to "open bus" and eventually end up executing a "BRK" instruction.
Load #$ff from $ad, shift left, move to x register. Take address $fe70, offset by x register, load the contents and jump to that address. End up in $0a20e0 where nothing is mapped. Since nothing is mapped there, we enter open bus, which means the CPU will execute whatever is left on the data bus.
bsnes core shows just 00 for any unmapped area, pretending 00 is being executed, while in fact it isn't. The log is lying.
<Masterjun> it executes 20 due to the high byte of the address it just jumped to (since it's a 16 bit jump, it didn't even look at the bank, thus it wasn't 0A)
<Masterjun> then open bus changes because the JSR just wrote a 20 then 21 (or something) to stack
<Masterjun> and then it just runs through until it hits hardware registers (starting 2100), which isn't open bus anymore
<Masterjun> https://floating.muncher.se/bot/regs.txt
<Masterjun> well, not all of it at least
<Masterjun> then the critical part is 0a2134, execting something which changes open bus to 00, which then results in a real BRK at 0a2137
This instruction in turn jumps to $00FFFF in ROM where there's the value for a "branch long" instruction that executes a jump. The location from this jump will be read from $000000-$000002 because of a wraparound from $00FFFF.
Machine code 00 (Break) means we're jumping to $00:FFFF using the BRK vector.
<Masterjun> ROM is segmented into blocks of 0x8000 bytes into the $8000-FFFF part of each bank
<Masterjun> in other words, $00:FFFF is actually 0x7FFF bytes into the ROM
"0x7FFF bytes into the ROM" we see #$82 so we fetch this as a machine code, which means BRL (Branch Long). When an opcode is being fetched along with its arguments, the bank isn't accounted for, so all that's being incremented is the 16-bit address. So when we're at $00:FFFF and we have fetched the first byte of a multi-byte opcode, the rest is being fetched from $00:0000 and onward.
As luck would have it, those addresses contains the controller inputs left there by the controller reading routine that executed just before this crash happened.
By the time we get to $00ffff, address $000000 is #$4218. Since BRL is relative, we end up at PC $000002 and #$4218 is added, so we arrive at address $00421a. Finally our PC is at controlled registers, so we can execute anything that we input.
From there on it's business as usual when it comes to ACE on the SNES. A jump to controller registers is done and execution is kept there in a loop by executing code entered by 4 controllers, waiting for the next frame and then looping back. This code ends up storing $1A to $10 and $00 to $11 to set the game mode to credits and then jumping back into the main game loop and letting the game resume from there.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.