Submission #6499: pirohiko's SNES Final Fantasy V "game end glitch" in 07:28.13

Console Super NES Emulator lsnes-rr2 beta23
Game Version JPN Frame Count 26932
ROM Filename Final Fantasy V (J).snes Frame Rate 60.0988138974405
Branch game end glitch Rerecord Count 25665
Unknown Authors pirohiko
Game Final Fantasy V
Submitted by pirohiko on 8/30/2019 4:57:33 PM

Submission Comments

Game objectives

  • Emulator used: lsnes rr2-beta23
  • Heavy glitch abuse
  • Uses sub-frame resets
  • Aims for fastest time
  • Uses game-breaking glitches
  • Corrups save data
  • Abuses programming errors
  • Manipulates luck
  • Arbitrary Code Execution

Old Route

Please see the previous submission for things that are not explained

New Route

knbnitkr suggested a new route plan to me.

No-encounter flag

Karnak Castle exit turned out to turn off no-encounter flag $0A53.

Black Chocobo

Crescent Town turns on Black Chocobo flag $0A93 and event tiles flag $0A1B in the forest. The event black chocobo will crash the game if checked.

Detailed route


  • Saved to data 1 at the position of $0AD8 = {X=0x9E, Y=0x86}.
    • In the initial state it is more difficult to reduce than adding an even number of checksums, so I first increased it with config ($0970-).
    • By setting to store the cursor position, cursor movement of the menu screen is shortened.
    • To compress the final checksum adjustment time, I did it 4 steps higher than the previous TAS.
  • Saved to data 3 and 2 at position of $0AD8 = {X=0x9E, Y=0x7B}.
  • Resetting while saving to data 1, at position of $0AD8 = {X=0xAD, Y=0x90}.
    • I adjusted the checksum by reducing the increased configuration value.
    • It is important to speed up the message of the battle, but if you speed up the battle speed faster you will only accelerate the enemy.
    • By subframe reset, the position of data 1 has become {X=0xAD, Y=0x86}.
  • Loaded from data 1.
    • It walked 8 steps to the right and 2 steps down.
  • Resetting while saving to data 2, at position {X=0xB5, Y=0x8A}.
    • The checksum was adjusted by only waiting for 8 frames when saving the data without using the config screen.
    • By subframe reset, the position of data 2 has become {X=0xB5, Y=0x7B}.
    • Unlike the previous TAS, the checksum is correct.
  • Loaded from data 2.
    • It walked upwards.
  • Saved to data 2 at position {X=0xB6, Y=0x69}.
    • Waited 5 frames for the next checksum adjustment.
    • Normal reset.
  • Loaded from data 3.
    • It walked two steps to the right.
  • Resetting while saving to data 2, at position {X=0xA0, Y=0x7B}.
    • Changed his position to the second back for arbitrary code execution.
    • By subframe reset, the position of data 2 has become {X=0xA0, Y=0x69}.
  • Loaded from data 2.
    • In this position of the ocean there is an event related to the ship, so I got it!
    • The double speed flag by the chocobo is kept even on the ship, so it is quadrupled.
  • Saved to data 2 and 4 at position {X=0x9F, Y=0x6D, ShipX=0xA0, ShipY=0x6D}
    • Turned upward for the next checksum adjustment.
  • Moved to west-northwest by ship.
    • Turned rightward for the next checksum adjustment.
  • Saved to data 3 and resetting while saving to data 2, the position of data 2 has become {X=0x8A, Y=0x62, ShipX=0x8A, ShipY=0x6D}.
    • Data 2 was apparently lost as the checksum was incorrect.
  • Loaded from data 4.
    • It does not move.
  • Resetting while saving to data 2, at position {X=0x9F, Y=0x6D}.
    • By subframe reset, the position of data 2 has become {X=0x9F, Y=0x6D, ShipX=0x8A, ShipY=0x6D}.
    • The checksum of data 2 was still inaccurate.
  • Loaded from data 3.
    • It does not move.
  • Resetting while saving to data 2, at position {X=0x8A, Y=0x62}.
    • The checksum was adjusted mainly by the setting of the custom pad of config.
    • By subframe reset, the position of data 2 has become {X=0x8A, Y=0x6D, ShipX=0x8A, ShipY=0x6D}, same as the ship.
    • This is the best position to go straight down or left without hitting the land.
  • Loaded from data 2.
    • The ship went to Crescent Town and sank as the event progressed.
    • Black Chocobo flag $0A93 and event tiles flag $0A1B were turned on as the event progressed.
  • Resetting while saving to data 1.
    • Overwritten from SRAM $0000 to $05EF (WRAM $0500-$AEF) for the next checksum adjustment.
    • Data 1 was apparently lost as the checksum was incorrect.
  • Loaded from data 2.
    • Went to Karnak Castle to turn off no-encounter flag $0A53.
  • Resetting while saving to data 1.
    • Overwiten from SRAM $0000 to $0591 (WRAM $0500-$A91).
    • The no-encount flag $0A53 and event tile flag $0A1B on data 1 are turned off.
    • As a result of previous adjustments, the final checksum was adjusted without waiting time.
  • Loaded from data 1.
    • Input for arbitrary code execution was made on the load screen.
    • Input for arbitrary code execution was made at the end of the battle.

