ゼルダの伝説 夢をみる島(JP v1.0) in 01:19.946 [TAS][Arbitrary Code Execution] by hogehoge61,pirohiko

前後に特別な記載が無い限り、解説の内容はDX版と通常版で共通。 スクリーンショットは調査の都合で混在(ただし、片方のみに触れるのが適切な場合はそちらを使う)。

動画

ムービーファイル: LA_JP_ACE_TAS_4775f.bk2

解説

大まかなルートの概要

今回のTASにおいての大まかなルートは以下の通り。

  1. 実行するコードに当たるリンクの名前を付けてゲームを始める
  2. 敵を倒すために剣を取得する
  3. 敵を三体倒した状態で犬小屋バグを起こす
  4. 特定マップ位置の宝箱を開く

フレームルールとその最適化について

このゲームはRAMアドレス#FFE7hに汎用のタイミングカウンタを持っている。 これはスプライトなどで使われる各種カウンタ処理のタイミングを制御するための大本に当たる物で、 メインループ中で必ず1回インクリメントが行われる。なお、オーバーフローする状態でもそのままインクリメントは行われ続ける(FFh→00h→01h...)。

スプライトなどの各種カウンタ処理はこの汎用カウンタをAND命令などで手元の値と比較し、 「nフレームに一度なにかを実行する」という処理などを行っている。

なお、これはあくまでメインループ中で行われる処理なので、 全体の処理が1フレーム内に収まらなかった場合(ラグが起きている場合)はそれに準じて遅れる。 つまり、表示フレームとイコールではない。

; 汎用カウンターのインクリメント処理
0216:21 E7 FF  LD HL,#FFE7h    SP:dfff A:e7 B:00 C:ff D:68 E:67 F:00 H:c1 L:bf  Cy:176975040
0219:34        INC (HL)        SP:dfff A:e7 B:00 C:ff D:68 E:67 F:00 H:ff L:e7  Cy:176975052
			

