従来より32階層でのメニューオープンでゲームがフリーズすることが知られていました。
32回の昇降後に単にメニューを開くだけだと"40:RTI"を踏んでしまうため、$0312に到達することが出来ません。
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0300: 10 05 7A 10 06 00 07 0C 05 06 40 40 04 04 30 40
0303:10 06 BPL $030B
030B:40 RTI
しかし予めどこかでメニューを開いていると$0300-$030Fの上書き処理が完了され、$0312に到達できるようになります。
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0300: 10 05 7A 10 06 00 01 13 02 00 80 7A 80 7A 80 00
0303:10 06 BPL $030B
030B:7A NOP
030C:80 7A NOP #$7A
030E:80 00 NOP #$00
0310:01 00 ORA ($00,X) @ $0000 = #$00
エンディングシーケンスに移行するにはbank:0Dに切り替える必要がありますが、幸いなことにそれはbank:0Fのカオス戦後のループ処理の中に存在します。
0F:C93A:20 2B E9 JSR $E92B
0F:C93D:A9 0D LDA #$0D
0F:C93F:20 03 FE JSR $FE03
0F:C942:20 03 B8 JSR $B803
0F:C945:4C 3A C9 JMP $C93A
このループのどこかに飛ぶことが出来ればカオスを呼び出すことなくゲームを終えることが可能ですが、0xC9や0x44以下の文字は登録できない上に7byteしか自由に使えないので非常に困難です。
そこで、スタックに既に積まれている0xC9を再利用し、0x38-0x44の値を"48:PHA"でプッシュすれば"60:RTS"でエンディングシーケンスへリターンすることが可能になります。
条件を満たすためには A = X = 0x38 or 0x3F に3byte、"9A:TXS(SP=X)"に1byte、"48:PHA"に1byte、0x5C-0x6Fが使用不能文字なので"60:RTS"を含んでいるアドレスにジャンプするために"4C:JMP $****"で3byte、合計8byteが必要になります。
残念なことに1byte足りないので無理やり捻出する事を考えます。
"48:PHA"からはじまり"60:RTS"で終わるサブルーチンがあれば1byteを削減できるので、探した結果ふたつの名前が候補に上がりました。
4人目の名前は「ちごあゆ」か「ちごにむ」のどちらかが使え、入力が楽なのは前者ですがムービーの最後に入力が余計に必要になるのでTASには向きません。
2人目の名前には "AF:LAX $****" という illegal opcode を使います、これにより37*2種類の候補の名前からカーソル移動の一番少ないものを選択できます。
「よるえき」という文字がカーソル移動10回で済むので、多分これが一番早いと思います。
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0300: 10 05 7A 10 06 00 01 13 02 00 80 7A 80 7A 80 00
0310: 01 00 AF B2 8D 90 15 0C 13 06 B0 40 12 04 A0 40
0320: 02 00 4C 51 50 55 07 18 05 12 40 A0 04 10 30 A0
0330: 03 00 9A 4C 9F AA 15 18 13 12 B0 A0 12 10 A0 A0
$0310:01 00 ORA ($00,X) @ $0000 = #$00 A:05 X:05 Y:0E S:11 P:nvubdIzc
$0312:AF B2 8D LAX $8DB2 = #$38 A:05 X:05 Y:0E S:11 P:nvubdIzc -- A = X = #$38
$0315:90 15 BCC $032C A:38 X:38 Y:0E S:11 P:nvubdIzc
$032C:04 A0 NOP $A0 A:38 X:38 Y:0E S:11 P:nvubdIzc
$032E:30 A0 BMI $02D0 A:38 X:38 Y:0E S:11 P:nvubdIzc
$0330:03 ASO ($00,X) @ $010B = #$00 A:38 X:38 Y:0E S:11 P:nvubdIzc -- * Be careful *
$0332:9A TXS A:38 X:38 Y:0E S:11 P:nvubdIzc -- SP = X
$0333:4C 9F AA JMP $AA9F A:38 X:38 Y:0E S:38 P:nvubdIzc
$AA9F:48 PHA A:38 X:38 Y:0E S:38 P:nvubdIzc
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$FE2D:60 RTS A:00 X:EF Y:00 S:37 P:nvubdIZC
$C939:0E 20 2B ASL $2B20 = #$08 A:00 X:EF Y:00 S:39 P:nvubdIZC -- Wrong address
$C93C:E9 A9 SBC #$A9 A:00 X:EF Y:00 S:39 P:nvubdIZc
$C93E:0D 20 03 ORA $0320 = #$02 A:56 X:EF Y:00 S:39 P:nvubdIzc
$C941:FE 20 03 INC $0320,X @ $040F = #$00 A:56 X:EF Y:00 S:39 P:nvubdIzc
$C944:B8 CLV A:56 X:EF Y:00 S:39 P:nvubdIzc
$C945:4C 3A C9 JMP $C93A A:56 X:EF Y:00 S:39 P:nvubdIzc
$C93A:20 2B E9 JSR $E92B A:56 X:EF Y:00 S:39 P:nvubdIzc -- Correct address
$C93D:A9 0D LDA #$0D A:FF X:00 Y:00 S:39 P:nvubdIZC
$C93F:20 03 FE JSR $FE03 A:0D X:00 Y:00 S:39 P:nvubdIzC -- Bank Change
$C942:20 03 B8 JSR $B803 A:00 X:00 Y:00 S:39 P:nvubdIZC -- Ending Sequence
ここで注意が必要なのは、4人目の職業が赤魔道士[03]の場合Aの値が$010Bの値とAの論理和になるが、$010Bはエミュレータの初期化パターンによって#$00になっている。
$010Bの初期値はコンソールによって個体差があるので白魔道士[04]でなければ成功しない事がある。
Stack 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0100: FF 00 00 00 FF FF FF FF 00 00 00 00 FF FF 68 E1
0110: 02 03 0E BA 62 B8 EB AD 45 CA F6 C8 92 C9 01 18
0120: 00 0B 05 92 C9 01 08 00 0B 05 92 C9 01 18 00 0B
0130: 05 92 C9 01 08 00 0B 05 92 C9 01 18 00 0B 05 92
Character List
8A 8B 8C 8D 8E 48 49 4A 4B 4C
あ い う え お が ぎ ぐ げ ご
8F 90 91 92 93 4D 4E 4F 50 51
か き く け こ ざ じ ず ぜ ぞ
94 95 96 97 98 52 53 54 55 56
さ し す せ そ だ ぢ づ で ど
99 9A 9B 9C 9D 57 58 59 5A 5B
た ち つ て と ば び ぶ べ ぼ
9E 9F A0 A1 A2 70 71 72 73 74
な に ぬ ね の ぱ ぴ ぷ ぺ ぽ
A3 A4 A5 A6 A7 7C 7D 7E 7F B9
は ひ ふ へ ほ ゃ ゅ ょ っ 。
A8 A9 AA AB AC 80 81 82 83 84
ま み む め も 0 1 2 3 4
AD AE AF B0 B1 85 86 87 88 89
ら り る れ ろ 5 6 7 8 9
B2 B3 B4 B5 B6 C2 C4 C5 C3 FF
や ゆ よ わ ん - ! ? ‥