Arbitrary code setup

A direct page is 256 bytes that SNES CPU frequently accesses, and it has a memory address set according to the scene of the game different. In this game, the jump address of the BRK opcode is set to $000000. The direct page is set to $0000 in the battle scene, and pad input is put in $0000-$0005. But after loading the save data the memory will be filled with 0. Therefore to execute arbitrary code it was necessary to fight before checking the helmet. However, because it is disturbed by the "no-encounter flag ($0A53:0x80)", you need to see the event getting off Chocobo.

Closed menu input

When walking, the direct page will be set to $0B00, And when you open the menu screen it will be set to $0100. If you input the pad in two frames at the moment the menu screen closes, it will be put into $0100-$0105 and it will not change until you open it again.
26135|........A.......|
26136|..sSudl.A.L.....|
address000102030405
$0100203EA03EA03E

Battle end input

If you escape when the second character is in order, $000A will be "FC 00 01". Then $0000 was adjusted at the moment the battle screen closed.
26640|....u...A.......|
address000102030405060708090A0B0C0D0E0F
$0000800880088008 FC0001

Checked Black Chocobo input

26929|B.sSu..rA.L.....|
26930|B.sSu.lrAXLR....|
address000102030405060708090A0B0C0D0E0F
$0100203EA03EA03EF0BBF0BB50028001F0BB
$0110A0B90000

Last 3 frames input

When Joypad-Registers was read by unjust timing, bit position slipped, so I did the input by which that was considered.
             1-1              1-2              2-1              2-2
26930|B.sSu..rA.L.....|................|................|................|
26931|B.sSu.lrAXLR....|.Y....l.AXL..1..|.Ys.u.lr.X.R.1..|.Ys..d.rAXL.0.23|
26932|B....d.rA.LR.1.3|BY..u.lr.X.R01..|BY.S.d.rA....1.3|BY......A.L...2.|
Actual Joypad binary
A9D6C985D7CB
B58585D55CCBA2C0

Executed codes

