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.....|
address | 00 | 01 | 02 | 03 | 04 | 05 |
---|---|---|---|---|---|---|
$0100 | 20 | 3E | A0 | 3E | A0 | 3E |
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.......|
address | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0A | 0B | 0C | 0D | 0E | 0F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
$0000 | 80 | 08 | 80 | 08 | 80 | 08 | FC | 00 | 01 |
Checked Black Chocobo input
26929|B.sSu..rA.L.....| 26930|B.sSu.lrAXLR....|
address | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0A | 0B | 0C | 0D | 0E | 0F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
$0100 | 20 | 3E | A0 | 3E | A0 | 3E | F0 | BB | F0 | BB | 50 | 02 | 80 | 01 | F0 | BB |
$0110 | A0 | B9 | 00 | 00 |
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
A9 | D6 | C9 | 85 | D7 | CB | ||
B5 | 85 | 85 | D5 | 5C | CB | A2 | C0 |
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".
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.