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
Subframe reset
If resetting is done while WRAM is being transferred to SRAM, a mixed SRAM is created.
When reset between the X / Y address, it warps horizontally from the SRAM position, but it needs to pass a checksum.
It is also possible to mix the state of various event flags.
Checksum
The checksum of FF6 adds the game data to the 16-bit register every 8 bits, but this game adds it to the 16-bit register every 16 bits.
In this game, it is relatively easy to adjust checksum separately for even and odd bytes in config.
Even number bytes have frame advance time, so even number bytes move more intensely.
Helmet of memory destruction.
This movie abuses subframe reset.
Some untouched objects will destroy memory when checked.
Memory after $1417 will be destroyed if some untouched objects are checked.
This game's V-blank interrupt has a jump address set to $1F00, which is dynamically rewritten when changing game scenes.
If this address is destroyed, the program of this game jumps to $000000 by the BRK opcode.
Detailed route
- Saved to data 1 at the position of $0AD8 = {X=0x9C, Y=0x8A}.
- 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.
- Saved to data 3 and 2 at position of $0AD8 = {X=0x9E, Y=0x7B}.
- It walked downwards and rightwards.
- 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=0x8A}.
- Loaded from data 1.
- It walked eight steps to the right.
- Resetting while saving to data 2, at position {X=0xB5, Y=0x8A}.
- Because walking is short, I can adjust the checksum by waiting for some frames, but I changed the character position rather than wait long.
- By subframe reset, the position of data 2 has become {X=0xB5, Y=0x7B}.
- Data 2 was apparently lost as the checksum was exceeded.
- Loaded from data 3.
- It does not move.
- Resetting while saving to data 2, at position {X=0x9E, Y=0x7B}.
- By losing data 2, the overwrite question was omitted.
- The unjoined Lenna whose position was changed in Data 2 was overwritten by the Bartz joined flag.
- By overwriting the SRAM $0700-$0708, the checksum is corrected.
- Loaded from data 2.
- I waited one frame on the loading screen to manipulate luck.
- This waiting time is absorbed by later waiting time.
- It walked upwards.
- Saved to data 4 at position {X=0xB6, Y=0x69}.
- Normal reset.
- Loaded from data 3.
- It walked two steps to the right.
- Resetting while saving to data 4, at position {X=0xA0, Y=0x7B}.
- The checksum was adjusted by only waiting for 2 frames when saving the data without using the config screen.
- By subframe reset, the position of data 4 has become {X=0xA0, Y=0x69}.
- Loaded from data 4.
- 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.
- The memory address of the position where the ship landed is $0AEF = {X=0xA6, Y=0x4B}.
- Saved to data 1 and 3, and resetting while saving to data 4, at position {X=0xA6, Y=0x4B}.
- I overlapped the ship and saved it.
- By subframe reset, the position of data 4 has become {X=0xA6, Y=0x69}.
- This position is adjacent to the middle entrance of the pirates cave.
- Data 4 was apparently lost as the checksum was incorrect.
- Loaded from data 3.
- Landed in front of the Wind Shrine.
- Resetting while saving to data 3, at the ship landed position {X=0xB5, Y=0x3D}.
- By subframe reset, the ship landed position of data 3 has become {X=0xB5, Y=0x4B}.
- Data 3 was apparently lost as the checksum was incorrect.
- Loaded from data 1.
- It does not move.
- Resetting while saving to data 3, at position {X=0xA6, Y=0x4B}.
- By subframe reset, the position of data 3 has become {X=0xA6, Y=0x4B}.
- The checksum of data 3 was still inaccurate.
- Loaded from data 2.
- It does not move.
- Resetting while saving to data 3, at position {X=0xB5, Y=0x7B}.
- The checksum was adjusted mainly by the setting of the custom pad of config.
- By subframe reset, the position of data 3 has become {X=0xB5, Y=0x4B}, same as the ship.
- Loaded from data 3.
- I visited Carwen to pick up the Ice Rod.
- Disturbance by the residents was avoided with the previous luck manipulation.
- North Mountain
- When they get off the ship, their appearance is changed, but the no-encounter flag by Chocobo is kept.
- Magissa
- Luck manipulation can be done easily by input before battle.
- Because the attack magic can not be avoided, the duplicated man was sacrificed.
- By pressing LR a few lag frames have been reduced.
- Ice Rod is strong.
- Then they returned straight to the save point.
- Saved to data 3, and resetting while saving to data 4.
- Data 4 was overwritten until no-encounter flag $0A53.
- They include the Magissa flag $0A18, and helmet flag $0A67 is not included.
- The checksum was adjusted using several configuration settings and window colors.
- Loaded from data 4.
- I waited 17 frames on the loading screen to manipulate luck.
- To avoid encounters with enemies, 14 steps were added.
- The double speed flag was erased by the event of a slow moving ship.
- The no-encounter flag was erased by the event getting off Chocobo.
- Resetting while saving to data 3.
- Data 3 was overwritten until $0A67.
- Because the rear row can escape faster, I changed it.
- The checksum was adjusted using several configuration settings.
- Loaded from data 3.
- Let's set arbitrary code.
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.
37858|........A.......| 37859|..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.
38444|....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 helmet input
38595|B.sSu..rA.L.....| 38596|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 7 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 38595|B.sSu..rA.L.....|................|................|................| 38596|B.sSu.lrAXLR....|.YsS..lr.XLR.12.|.YsS.dlrAX.R.1..|.Ys..d.rA.L.0.23| 38597|B..S............|................|B...............|B...............| 38598|..s.udlr....012.|...S.d.r........|B..Sud.......1.3|BY..u.lrAX..0.23| 38599|.Y..u...A..R01..|....ud.r..LR0.2.|B..Sud.....R01.3|BY..u.lrAX..0.23| 38600|BY.Su..rA...012.|BY...d.r...R0.2.|BY.Sud.....R01.3|BY..u.lrAX..0.23| 38601|.....dl.A....1.3|....u.lr.X.R01..|....u...AX...12.|........A.L...2.|
Actual Joypad binary
A9 | EF | EC | 06 | 57 | CB | ||
0E | 9F | 05 | 8C | 00 | 05 | CB | CB |
9C | 28 | 1D | 9C | 3A | 1D | CB | CB |
8E | 48 | 1D | 9C | 1A | 05 | CB | CB |
85 | D6 | C6 | D8 | 5C | CB | A2 | C0 |
Executed codes
00CEE0 5C 00 1F 00 JML $001F00 A:04fc X:1f52 Y:130e S:1ff5 D:0b00 DB:00 nvmxdIzC V:240 H: 98 001F00 00 BRK 000000 80 08 BRA $000A 00000A FC 00 01 JSR (0100,x) -- $2052 return 0101 000101 3E A0 3E ROL 000104 A0 3E F0 LDY #$F03E -- Y = F03E 000107 BB TYX -- X = Y 000108 F0 BB BEQ 00010A 50 02 BVC $010E 00010E F0 BB BEQ 000110 A0 B9 LDY #$00B9 -- Y = 00B9 000113 00 BRK
000000 80 08 BRA $000A 00000A FC 00 01 JSR (0100,x) -- $F13E return 4218 yey!
004218 C1 FE CMP 00421A A9 EF EC LDA #$ECEF -- A = ECEF 00421C 06 57 INC $0B57 -- Event talk flag on 00421F CB WAI
00CEE0 -> 001F00 -> 000000 -> 00000A -> 004218
004218 0E 9F 05 ASL $059F -- GALUF ID 42 -> KLIRE ID 84 00421B 8C 00 05 STY $0500 -- BUTZ ID 00 -> LENNA ID B9 00421E CB WAI
004218 9C 28 1D STZ $1D28 -- APU data fix $1D28 = 0000 00421B 9C 38 1D STZ $1D3A -- APU data fix $1D3A = 0000 00421E CB WAI 004218 8E 48 1D STX $1D49 -- APU data fix $1D49 = F03E 00421B 9C 1A 05 STZ $051A -- LENNA Status = 0000 00421E CB WAI 004218 85 D6 STA $0BD6 00421A C6 D8 DEC $0BD8 -- Event Pointer = C8ECEF 00421C 5C CB A2 C0 JML $C0A2C0 -- Event Script engine
likelihood
Dead zombie and chemist glitch could also do Arbitrary Code Execution likewise, but I thought the second world was far.
Special Thanks
Yu-ki(hs), Sumurai Goroh, Yona2san
Masterjun: This looks interesting. Judging.
Masterjun: An important part to note for this run is the fact that it executes controller registers while they are being updated. This is known to not be emulated in a correct way on emulator. This gives this run a high chance of not working on console at all. However, leading the game code to the controller registers is done perfectly fine, so while these exact input sequences probably won't work on console, it's likely there are indeed some inputs which work. The run wouldn't look very different, so we can safely say that this isn't a problem.
Important to note is if there was a submission that is a bit longer, but with a more accurate way of beating the game in terms of emulator accuracy, then it can count as superior and obsolete this movie.
No other problems with this run and the viewer feedback has been quite good as well.
Accepting to Moons.
fsvgm777: Processing.