-- NMI occured --
00cee0 jml $001f00   <001f00> A:008d X:299c Y:11c8 S:1ff5 D:0b00 DB:00 nvmxdIzC V:225 H:  88
001f00 brk #$00               A:008d X:299c Y:11c8 S:1ff5 D:0b00 DB:00 nvmxdIzC V:225 H: 120
000000 bra $000a     <00000a> A:008d X:299c Y:11c8 S:1ff1 D:0b00 DB:00 nvmxdIzC V:225 H: 184
00000a jsr ($0100,x) <002a9c> A:008d X:299c Y:11c8 S:1ff1 D:0b00 DB:00 nvmxdIzC V:225 H: 206
000101 rol $3ea0,x   <00683c> A:008d X:299c Y:11c8 S:1fef D:0b00 DB:00 nvmxdIzC V:225 H: 264
000104 ldy #$f03e             A:008d X:299c Y:11c8 S:1fef D:0b00 DB:00 nvmxdIzc V:225 H: 332
000107 tyx                    A:008d X:299c Y:f03e S:1fef D:0b00 DB:00 NvmxdIzc V:225 H: 356
000108 beq $00c5     <0000c5> A:008d X:f03e Y:f03e S:1fef D:0b00 DB:00 NvmxdIzc V:225 H: 370
-- Start automatic polling --
00010a bvc $010e     <00010e> A:008d X:f03e Y:f03e S:1fef D:0b00 DB:00 NvmxdIzc V:225 H: 386
00010e beq $00cb     <0000cb> A:008d X:f03e Y:f03e S:1fef D:0b00 DB:00 NvmxdIzc V:225 H: 408
000110 ldy #$00b9             A:008d X:f03e Y:f03e S:1fef D:0b00 DB:00 NvmxdIzc V:225 H: 424
000113 brk #$f0               A:008d X:f03e Y:00b9 S:1fef D:0b00 DB:00 nvmxdIzc V:225 H: 448
000000 bra $000a     <00000a> A:008d X:f03e Y:00b9 S:1feb D:0b00 DB:00 nvmxdIzc V:225 H: 512
00000a jsr ($0100,x) <00f13e> A:008d X:f03e Y:00b9 S:1feb D:0b00 DB:00 nvmxdIzc V:225 H: 574
004218 sbc ($77,x)   <00ab89> A:008d X:f03e Y:00b9 S:1fe9 D:0b00 DB:00 nvmxdIzc V:225 H: 636
00421a lda #$c9d6             A:0cbc X:f03e Y:00b9 S:1fe9 D:0b00 DB:00 nvmxdIzc V:225 H: 686
00421d sta $d7       <000bd7> A:c9d6 X:f03e Y:00b9 S:1fe9 D:0b00 DB:00 NvmxdIzc V:225 H: 704
00421f wai                    A:c9d6 X:f03e Y:00b9 S:1fe9 D:0b00 DB:00 NvmxdIzc V:225 H: 732
-- End automatic polling <85b5 d585 cb5c c0a2> --
-- NMI occured --
00cee0 jml $001f00   <001f00> A:c9d6 X:f03e Y:00b9 S:1fe5 D:0b00 DB:00 NvmxdIzc V:225 H:  80
001f00 brk #$00               A:c9d6 X:f03e Y:00b9 S:1fe5 D:0b00 DB:00 NvmxdIzc V:225 H: 112
-- Start automatic polling --
000000 bra $000a     <00000a> A:c9d6 X:f03e Y:00b9 S:1fe1 D:0b00 DB:00 NvmxdIzc V:225 H: 176
00000a jsr ($0100,x) <00f13e> A:c9d6 X:f03e Y:00b9 S:1fe1 D:0b00 DB:00 NvmxdIzc V:225 H: 198
004218 lda $85,x     <00fbc3> A:c9d6 X:f03e Y:00b9 S:1fdf D:0b00 DB:00 NvmxdIzc V:225 H: 260
00421a sta $d5       <000bd5> A:396b X:f03e Y:00b9 S:1fdf D:0b00 DB:00 nvmxdIzc V:225 H: 294
00421c jml $c0a2cb   <c0a2cb> A:396b X:f03e Y:00b9 S:1fdf D:0b00 DB:00 nvmxdIzc V:225 H: 322

About the code

The event pointer $0BD6-$0BD8 was rewritten to 0xC9D639, and the event engine $C0A2CB was executed by JML(Jump to New Location Long).
The memory address to be corrected is less than the previous TAS.
Rewriting is much less than the previous TAS, because the event pointer is closer to "THE END".

Special Thanks

knbnitkr, Yu-ki(hs)

Masterjun: Judging.
Masterjun: Just like in the judgment message of the last submission, this run executes controller registers while they're being updated, which is not emulated correctly. I will accept this run, but a longer run that doesn't rely on updating controller data will be considered superior and can obsolete this run even if it's longer.
This run also skips the most part of the credits. However, it still reaches the correct end screen.
A lot of content that made the previous run entertaining, such as the tight movement around NPCs and some fast-paced battles don't appear anymore. But the entertainment votes in the discussion thread poll show there is entertainment to be found. If the ratings of the publications agree, this can stay in Moons.
Accepted to Moons as an improvement to the previous run.
fsvgm777: Processing.

Last Edited by fsvgm777 on 9/27/2019 6:08 PM
Page History Latest diff List Referrers