Casual Angle of Attack: Is the introduction part of the game? I think many speedrunners and most casual players think the game starts at the beginning of the intro. Why then would the run not terminate at the end at the ending of the outro? Time stopping at Ganon was because that was a direct and convenient representation of your final time (and partially it was a remenant of SDA timing, where what matters is first and last non-cutscene input that takes you to the end of the credits).
Technical Angle of Attack: Remember how we use glitching because we don't care about what people "think" is playing the game? We will skip to the ending because we don't care about what people "think" ends the game. I don't understand how people can argue that Ganon is the ending over a screen that EXPLICITLY SAYS "THE END". How is this up to interpretation? THE END is the end. It maybe anticlimactic, and it may not "feel right", but we don't care about what "feels right" (like seriously, does RBA "feel right" to anyone?)
WARNING: TECHNICAL STUFF AHEAD
I copied this post from TASVideos. It was from a thread on Super Mario World, which was completed in a similar way (jump to The End screen using glitchs).
No you can not move Mario. The game no longer is in a level, it it has changed its mode of processing entirely. In this glitch the game mode is changed to #$26 (as I explained like three times now). But let me bring the actual code into this now:
First lets talk about how SMW actually processes its game loop. There is a small infinite loop that basically checks if NMI has run, and once it has it will run a routine called "RunGameMode". So lets take a look at the game loop:
GameLoop:
LDA $10 ;$00806B |\ Main wait loop
BEQ GameLoop ;$00806D | | $10 is set in NMI to $00
CLI ;$00806F | | Enable interrupts
INC $13 ;$008070 | | Increment frame counter
JSR RunGameMode ;$008072 | | Run the game
STZ $10 ;$008075 | | Clear $10
BRA GameLoop ;$008077 |/ Back to the wait loop
As you can see, the game simply runs in an infinite loop. So the real important thing to us is what happens in the different game modes. So lets take a look at the routine next.
RunGameMode:
LDA.w $0100 ;$009322 | Load the current game mode
JSL ExecutePtr ;$009325 | Call the execute pointer routine
Simple enough, So what does this mean? It means there are a series of pointers that control game execution.
So here are the important game mode pointers to us, I have snipped non-important ones.
*snip*
dw InLevelGameMode ; 14 - In level
*snip*
dw CODE_009F6F ; 26 - Fade to the end
dw CODE_00963D ; 27 - load the end
dw CODE_009F7C ; 28 - Fade in to the end
dw Return00968D ; 29 - END (last game mode in SMW)
In game mode 14 is when you are controlling Mario and the level is executing as normal. The code for game mode 14 is huge, I won't torture you with that unless you want to see the code for it.
Game mode 26 is the code there the game will fade out to enter F-Blank (brightness of 00 with the negative bit set) in preparation for game mode #$27 to upload graphics.
CODE_009F4C:
LDA.w $0DAE ;$009F4C |\ Calculate the current brightness step
CLC ;$009F4F | |
ADC.w DATA_009F2F,Y ;$009F50 | |
STA.w $0DAE ;$009F53 |/ Store the current brightness ($2100 mirror)
CMP.w DATA_009F33,Y ;$009F56 |\ If the brightness has not reached the desired brightness
BNE CODE_009F66 ;$009F59 |/
INC.w $0100 ;$009F5B | Increment the game mode (putting you at game mode #$27)
LDA.w $0DAF ;$009F5E |\ Flip the Mosaic/Fade direction
EOR.b #$01 ;$009F61 | |
STA.w $0DAF ;$009F63 |/
CODE_009F66:
LDA.b #$03 ;$009F66 |\ Copy the mosaic mirror to the mosaic register
ORA.w $0DB0 ;$009F68 | |
STA.w $2106 ;$009F6B |/
Return009F6E:
RTS ;$009F6E | Done with game mode 26
CODE_009F6F:
DEC.w $0DB1 ;$009F6F |\ Keep the current game mode active
BPL Return009F6E ;$009F72 | |
JSR KeepModeActive ;$009F74 |/
CODE_009F77:
LDY.w $0DAF ;$009F77 |\ Load the current Mosaic/Fade direction
BRA CODE_009F4C ;$009F7A |/ Branch to an earlier portion of code
Game mode #$27 is where the actual graphics are uploaded. This game mode simply prepares the screen in F-Blank.
CODE_00963D:
JSR CODE_0085FA ;$00963D | Turns off IO and does some DMA
JSR Clear_1A_13D3 ;$009640 | Clean RAM $131A to $13D3
JSR SetUpScreen ;$009643 | Do some screen setup
JSR CODE_00955E ;$009646 | Upload the layer graphics to VRAM
LDA.b #$19 ;$009649 |\ Set some screen properties(such as palette settings)
STA.w $192B ;$00964B | |
LDA.b #$03 ;$00964E | |
STA.w $192F ;$009650 | |
LDA.b #$03 ;$009653 | |
STA.w $1930 ;$009655 |/
JSR UploadSpriteGFX ;$009658 |\ Upload the palette and graphics
JSR LoadPalette ;$00965B |/
LDX.b #$0B ;$00965E | Load the loop index
CODE_009660:
LDA.w TheEndPalettes,X ;$009660 |\ Do some palette corrections
STA.w $08A7,X ;$009663 | |
LDA.w DATA_00B71A,X ;$009666 | |
STA.w $08C7,X ;$009669 | |
LDA.w DATA_00B726,X ;$00966C | |
STA.w $08E7,X ;$00966F | |
DEX ;$009672 | |
BPL CODE_009660 ;$009673 |/
JSR CODE_00922F ;$009675 | DMA the palettes to CGRAM (they were in mirrors before)
LDA.b #$D5 ;$009678 |\ Set and load a layer three image (THE END text)
STA $12 ;$00967A | |
JSR LoadScrnImage ;$00967C |/
JSL CODE_0CAADF ;$00967F | Copy some sprites to OAM (the characters)
JSR CODE_008494 ;$009683 | Run the OAM size table routine
LDX.b #$14 ;$009686 |\ Useless loads, probably old leftover code
LDY.b #$00 ;$009688 |/
JMP CODE_009622 ;$00968A | Jump ahead
CODE_009622:
JSR KeepModeActive ;$009622 | Keep the game mode active(unused since there is no $0DB1 check)
LDA.b #$09 ;$009625 |\ Set the background mode
STA $3E ;$009627 |/
JMP CODE_0093EA ;$009629 | Jump ahead
CODE_0093EA:
LDA.b #$01 ;$0093EA |\ Set to the cutscene mode
STA.w $0D9B ;$0093EC |/
LDA.b #$20 ;$0093EF |\ Update some screen settings
JSR ScreenSettings ;$0093F1 |/
INC.w $0100 ;$0093F4 | Increment the game mode
LDA.b #$81 ;$0093F7 |\ Renable NMI
STA.w $4200 ;$0093F9 |/
RTS ;$0093FC | Done with game mdoe #$27
Game mode #$28 is a small game mode that shares most of the code with #$26. This game mode is responsible for doing the fade-in effect.
CODE_009F7C:
DEC.w $0DB1 ;$009F7C |\ Check if the game mode should be kept active
BPL Return009F6E ;$009F7F |/
LDA.b #$08 ;$009F81 |\ Set the number of frames to delay the fade-in steps
JSR CODE_009F2B ;$009F83 |/
BRA CODE_009F77 ;$009F86 | Run the fade code from game mode #$26 (opposite direction)
And lastly, game mode #$29. The simplest one of them all.
Return00968D:
RTS
Thats it. The game just simply returns. It has nothing more to do. For all intents and purposes, the game is done with execution.
Hopefully this helps clarify what a "winning" state in SMW is.
And hopefully this helps clarify that winning is hard coded into games (or at least, games that require a manual reset after The End like Ocarina of Time). You don't need to completely understand the code (I know I don't), just pay attention to the annotations especially about the game modes and how game mode 29 is a state that sets the game to be finished. Whatever the game mode 29 equivalent is for Ocarina of Time, we've reached it. Someone brought up in a different chat about the infinite credits loop, which we can put ourselves in. That isn't beating the game precisely because the game won't play out until The End and obtain the "game completed" game state.
If you wrong warp to the Fire Temple it would be ridiculous to say "I am not in the Fire Temple", as the game code proves otherwise. Likewise, if you wrong warp to the credits and reach The End, it would be ridiculous to say "I have not reached the end".