Game objectives
- Allow Left+Right / Up+Down
- Emulator used: FCEUX 2.2.2 (Old PPU)
- Major skip glitch
- Executes arbitrary code
- Corrupts memory
- Genre: RPG
- Uses a game restart sequence
- Aims for fastest time
- Heavily abuses programming errors
- Manipulates Luck
Usable memory address
- $00F5 = RNG index
- $00F6 = RNG index direction, if it is more than 80, it is leftward.
- $F900-$F9FF = RNG table
- $F900+($00F5) = RNG
- $00F7 = The encounter number of times
- $00F8 = The encounter threshold in UW
Save and Restart
Even if a game is reset, the encounter table is held.
1. You save a game
2. You move it one pixel
3. You reset a game
4. The encounter is skipped
When you overwrite a game, the confirmation message is very slow.
Because a game is saved before confirmation, it is fast that a game is reset than it closes a menu.
It is faster to touch a power supply, but 1/4 time is good at a good balance with the distance to walk.
To Paloom
The route going around the world to the west obtains a canoe and is faster than a route across the river by more than 50 seconds.
Chocobo Forest
Because the power supply was initialized, NPC RNG is not manipulated.
On the way, I adjusted it to be able to encounter the Land Turtle.
Takeover of the shuttle ship
When you push the start button just before you enter the paid sailing ship, the autopilot is concluded with a menu screen and becomes able to steer it by yourself.
But you can never get into a ship if you got it off in the island.
Deist Cavern
The monster of this place cannot escape.
I pushed forward RNG for encounter evasion twice using Potion.
Because the encounter number of times is 4, the land turtle appears.
45-floor bug
Outline
Please refer to the
post of TaoTao.
This game has room movement of "goto" and "return".
5 bytes are pushed to stack domain by "goto" movement, and it is popped for "return" movement.
"goto" movement is repeated between the rooms with complicated divergence of stairs.
"goto" movement is restricted by 45 times, but that's insufficient, so when a battle was accomplished, a stack overflow occurs.
Top of the stack and NMI
When Non-Maskable Interrupts (NMI) occurs by this game, $0100 are run.
$0100 are the top of the stack domain that is 256 bytes, and ReTurn from Interrupt (RTI) and JMP are written in dynamically here.
When the stack is pushed up to $0101-$0102, unjust JMP is carried out at the time of NMI,
the game almost freezes, and the save data often disappear, too.
Why were $6785 called?
When the second character attacked the Land Turtle, a stack domain was renewed to $0101 by a recursive Jump SubRoutine (JSR).
27364 frame A:FF X:04 Y:08 S:02 P:NvUbdIzc $9B4A:20 B6 9B JSR $9BB6 A:FF X:04 Y:08 S:00 P:NvUbdIzc $9BB6:A5 C4 LDA $00C4 = #$FF
NMI occurs in the middle of a calculation, and return address and P-Register are pushed to stack up as "$010F:27 A0 FC".
- P:nvUbdIZC = 0b00100111 = 0x27
A:00 X:10 Y:EE S:11 P:nvUbdIZC $FC9E:85 04 STA $0004 = #$00 A:00 X:10 Y:EE S:0E P:nvUbdIZC $0100:4C 4C 9B JMP $9B4C A:00 X:10 Y:EE S:0E P:nvUbdIZC $9B4C:6A ROR
NMI jumped to $9B4C, and a Stack-Pointer slipped off when the Program-Counter returned from many subroutines.
RTI using 3 bytes at the end of NMI is usually appropriate, but the Program-Counter goes to $A028 because RTS, which in this case only 2 bytes uses, was run.
27374 frame A:00 X:03 Y:00 S:0E P:nvUbdIZC $9B84:60 RTS- A:00 X:03 Y:00 S:10 P:nvUbdIZC $A028:04 NOP (illgal) A:00 X:03 Y:00 S:10 P:nvUbdIZC $A02A:66 A9 ROR $00A9 = #$76 A:00 X:03 Y:00 S:10 P:NvUbdIzc $A02C:15 85 ORA $85,X @ $0088 = #$04 A:04 X:03 Y:00 S:10 P:nvUbdIzc $A02E:67 RRA $20 (illgal) A:40 X:03 Y:00 S:10 P:nvUbdIzc $A030:2F RLA $A997 (illgal) A:40 X:03 Y:00 S:10 P:nvUbdIzc $A033:05 85 ORA $0085 = #$0E A:4E X:03 Y:00 S:10 P:nvUbdIzc $A035:66 A9 ROR $00A9 = #$BB A:4E X:03 Y:00 S:10 P:nvUbdIzC $A037:69 85 ADC #$85 A:D4 X:03 Y:00 S:10 P:NvUbdIzc $A039:67 RRA $20 (illgal) A:F2 X:03 Y:00 S:10 P:NvUbdIzc $A03B:2F RLA $A997 (illgal) A:40 X:03 Y:00 S:10 P:nvUbdIzc $A03E:06 85 ASL $0085 = #$0E A:40 X:03 Y:00 S:10 P:nvUbdIzc $A040:66 A9 ROR $00A9 = #$5D A:40 X:03 Y:00 S:10 P:nvUbdIzC $A042:20 85 67 JSR $6785
- $A041:"A9 20 85 67" is "LDA #$20" and "STA $0067"
- $A042:"20 85 67" becomes "JSR $6785", because 1 byte slips off than a right program.
27374 frame A:40 X:03 Y:00 S:0E P:nvUbdIzC $6785:4C 42 64 JMP $6442 A:40 X:03 Y:00 S:0E P:nvUbdIzC $6442:CE CF D0 DEC $D0CF = #$85 A:40 X:03 Y:00 S:0E P:NvUbdIzC $6445:4C 4D F3 JMP $F34D
It can arrive at the credits by "JMP $F34D",
but MMC1, which became unstable because of "RLA $A997", will fail in bank changing.
I initialize MMC1 with "DEC $D0CF" to evade it.
The details of the character
SRAM Addresses
Save Data 1
$6440 | 01 | 00 | CE | CF | D0 | 4C | 4D | F3 | 14 | 00 | 14 | 00 | 05 | 00 | 05 | 00 |
---|
Save Data 2
$6700 | 00 | 00 | FF | FF | FF | FF | FF | 95 | 1E | 00 | 1E | 00 | 05 | 00 | 05 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
$6740 | 01 | 00 | CE | CF | D0 | 4C | 4D | F3 | 14 | 00 | 14 | 00 | 05 | 00 | 05 | 00 |
$6780 | 02 | 00 | D0 | DA | D1 | 4C | 42 | 64 | 28 | 00 | 28 | 00 | 05 | 00 | 05 | 00 |
$67C0 | 08 | 00 | A2 | B6 | A2 | B6 | FF | FF | 1E | 00 | 1E | 00 | 05 | 00 | 05 | 00 |
Meaning of the character name
1st | し | Five space that were skipped | "Shi" is death | |||||
2nd | オ | カ | キ | び | ぶ | レ | "O KA KI" is DEC $D0CF | "Bi Bu Re" is JMP $F34D |
---|---|---|---|---|---|---|---|---|
3rd | キ | チ | ク | び | じ | ぱ | "Ki Chi Ku" is without meaning | "Bi Ji Pa" is JMP $6442 |
4th | の | ん | の | ん | "No N No N" is without meaning |
Nameable Text Table
あ | い | う | え | お | か | き | く | け | こ | |
8A | 8B | 8C | 8D | 8E | 8F | 90 | 91 | 92 | 93 | |
さ | し | す | せ | そ | た | ち | つ | て | と | |
---|---|---|---|---|---|---|---|---|---|---|
94 | 95 | 96 | 97 | 98 | 99 | 9A | 9B | 9C | 9D | |
な | に | ぬ | ね | の | は | ひ | ふ | へ | ほ | |
9E | 9F | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | |
ま | み | む | め | も | ら | り | る | れ | ろ | |
A8 | A9 | AA | AB | AC | B0 | B1 | B2 | B3 | B4 | |
や | ゆ | よ | わ | ん | が | ぎ | ぐ | げ | ご | |
AD | AE | AF | B5 | B6 | 3C | 3D | 3E | 3F | 40 | |
ざ | じ | ず | ぜ | ぞ | だ | ぢ | づ | で | ど | |
41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 4A | |
ぱ | ぴ | ぷ | ぺ | ぽ | ば | び | ぶ | べ | ぼ | |
64 | 65 | 66 | 67 | 68 | 4B | 4C | 4D | 4E | 4F | |
ゃ | ゅ | ょ | っ | 0 | 1 | 2 | 3 | 4 | ||
7D | 7E | 7F | 7C | FF | 80 | 81 | 82 | 83 | 84 | |
ア | イ | ウ | エ | オ | カ | キ | ク | ケ | コ | |
CA | CB | CC | CD | CE | CF | D0 | D1 | D2 | D3 | |
サ | シ | ス | セ | ソ | タ | チ | ツ | テ | ト | |
D4 | D5 | D6 | D7 | D8 | D9 | DA | DB | DC | DD | |
ナ | ニ | ヌ | ネ | ノ | ハ | ヒ | フ | ヘ | ホ | |
DE | DF | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7 | |
マ | ミ | ム | メ | モ | ラ | リ | ル | レ | ロ | |
E8 | E9 | EA | EB | EC | F0 | F1 | F2 | F3 | F4 | |
ヤ | ユ | ヨ | ワ | ン | ガ | ギ | グ | ゲ | ゴ | |
ED | EE | EF | F5 | F6 | 50 | 51 | 52 | 53 | 54 | |
ザ | ジ | ズ | ゼ | ゾ | ダ | ヂ | ヅ | デ | ド | |
55 | 56 | 57 | 58 | 59 | 5A | 5B | 5C | 5D | 5E | |
パ | ピ | プ | ペ | ポ | バ | ビ | ブ | ベ | ボ | |
69 | 6A | 6B | 6C | 6D | 5F | 60 | 61 | 62 | 63 | |
ャ | ュ | ョ | ッ | - | 5 | 6 | 7 | 8 | 9 | |
BD | BE | BF | BC | C2 | 85 | 86 | 87 | 88 | 89 |
Special Thanks
- cheap: Cheap showed that Deist Cavern was the shortest route.
- FinalFighter: FinalFighter made the LuaScript which told that a PC passed a specific address.
- naruko: Naruko taught me code where MMC1 did not freeze. And he also offered various documents.
- TaoTao: TaoTao made a movie of the 45-floor bug. I was able to discover the jump to SRAM of $6785 by investigating the movie with LuaScript of FinalFighter.
ars4326: (Made some minor grammatical corrections for better readability).
ars4326: Judging underway!
ars4326: Hello, pirohiko. This run was an outstanding technical display of arbitrary code execution (ACE), which, despite a considerable trek through the overworld, provided an entertaining payoff. The included overlay in the encode made the process easier to understand and added to the viewing experience. Thread feedback, also, was mostly enthusiastic and appreciative of the amount of effort put in. Great work on another well-made TAS!
Accepting for publication to Moons!
Guga: Processing...