スプライトのイベント用カウンタ(#C49*h)の内容は 基本的に(全ての調査はしていないが、恐らく殆どの物が?) 設定された値から4フレームに一度デクリメントされる。 これらのタイミングは前述の汎用カウンタを元にして行われている。

汎用カウンタは他の状態に関わらずメインループ中でインクリメントされ続けるので、 スプライトのイベントカウンタが待ち時間として使われる場合は処理が始まるタイミング次第で最大3フレーム差が出る事になる。 今回のTASにおいては剣の取得時、待ち時間用のイベントカウンタがセットされた直後のフレームでデクリメントが発生するよう剣を取るタイミングを僅かにずらして最適化している。

以下は#03hとANDして結果がゼロの時だけ(=4フレーム間に一度だけ)実行する結果サンプル(JS使用)。

汎用カウンタ0000000000
比較値0300000011
結果RUN(0)
; 剣を取った直後の該当処理より一部抜粋


; 汎用カウンタ値(今回#F8h)をAレジスタにロードする
77E3:F0 E7     LDH A,(#FFE7h)  SP:dff7 A:00 B:00 C:02 D:1c E:0e F:a0 H:c4 L:82  Cy:177065120
; 汎用カウンタ内容‭#F8h(11111000)‬と #03h(00000011) で AND。
; 今回は結果ゼロ。
77E5:E6 03     AND #03h        SP:dff7 A:f8 B:00 C:02 D:1c E:0e F:a0 H:c4 L:82  Cy:177065132

; ノーゼロであれば(=4フレームに一度の機会でなければ)77EFへジャンプ。
; 0000(#00h,該当) → 0001(#01h,非該当) → 0010(#02h,非該当) → 0011(#03h,非該当) → 0100(#04h,該当) 以降繰り返し...

; 今回は両方共ゼロ、つまり4フレームに一度来る非成立。カウンターのデクリメント処理へ
77E7:20 06     JR NZ,77EFh     SP:dff7 A:00 B:00 C:02 D:1c E:0e F:a0 H:c4 L:82  Cy:177065140
; イベントカウンタのデクリメント用のサブルーチンを開始
77E9:CD 87 08  CALL #0887h     SP:dff7 A:00 B:00 C:02 D:1c E:0e F:a0 H:c4 L:82  Cy:177065148
; イベントカウンタのベースアドレスと処理中番号と合算
0887:21 50 C4  LD HL,#C450h    SP:dff5 A:00 B:00 C:02 D:1c E:0e F:a0 H:c4 L:82  Cy:177065172
088A:18 08     JR 0894h        SP:dff5 A:00 B:00 C:02 D:1c E:0e F:a0 H:c4 L:50  Cy:177065184
0894:09        ADD HL,BC       SP:dff5 A:00 B:00 C:02 D:1c E:0e F:a0 H:c4 L:50  Cy:177065196
; イベントカウンタの値をAにロード
0895:7E        LD A,(HL)       SP:dff5 A:00 B:00 C:02 D:1c E:0e F:80 H:c4 L:52  Cy:177065204
; AND Aでゼロかどうかを確かめる。今回ノーゼロ。
0896:A7        AND A           SP:dff5 A:52 B:00 C:02 D:1c E:0e F:80 H:c4 L:52  Cy:177065212
; サブルーチン終了
0897:C9        RET             SP:dff5 A:52 B:00 C:02 D:1c E:0e F:20 H:c4 L:52  Cy:177065216
; 先のイベントカウンタの値がゼロであれば77EFへジャンプ(77EEをスキップ)。
; 今回はノーゼロなので処理を行う
77EC:28 01     JR Z,77EFh      SP:dff7 A:52 B:00 C:02 D:1c E:0e F:20 H:c4 L:52  Cy:177065232
; イベントカウンタをデクリメント。
77EE:35        DEC (HL)        SP:dff7 A:52 B:00 C:02 D:1c E:0e F:20 H:c4 L:52  Cy:177065240
			

犬小屋バグにおいて異常なルーム移動先が決定されるまでの過程

部屋中の移動タイルは複数の移動先に関わらず固定の番号を持っており、 これらはマップ情報としてタイル位置に応じて複数スロット(#D416h-#D419hまでの4バイト(=4スロット)分)を持って移動先を管理し、 リンクが接触したタイルの位置とそれらを照らし合わせる事によって管理がされている。

OW・B1地点 犬小屋マップ サンプルスクリーンショット タイル位置番号 OW・B1地点 犬小屋マップ サンプルスクリーンショット タイル内容番号

前者がタイルの位置番号。後者がタイル内容。 このマップでは移動タイルの位置として35,33,00,00が振られており、それぞれの位置には共通のドアタイル「E2」が使われている事がわかる。

通常ならリンクが踏んでいるタイルの位置と タイル自体の位置のそれぞれを照合して、 同一だった番号のスロットから読み出された移動先が使われる。 だが、移動タイルに対してリンクが特定の 不正な方法で触れると「タイルに接触はしたが、移動先判定を行う際に位置がずれる」という 移動スロットのどれにも該当しない状態が起きてしまう事がある。

通常のスロット用としては[マップカテゴリ][サブルームID][ベースマップ位置][リンクX位置][リンクY位置]の5バイトが4つに連なった #D401h-#D419hの20バイト(5バイト*4スロット分)が使われているが、 この状態が起きると移動先を制御するルーチンは処理を誤り 本来なら移動先情報として読み出されてはいけない#D415h-#D419hが読み出される。

ここで読み出されてしまう#D415hの内容は敵の撃破数、その後の#D416h-#D419hの4バイトはスロット判別用のタイル位置に相当しており、 [敵撃破数][S1-判別タイル位置][S2-判別タイル位置][S3-判別タイル位置][S4-判別タイル位置]がそのまま [マップカテゴリ][サブルームID][ベースマップ位置][リンクX位置][リンクY位置]に対応して書き込まれてしまう事になる。 「それまでの敵の撃破数を変えると移動先が変化する」というのは 敵の撃破数が誤って読み出された後に書き込まれる場所がマップカテゴリ値にあたるのに由来し、 また、これが任意コード実行が出来る原因の一つともなる(後述)。

並び表 (S*はスロット、スロット番号は内部と同じ0からカウントなので注意)
0123456789ABCDEF
D40*未使用スロット0番、試行1回目(5バイト)スロット1番、試行2回目(5バイト)スロット2番、試行3回目(5バイト)
マップカテゴリサブルームIDベースマップ位置リンク開始X位置リンク開始Y位置マップカテゴリサブルームIDベースマップ位置リンク開始X位置リンク開始Y位置マップカテゴリサブルームIDベースマップ位置リンク開始X位置リンク開始Y位置
D41*スロット3番、試行4回目(5バイト)4回分の試行に失敗時(5バイト)未使用
マップカテゴリサブルームIDベースマップ位置リンク開始X位置リンク開始Y位置敵撃破数S1-判別タイル位置S2-判別タイル位置S3-判別タイル位置S4-判別タイル位置
; 実際に処理を読んだ時のトレースログ(DX版)

; おことわり 下記のトレースログはTASを製作する前の調査として取得した物であり
; 完成されたTASのキーファイルから得られる動作によるログではありません。

; 移動先スロット先頭にあたるRAMアドレス0xD416をHLにロード
18B4:21 16 D4  LD HL,#D416h    SP:dffb A:00 B:04 C:00 D:00 E:00 F:a0 H:d4 L:01  Cy:172156280

; Cレジスタを0x00に初期化(これが試行回数になる)
18B7:0E 00     LD C,#00h       SP:dffb A:00 B:04 C:00 D:00 E:00 F:a0 H:d4 L:16  Cy:172156292

; ここから移動先スロットチェックのルーチン
; #FF98h、リンクのX座標をAにロード
18B9:F0 98     LDH A,(#FF98h)  SP:dffb A:00 B:04 C:00 D:00 E:00 F:a0 H:d4 L:16  Cy:172156300

; Aレジスタをスワップ(4bitの循環右ローテーション)
18BB:CB 37     SWAP A          SP:dffb A:62 B:04 C:00 D:00 E:00 F:a0 H:d4 L:16  Cy:172156312


; 0x0FとANDする事で
; AレジスタにリンクX座標の上部4ビットだけを
; 下位4ビットに収めた物に相当する値を取り出す

18BD:E6 0F     AND #0Fh        SP:dffb A:26 B:04 C:00 D:00 E:00 F:00 H:d4 L:16  Cy:172156320
; 0x0F(00001111)とAND
; 0x26 00100110
; 0x0F 00000110
; 結果
; 0x06 00000110

; 結果となったAレジスタの内容をEレジスタにコピー
18BF:5F        LD E,A          SP:dffb A:06 B:04 C:00 D:00 E:00 F:20 H:d4 L:16  Cy:172156328

; #FF99h、リンクのY座標をAにロード
18C0:F0 99     LDH A,(#FF99h)  SP:dffb A:06 B:04 C:00 D:00 E:06 F:20 H:d4 L:16  Cy:172156332

; Y座標は下部が基点となっているので、中央点に直すために0x08を引く
18C2:D6 08     SUB #08h        SP:dffb A:30 B:04 C:00 D:00 E:06 F:20 H:d4 L:16  Cy:172156344

; 0xF0(11110000)とANDして、上位4ビットをそのまま取り出す

; 0x28 00101000
; 0xF0 11110000
; 結果
; 0x20 00100000

18C4:E6 F0     AND #F0h        SP:dffb A:28 B:04 C:00 D:00 E:06 F:40 H:d4 L:16  Cy:172156352

; リンクX座標上位4ビットだけを下位4ビットに収めた結果が入ったEレジスタと
; リンクY座標上位4ビットだけを上位4ビットに収めた結果が入ったAレジスタとでOR

; 1タイルのサイズは縦横ともに丁度0x0Fなので、
; 結果としてリンクが現在居るタイル位置に相当する0xYXという形が出来上がる
18C6:B3        OR E            SP:dffb A:20 B:04 C:00 D:00 E:06 F:20 H:d4 L:16  Cy:172156360

; その結果を先のタイル移動先スロットとコンペア
18C7:BE        CP (HL)         SP:dffb A:26 B:04 C:00 D:00 E:06 F:00 H:d4 L:16  Cy:172156364

; ゼロではない=このスロットではない
; 故にジャンプ不成立
18C8:28 07     JR Z,18D1h      SP:dffb A:26 B:04 C:00 D:00 E:06 F:50 H:d4 L:16  Cy:172156372

; HLをインクリメントし、直前スロットのアドレスから+1
18CA:23        INC HL          SP:dffb A:26 B:04 C:00 D:00 E:06 F:50 H:d4 L:16  Cy:172156380
; Cをインクリメントし、試行回数1回分をカウント
18CB:0C        INC C           SP:dffb A:26 B:04 C:00 D:00 E:06 F:50 H:d4 L:17  Cy:172156388

; 試行回数をAレジスタにコピーして0x04とコンペア
; 結果がノーゼロなら18B9へ戻る
; つまり、試行回数が0x04(=4回目の試行が失敗した直後)でなければ
; 直前のスロット処理へ戻るという処理
18CC:79        LD A,C          SP:dffb A:26 B:04 C:01 D:00 E:06 F:10 H:d4 L:17  Cy:172156392
18CD:FE 04     CP #04h         SP:dffb A:01 B:04 C:01 D:00 E:06 F:10 H:d4 L:17  Cy:172156396
18CF:20 E8     JR NZ,18B9h     SP:dffb A:01 B:04 C:01 D:00 E:06 F:50 H:d4 L:17  Cy:172156404

; また直前の処理へ戻ってくる。内容については
; スロットアドレスと試行回数が
; インクリメントされている以外は同一なのでほぼ省略。
18B9:F0 98     LDH A,(#FF98h)  SP:dffb A:01 B:04 C:01 D:00 E:06 F:50 H:d4 L:17  Cy:172156416
18BB:CB 37     SWAP A          SP:dffb A:62 B:04 C:01 D:00 E:06 F:50 H:d4 L:17  Cy:172156428
18BD:E6 0F     AND #0Fh        SP:dffb A:26 B:04 C:01 D:00 E:06 F:00 H:d4 L:17  Cy:172156436
18BF:5F        LD E,A          SP:dffb A:06 B:04 C:01 D:00 E:06 F:20 H:d4 L:17  Cy:172156444
18C0:F0 99     LDH A,(#FF99h)  SP:dffb A:06 B:04 C:01 D:00 E:06 F:20 H:d4 L:17  Cy:172156448
18C2:D6 08     SUB #08h        SP:dffb A:30 B:04 C:01 D:00 E:06 F:20 H:d4 L:17  Cy:172156460
18C4:E6 F0     AND #F0h        SP:dffb A:28 B:04 C:01 D:00 E:06 F:40 H:d4 L:17  Cy:172156468
18C6:B3        OR E            SP:dffb A:20 B:04 C:01 D:00 E:06 F:20 H:d4 L:17  Cy:172156476
18C7:BE        CP (HL)         SP:dffb A:26 B:04 C:01 D:00 E:06 F:00 H:d4 L:17  Cy:172156480
18C8:28 07     JR Z,18D1h      SP:dffb A:26 B:04 C:01 D:00 E:06 F:50 H:d4 L:17  Cy:172156488
18CA:23        INC HL          SP:dffb A:26 B:04 C:01 D:00 E:06 F:50 H:d4 L:17  Cy:172156496
; また失敗なので試行回数をインクリメント
18CB:0C        INC C           SP:dffb A:26 B:04 C:01 D:00 E:06 F:50 H:d4 L:18  Cy:172156504
18CC:79        LD A,C          SP:dffb A:26 B:04 C:02 D:00 E:06 F:10 H:d4 L:18  Cy:172156508
18CD:FE 04     CP #04h         SP:dffb A:02 B:04 C:02 D:00 E:06 F:10 H:d4 L:18  Cy:172156512
18CF:20 E8     JR NZ,18B9h     SP:dffb A:02 B:04 C:02 D:00 E:06 F:50 H:d4 L:18  Cy:172156520

; 中略。3回目の試行
18B9:F0 98     LDH A,(#FF98h)  SP:dffb A:02 B:04 C:02 D:00 E:06 F:50 H:d4 L:18  Cy:172156532
18BB:CB 37     SWAP A          SP:dffb A:62 B:04 C:02 D:00 E:06 F:50 H:d4 L:18  Cy:172156544
18BD:E6 0F     AND #0Fh        SP:dffb A:26 B:04 C:02 D:00 E:06 F:00 H:d4 L:18  Cy:172156552
18BF:5F        LD E,A          SP:dffb A:06 B:04 C:02 D:00 E:06 F:20 H:d4 L:18  Cy:172156560
18C0:F0 99     LDH A,(#FF99h)  SP:dffb A:06 B:04 C:02 D:00 E:06 F:20 H:d4 L:18  Cy:172156564
18C2:D6 08     SUB #08h        SP:dffb A:30 B:04 C:02 D:00 E:06 F:20 H:d4 L:18  Cy:172156576
18C4:E6 F0     AND #F0h        SP:dffb A:28 B:04 C:02 D:00 E:06 F:40 H:d4 L:18  Cy:172156584
18C6:B3        OR E            SP:dffb A:20 B:04 C:02 D:00 E:06 F:20 H:d4 L:18  Cy:172156592
18C7:BE        CP (HL)         SP:dffb A:26 B:04 C:02 D:00 E:06 F:00 H:d4 L:18  Cy:172156596
18C8:28 07     JR Z,18D1h      SP:dffb A:26 B:04 C:02 D:00 E:06 F:40 H:d4 L:18  Cy:172156604
18CA:23        INC HL          SP:dffb A:26 B:04 C:02 D:00 E:06 F:40 H:d4 L:18  Cy:172156612
; またまた失敗なので試行回数をインクリメント
18CB:0C        INC C           SP:dffb A:26 B:04 C:02 D:00 E:06 F:40 H:d4 L:19  Cy:172156620
18CC:79        LD A,C          SP:dffb A:26 B:04 C:03 D:00 E:06 F:00 H:d4 L:19  Cy:172156624
18CD:FE 04     CP #04h         SP:dffb A:03 B:04 C:03 D:00 E:06 F:00 H:d4 L:19  Cy:172156628
18CF:20 E8     JR NZ,18B9h     SP:dffb A:03 B:04 C:03 D:00 E:06 F:50 H:d4 L:19  Cy:172156636


; 中略。4回目の試行。
18B9:F0 98     LDH A,(#FF98h)  SP:dffb A:03 B:04 C:03 D:00 E:06 F:50 H:d4 L:19  Cy:172156648
18BB:CB 37     SWAP A          SP:dffb A:62 B:04 C:03 D:00 E:06 F:50 H:d4 L:19  Cy:172156660
18BD:E6 0F     AND #0Fh        SP:dffb A:26 B:04 C:03 D:00 E:06 F:00 H:d4 L:19  Cy:172156668
18BF:5F        LD E,A          SP:dffb A:06 B:04 C:03 D:00 E:06 F:20 H:d4 L:19  Cy:172156676
18C0:F0 99     LDH A,(#FF99h)  SP:dffb A:06 B:04 C:03 D:00 E:06 F:20 H:d4 L:19  Cy:172156680
18C2:D6 08     SUB #08h        SP:dffb A:30 B:04 C:03 D:00 E:06 F:20 H:d4 L:19  Cy:172156692
18C4:E6 F0     AND #F0h        SP:dffb A:28 B:04 C:03 D:00 E:06 F:40 H:d4 L:19  Cy:172156700
18C6:B3        OR E            SP:dffb A:20 B:04 C:03 D:00 E:06 F:20 H:d4 L:19  Cy:172156708
18C7:BE        CP (HL)         SP:dffb A:26 B:04 C:03 D:00 E:06 F:00 H:d4 L:19  Cy:172156712
18C8:28 07     JR Z,18D1h      SP:dffb A:26 B:04 C:03 D:00 E:06 F:40 H:d4 L:19  Cy:172156720
18CA:23        INC HL          SP:dffb A:26 B:04 C:03 D:00 E:06 F:40 H:d4 L:19  Cy:172156728
; 4回目の試行も失敗に終わり、試行回数のCレジスタをインクリメント。
18CB:0C        INC C           SP:dffb A:26 B:04 C:03 D:00 E:06 F:40 H:d4 L:1a  Cy:172156736
18CC:79        LD A,C          SP:dffb A:26 B:04 C:04 D:00 E:06 F:00 H:d4 L:1a  Cy:172156740

; 4回やってもダメな場合、ジャンプ命令を無視してそのまま続行する。
; この場合ジャンプで飛んでいないが、
; 途中で成立しても同じく18D1に飛んでくるのでやる事は変わらない。
18CD:FE 04     CP #04h         SP:dffb A:04 B:04 C:04 D:00 E:06 F:00 H:d4 L:1a  Cy:172156744
18CF:20 E8     JR NZ,18B9h     SP:dffb A:04 B:04 C:04 D:00 E:06 F:c0 H:d4 L:1a  Cy:172156752

; AにC(ここまでに試行した回数)をロード
18D1:79        LD A,C          SP:dffb A:04 B:04 C:04 D:00 E:06 F:c0 H:d4 L:1a  Cy:172156760
; これをSLAで4倍(0x04→0x08→0x10)に元々の値を合算して合計5倍(データサイズ分)
18D2:CB 27     SLA A           SP:dffb A:04 B:04 C:04 D:00 E:06 F:c0 H:d4 L:1a  Cy:172156764
18D4:CB 27     SLA A           SP:dffb A:08 B:04 C:04 D:00 E:06 F:00 H:d4 L:1a  Cy:172156772
18D6:81        ADD A,C         SP:dffb A:10 B:04 C:04 D:00 E:06 F:00 H:d4 L:1a  Cy:172156780

; 結果をEレジスタへコピー
18D7:5F        LD E,A          SP:dffb A:14 B:04 C:04 D:00 E:06 F:00 H:d4 L:1a  Cy:172156784
; Dレジスタを00で初期化
18D8:16 00     LD D,#00h       SP:dffb A:14 B:04 C:04 D:00 E:14 F:00 H:d4 L:1a  Cy:172156788

; 0xD401というRAMアドレスをHLにロード。
; これが移動先として書き込む内容のベースアドレスになる。
18DA:21 01 D4  LD HL,#D401h    SP:dffb A:14 B:04 C:04 D:00 E:14 F:00 H:d4 L:1a  Cy:172156796

; 先に試行回数から得た値をアドレスに合算する。
; 通常であればこれが最大の4スロット目(0から始めて3で4つ)でも
; ((3*2)+(3*2)+3)=0x0Fになるはずだが、
; 今回は4スロット全てに該当しなかった(試行回数が0から始めて04、5回目相当になっている)ので
; 結果が0x14となっている。

; つまり、HLの内容が移動先として書き込む内容が
; 含まれた正規のアドレスでなくなってしまっている。

; 正常に掴まされる形式としては[マップカテゴリ][サブルームID][ベースマップ位置][リンクX位置][リンクY位置]の順。
; 読み込まれるアドレスの先頭に当たる0xD415は敵を倒した数に相当し、
; 続く0xD416と0xD417は前述の移動先スロットの前二つに相当する。
; 追記: 移動として読み込まれる全ては [マップカテゴリ][サブルームID][ベースマップ位置][開始リンクX位置][開始リンクY位置]
18DD:19        ADD HL,DE       SP:dffb A:14 B:04 C:04 D:00 E:14 F:00 H:d4 L:01  Cy:172156808

; アドレス算出結果をスタックに積んでおく
18DE:E5        PUSH HL         SP:dffb A:14 B:04 C:04 D:00 E:14 F:00 H:d4 L:15  Cy:172156816

; 0xD415、敵を倒した数を誤ってマップカテゴリの値としてロードしつつHLをインクリメント
18DF:2A        LD A,(HL+)      SP:dff9 A:14 B:04 C:04 D:00 E:14 F:00 H:d4 L:15  Cy:172156832

; マップカテゴリの値として書き込み
18E0:EA A5 DB  LD (#DBA5h),A   SP:dff9 A:00 B:04 C:04 D:00 E:14 F:00 H:d4 L:16  Cy:172156840

; マップカテゴリとして書き込まれた値を0x02とコンペアし、
; もし02以外であれば0x18F1へジャンプ。今回成立。
18E3:FE 02     CP #02h         SP:dff9 A:00 B:04 C:04 D:00 E:14 F:00 H:d4 L:16  Cy:172156856
18E5:20 0A     JR NZ,18F1h     SP:dff9 A:00 B:04 C:04 D:00 E:14 F:50 H:d4 L:16  Cy:172156864

; D416、移動先スロット用リンク位置の1番目を誤ってサブルームID用内容としてロード
18F1:2A        LD A,(HL+)      SP:dff9 A:00 B:04 C:04 D:00 E:14 F:50 H:d4 L:16  Cy:172156876
; 結果を0xFFF7、サブルームIDへ書き込み
18F2:E0 F7     LDH (#FFF7h),A  SP:dff9 A:35 B:04 C:04 D:00 E:14 F:50 H:d4 L:17  Cy:172156884

; AにOWUWの現在値をロードしてAND Aでノーゼロかどうかチェック(今回は関係ない直後のジャンプで使用)
18F4:FA A5 DB  LD A,(#DBA5h)   SP:dff9 A:35 B:04 C:04 D:00 E:14 F:50 H:d4 L:17  Cy:172156896
18F7:A7        AND A           SP:dff9 A:00 B:04 C:04 D:00 E:14 F:50 H:d4 L:17  Cy:172156912

; D417、移動タイルスロット2番目を誤って全体部屋位置の値としてロード
18F8:2A        LD A,(HL+)      SP:dff9 A:00 B:04 C:04 D:00 E:14 F:a0 H:d4 L:17  Cy:172156916
; 全体部屋位置に書き込み
18F9:E0 F6     LDH (#FFF6h),A  SP:dff9 A:33 B:04 C:04 D:00 E:14 F:a0 H:d4 L:18  Cy:172156924

; 以下省略(リンクX位置とY位置に書き込みを行う処理が続くが、特に読む必要がないため)

			

何故ゲームモード2、#DB96hの内容が破壊されるか

宝箱の開閉状態等におけるマップ状態フラグはRAM上において OW(#D800h-#D8FFh)、UW1(#D900h-#D9FFh)、UW2(#DA00h-#DAFFh)の範囲で管理されている。 読み書きの処理としてはベースアドレス#D800hにマップカテゴリ値を上位、ベースマップ位置を下位として合算し、 更にサブルームIDの値(=UW1、UW2の区別)に応じてUW2だった場合に+#100hの合算をする事で算出される。

通常であればマップカテゴリの値は#1hが限度であり(移動時に2を渡すと横スクロールフラグを立てた上で1が書き込まれる)、 通常なら他を合算してもフラグ記録アドレスとして扱われる範囲は#D800h-#DAFFhの中へ収まる。 だが、犬小屋バグなどでマップカテゴリの値を#3h以上などの異常な内容とした場合は 単純にマップカテゴリ値を上位バイトとして合算するコードのために想定される範囲を超え、 各種ステータスなどを含んだ#DB00h以降のアドレスへ誤って書き込もうとするケースが出てくる事になる。

今回のTASにおいては犬小屋バグで異常移動を発生させる際に敵を倒した数(マップカテゴリ値)を#03hとし、 その上で宝箱を開くマップをベースマップ位置#96hとすることで#DB96、ゲームモード2の内容を破壊している。

フラグ・ベースアドレスD800
マップカテゴリ値03**
ベースマップ・現在位置値**96
UW1、UW2の区別(サブルームID値依存)*0**
フラグとして実際に書き込まれるアドレスDB96
; 無印版TAS フレーム4774-4775(end)より一部抜粋
; ゲームモードDB96hの破壊まで

; サブルーチン開始
51D8:CD E2 51  CALL #51E2h     SP:dff9 A:ff B:00 C:0f D:00 E:ff F:40 H:c3 L:bf  Cy:335395644

; 現在マップカテゴリ値をDレジスタにロードする
51E2:FA A5 DB  LD A,(#DBA5h)   SP:dff7 A:ff B:00 C:0f D:00 E:ff F:40 H:c3 L:bf  Cy:335395668
51E5:57        LD D,A          SP:dff7 A:03 B:00 C:0f D:00 E:ff F:40 H:c3 L:bf  Cy:335395684

; ベースアドレス0xD800をHLにロード
51E6:21 00 D8  LD HL,#D800h    SP:dff7 A:03 B:00 C:0f D:03 E:ff F:40 H:c3 L:bf  Cy:335395688

; 現在マップ位置をEレジスタにロードする
51E9:F0 F6     LDH A,(#FFF6h)  SP:dff7 A:03 B:00 C:0f D:03 E:ff F:40 H:d8 L:00  Cy:335395700
51EB:5F        LD E,A          SP:dff7 A:96 B:00 C:0f D:03 E:ff F:40 H:d8 L:00  Cy:335395712

; 現在サブルームIDを読み込み、1A以上なら51F7へジャンプ 今回成立
51EC:F0 F7     LDH A,(#FFF7h)  SP:dff7 A:96 B:00 C:0f D:03 E:96 F:40 H:d8 L:00  Cy:335395716
51EE:FE 1A     CP #1Ah         SP:dff7 A:35 B:00 C:0f D:03 E:96 F:40 H:d8 L:00  Cy:335395728
51F0:30 05     JR NC,51F7h     SP:dff7 A:35 B:00 C:0f D:03 E:96 F:40 H:d8 L:00  Cy:335395736

; マップフラグベースアドレスD800とDEを合算。Dはマップカテゴリ値、Eはベースマップ位置
; 0xD800+0x0396=0xDB96、つまり結果がゲームモードのアドレスとなっている
51F7:19        ADD HL,DE       SP:dff7 A:35 B:00 C:0f D:03 E:96 F:40 H:d8 L:00  Cy:335395748

; サブルーチン終了
51F8:C9        RET             SP:dff7 A:35 B:00 C:0f D:03 E:96 F:00 H:db L:96  Cy:335395756
; 現在のアドレス内容をAレジスタに読み込み
51DB:7E        LD A,(HL)       SP:dff9 A:35 B:00 C:0f D:03 E:96 F:00 H:db L:96  Cy:335395772
; 0x10(00010000)とOR、つまり4ビット(5番目)にフラグを立てる
; 本来であればこれが宝箱の開閉フラグとして使われる
51DC:F6 10     OR #10h         SP:dff9 A:07 B:00 C:0f D:03 E:96 F:00 H:db L:96  Cy:335395780
; 書き込まれる。これでDB96hの内容が破壊された事になる。
51DE:77        LD (HL),A       SP:dff9 A:17 B:00 C:0f D:03 E:96 F:00 H:db L:96  Cy:335395788
			

ゲームモードの値はメインループに含まれる処理分岐のアドレス算出に直接使われており、 これが破壊されて不正に大きな値を持つ事によってRAM・EchoRAMを含んだ想定されない範囲へのジャンプが起こり得るようになる。

; ゲームモード破壊以後・異常ジャンプまで

; ここから暴走ジャンプ
; (#DB96h)=ゲームモードをロード
431E:FA 96 DB  LD A,(#DB96h)   SP:dffd A:01 B:00 C:00 D:00 E:03 F:a0 H:76 L:50  Cy:335443580
; ここでRSTでスタックに4322が積まれる(これが分岐元のアドレスになる)
4321:C7        RST 00H         SP:dffd A:17 B:00 C:00 D:00 E:03 F:a0 H:76 L:50  Cy:335443596
0000:C3 72 28  JP #2872h       SP:dffb A:17 B:00 C:00 D:00 E:03 F:a0 H:76 L:50  Cy:335443612
; Eにゲームモード値をコピーしておく
2872:5F        LD E,A          SP:dffb A:17 B:00 C:00 D:00 E:03 F:a0 H:76 L:50  Cy:335443628
; Dを00で初期化
2873:16 00     LD D,#00h       SP:dffb A:17 B:00 C:00 D:00 E:17 F:a0 H:76 L:50  Cy:335443632
; ゲームモード値をSLAで二倍
2875:CB 23     SLA E           SP:dffb A:17 B:00 C:00 D:00 E:17 F:a0 H:76 L:50  Cy:335443640
; DをCy付き左ローテートで事実上Cy格納、今回無し
2877:CB 12     RL D            SP:dffb A:17 B:00 C:00 D:00 E:2e F:00 H:76 L:50  Cy:335443648
; 先のRST元PCの4322をスタックからHLに取り出し
2879:E1        POP HL          SP:dffb A:17 B:00 C:00 D:00 E:2e F:80 H:76 L:50  Cy:335443656
; これを上位が先のCy結果入りD、下位8ビットがDB96ゲームモードのDEと合算する
287A:19        ADD HL,DE       SP:dffd A:17 B:00 C:00 D:00 E:2e F:80 H:43 L:22  Cy:335443668
; そのアドレスからEに入れる
287B:5E        LD E,(HL)       SP:dffd A:17 B:00 C:00 D:00 E:2e F:80 H:43 L:50  Cy:335443676
; 続いてHLをインクリメントして今度はDに入れる
287C:23        INC HL          SP:dffd A:17 B:00 C:00 D:00 E:c9 F:80 H:43 L:50  Cy:335443684
287D:56        LD D,(HL)       SP:dffd A:17 B:00 C:00 D:00 E:c9 F:80 H:43 L:51  Cy:335443692
; DEをPUSHして即POP HLでHLに移す
287E:D5        PUSH DE         SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:43 L:51  Cy:335443700
287F:E1        POP HL          SP:dffb A:17 B:00 C:00 D:fa E:c9 F:80 H:43 L:51  Cy:335443716
; JP (HL)で飛ぶ。大本のゲームモードが狂っているので飛び先を誤りRAM(Echo RAM)上の#FAC9hに出てくる
2880:E9        JP (HL)         SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443728

			

名前に書かれたコードとその実行内容

内部文字表 (空は空白、*は「あ」などで埋められる未使用)
*0*1*2*3*4*5*6*7*8*9*A*B*C*D*E*F
0*
1*
2*
3*
4*****
5**
6*
7*
8*
9*****
A**.******
B**0123456789
C*R***************
D**ABCDEF十字ボタン手紙ヨッシーハイビスカス足跡罰印髑髏リンクマリン
E*タリンヨッシーリボン缶詰バナナ木の棒蜂の巣(蜂蜜)パイナップルハイビスカス箒釣り針ブラジャー人魚の鱗見通しレンズ手紙(重複?)十字ボタン(重複?)
F************

リンクの名前文字として使えるのは濁音と半濁音を含んだ平仮名全てと「ー(長音)」のみ。 また、「あ」は先頭の01以外はダミー。絵文字の重複は本編中でどちらが使われているのか不明。

余談: 「R」は「Rモトごろく」でしか使われてない……気がする。

上記の名前によって行われる操作については以下の通り。

  1. #DB95h(ゲームモードその1)の内容をEDシーケンス中の値#01hに書き換える
  2. 破壊されていた#DB96h(ゲームモードその2)を#03hとして修正する
  3. メインループ中(アドレス#0300h付近)へPCをジャンプさせて処理を正常なルーチンへ戻す

プレイ中データのリンクの名前はRAMアドレス#DB4Fh-#DB53hに5バイト(一文字1バイト)で格納されている。

プレイ中データのリンクの名前とは別に 各セーブデータ(プレイ中の物も含む)のリンクの名前もRAM上に格納されており、 それぞれセーブ1が#DB80h-#DB84h、セーブ2が#DB85h-#DB89h、セーブ3が#DB8Ah-#DB8Ehにある。 これらは何れかのデータでプレイを始めてもRAM上に保持され続けており、 今回のTASにおいては先に実行されるプレイ中リンクの文字列(データ1)から相対ジャンプを行う事で データ2、データ3の名前を実行している。

DX(JP)版においてもコード実行までは同様の方法で行えますが、各種アドレスなどの違いで「だちるねら」「けばうげま」「げばどがげ」でないと通りません。また、挙動が不安定で実行が出来ない事があります(後日追記)。

DB95とDB96を適切な値に修正しながらDB94にも#C2h(JP NZ, #****h)を書き込んでおくことで セーブ3の名前列を通り過ぎた後にゲームモードの値二つ自体がジャンプ先のアドレスとして使われ、 メインルーチン中のアドレス#0301hへのジャンプが成立する。

DX版を含めた一連の実行コードについてはpirohiko先生に相談した上で最終的に同氏に書いて頂きました。

実行されたRAM領域のダンプ表(4776frameより)
0123456789ABCDEF
DAC*00000000000000000000000000000000
DAD*00000000000000000000000000000000
DAE*00000000000000000000000000000000
DAF*00000000000000000000000000000000
DB0*04010000000000000000000000000000
DB1*00000000000000000000000000000000
DB2*00000000000000000000000000000000
DB3*00000000000000000000000000000000
DB4*00000000010000310000000000000102
DB5*03091831A10000000000100300000003
DB6*35330000400000000000000000000016
DB7*50270000000020303000000000000000
DB8*0203091831293E3D2F223E0122172200
DB9*00000000C20103E41CE48000A3000000
; TAS(無印版)中における実際のトレースログ EDジャンプまで

; HLはこのまま維持されて後のコード実行にも使われる
FAC9:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443732
FACA:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443736
FACB:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443740
FACC:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443744
FACD:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443748
FACE:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443752
FACF:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443756
FAD0:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443760
FAD1:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443764
FAD2:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443768
FAD3:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443772
FAD4:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443776
FAD5:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443780
FAD6:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443784
FAD7:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443788
FAD8:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443792
FAD9:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443796
FADA:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443800
FADB:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443804
FADC:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443808
FADD:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443812
FADE:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443816
FADF:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443820
FAE0:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443824
FAE1:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443828
FAE2:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443832
FAE3:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443836
FAE4:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443840
FAE5:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443844
FAE6:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443848
FAE7:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443852
FAE8:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443856
FAE9:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443860
FAEA:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443864
FAEB:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443868
FAEC:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443872
FAED:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443876
FAEE:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443880
FAEF:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443884
FAF0:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443888
FAF1:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443892
FAF2:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443896
FAF3:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443900
FAF4:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443904
FAF5:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443908
FAF6:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443912
FAF7:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443916
FAF8:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443920
FAF9:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443924
FAFA:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443928
FAFB:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443932
FAFC:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443936
FAFD:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443940
FAFE:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443944
FAFF:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443948
FB00:04        INC B           SP:dffd A:17 B:00 C:00 D:fa E:c9 F:80 H:fa L:c9  Cy:335443952
FB01:01 00 00  LD BC,#0000h    SP:dffd A:17 B:01 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335443956
FB04:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335443968
FB05:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335443972
FB06:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335443976
FB07:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335443980
FB08:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335443984
FB09:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335443988
FB0A:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335443992
FB0B:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335443996
FB0C:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444000
FB0D:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444004
FB0E:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444008
FB0F:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444012
FB10:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444016
FB11:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444020
FB12:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444024
FB13:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444028
FB14:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444032
FB15:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444036
FB16:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444040
FB17:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444044
FB18:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444048
FB19:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444052
FB1A:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444056
FB1B:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444060
FB1C:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444064
FB1D:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444068
FB1E:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444072
FB1F:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444076
FB20:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444080
FB21:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444084
FB22:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444088
FB23:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444092
FB24:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444096
FB25:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444100
FB26:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444104
FB27:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444108
FB28:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444112
FB29:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444116
FB2A:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444120
FB2B:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444124
FB2C:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444128
FB2D:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444132
FB2E:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444136
FB2F:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444140
FB30:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444144
FB31:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444148
FB32:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444152
FB33:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444156
FB34:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444160
FB35:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444164
FB36:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444168
FB37:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444172
FB38:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444176
FB39:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444180
FB3A:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444184
FB3B:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444188
FB3C:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444192
FB3D:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444196
FB3E:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444200
FB3F:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444204
FB40:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444208
FB41:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444212
FB42:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444216
FB43:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444220
FB44:01 00 00  LD BC,#0000h    SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444224

; DB47/FB47は汎用カウンタが一周するに応じてカウント(インクリメント)処理がされる。
; しかしながらこれはゲーム中での使用箇所が見つかっておらず、
; また、リセット処理もされないので一度カウントが進みきるとFFで固定になる。

; TASにおいて最速で宝箱からのコード実行を行おうとするとHLがデクリメントされてしまうので、
; 名前欄の一文字目はそれに合わせた物になっている。
; 他のタイミングなど、実機で行う場合はセーブ1の一文字目を「あ」にするとよい。

; 未使用カウンタでデクリメントされるHL
FB47:32        LD (HL-),A      SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c9  Cy:335444236

FB48:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c8  Cy:335444244
FB49:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c8  Cy:335444248
FB4A:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c8  Cy:335444252
FB4B:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c8  Cy:335444256
FB4C:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c8  Cy:335444260
FB4D:00        NOP             SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c8  Cy:335444264
; FB4F-FB53がプレイ中リンク名

; 直前のFB4E=剣レベル、つまり事実上0x01強制
; 1文字目、2文字目FB50で 「い(0x02)」「う(0x03)」
; Bレジスタに03、Cレジスタに02をロード
FB4E:01 02 03  LD BC,#0302h    SP:dffd A:17 B:00 C:00 D:fa E:c9 F:00 H:fa L:c8  Cy:335444268
; 3文字目「け(0x09)」
; 元々あったHLと先のBCを合算
FB51:09        ADD HL,BC       SP:dffd A:17 B:03 C:02 D:fa E:c9 F:00 H:fa L:c8  Cy:335444280
; 4文字目「ね(0x18)」 5文字目「ぐ(0x31)」	
; 0x31先に相対ジャンプする。
; ジャンプ先のDB85/FB85はセーブデータ2の名前先頭
FB52:18 31     JR FB85h        SP:dffd A:17 B:03 C:02 D:fa E:c9 F:00 H:fd L:ca  Cy:335444288

; セーブデータ2のリンク名先頭
; 「る(0x29)」でHLを倍に
FB85:29        ADD HL,HL       SP:dffd A:17 B:03 C:02 D:fa E:c9 F:00 H:fd L:ca  Cy:335444300
; 「ば(0x3E)」「ど(0x3D)」でAに3Dをロード
FB86:3E 3D     LD A,#3Dh       SP:dffd A:17 B:03 C:02 D:fa E:c9 F:10 H:fb L:94  Cy:335444308
; 「が(0x2F)」でCPL、1の補数=全ビット反転
FB88:2F        CPL             SP:dffd A:3d B:03 C:02 D:fa E:c9 F:10 H:fb L:94  Cy:335444316
; 「め(0x22)」で0xC2、JP命令(0xC2)をゲームモード直前のFB94/DB94へ書き込み
FB89:22        LD (HL+),A      SP:dffd A:c2 B:03 C:02 D:fa E:c9 F:70 H:fb L:94  Cy:335444320

; セーブデータ3リンク名先頭
; 「ば(0x3E)」「あ(0x01)」で Aレジスタに01をロード
FB8A:3E 01     LD A,#01h       SP:dffd A:c2 B:03 C:02 D:fa E:c9 F:70 H:fb L:95  Cy:335444328
; 「め(0x22)」でFB95/DB95ゲームモード一つ目に
; 01(=EDシーケンス中)を書き込みつつHLをインクリメント
FB8C:22        LD (HL+),A      SP:dffd A:01 B:03 C:02 D:fa E:c9 F:70 H:fb L:95  Cy:335444336
; 「ぬ(0x17)」でCy付き左ローテート
; 今回はCyが1なのでAレジスタ値が01→03 ローテート自体で01→02、右にCy入って03
FB8D:17        RLA             SP:dffd A:01 B:03 C:02 D:fa E:c9 F:70 H:fb L:96  Cy:335444344
; 「め(0x22)」で破壊されていたDB96/FB96を03で修正。
; 03はEDシーケンス中で無操作進行する値
FB8E:22        LD (HL+),A      SP:dffd A:03 B:03 C:02 D:fa E:c9 F:00 H:fb L:96  Cy:335444348
; 名前列はここまで
FB8F:00        NOP             SP:dffd A:03 B:03 C:02 D:fa E:c9 F:00 H:fb L:97  Cy:335444356
FB90:00        NOP             SP:dffd A:03 B:03 C:02 D:fa E:c9 F:00 H:fb L:97  Cy:335444360
FB91:00        NOP             SP:dffd A:03 B:03 C:02 D:fa E:c9 F:00 H:fb L:97  Cy:335444364
FB92:00        NOP             SP:dffd A:03 B:03 C:02 D:fa E:c9 F:00 H:fb L:97  Cy:335444368
FB93:00        NOP             SP:dffd A:03 B:03 C:02 D:fa E:c9 F:00 H:fb L:97  Cy:335444372
; 先に書き込んでおいたFB94/DB94のジャンプ命令を踏んで
; ゲームモードにあたるDB95/FB95とDB96/FB96自体をジャンプ先として利用する
; 0301はメインループ中に相当しており
; 結果ここまでの操作によってエンディングシーケンスへのジャンプが成立する
FB94:C2 01 03  JP NZ,#0301h    SP:dffd A:03 B:03 C:02 D:fa E:c9 F:00 H:fb L:97  Cy:335444376

; メインループ中へ戻ってきた!
0301:FA 7C C1  LD A,(#C17Ch)   SP:dffd A:03 B:03 C:02 D:fa E:c9 F:00 H:fb L:97  Cy:335444392
			
inserted by FC2 system