英語による解説文は http://tasvideos.org/4709S.html をご参照ください。
前回のTAS(sm26296564)からRAT926氏によって移動部分で1:12で10Fと2:36で40Fほど更新されています。
※参考URL http://tasvideos.org/forum/viewtopic.php?p=408522#408522
裏ゼルダにするためにファイル名にZELDAの文字が必要で、
- ZELDAEヤ6
- Wヤ6AG2シ2
- ユノ6ソク+
ZELDAの後ろに文字が入ってても裏ゼルダになるので19文字分使えますが、
2マス空白にしているのでここでは17文字が任意コードに使われています。
ゼルダのファイル名は$0638・$0640・$0648の3つ分が連続して格納されています。
墓地にてギーニを沢山出して枠を埋めた後に笛を装備しながらABを押すと
本来スプライトのためではない部分が変更され、
バグAIとして$0602からプログラムが実行されます。
その近辺はBGMの制御に使われているのでタイミング調整で
ファイル名アドレス$0638部分までプログラムカウンタが進むようにしています。
- $0638: 23 0E 15 0D 0A 0E 4B 06
- $0640: 20 4B 06 0A 10 02 33 02
- $0648: 4C 40 06 36 2F 64 24 24
はじめの5文字はZELDAに使われているので$063Dからがコードになります。
- $063D: 0E 4B 06 ASL $064B
この ASL(Arithmetic Shift Left)」は「算術左シフト」を表し、
$064Bの[36]の値を2倍の[6C]へ書き換えてます。
ファイル名に使用可能な文字が[00-64]の範囲なので、
それを超える値を使うためにこのような手法をとっています。
ここからはリアルタイムにキー入力をメモリに書き込んで
$06C3から新しいコードを書くためのループ文となっています。
このコードの原型はsockfolder氏によって書かれました。
※参考URL http://tasvideos.org/forum/viewtopic.php?p=408475#408475
- $0640: 20 4B 06 JSR $064B
- $0643: 0A ASL
- $0644: 10 02 BPL $0648
- $0646: 33 02 RLA ($02),Y
- $0648: 4C 40 06 JMP $0640
- $064B: 6C 2F 64 JMP ($642F)
以下流れ
- $0640: 20 4B 06 JSR $064B
- $064B: 6C 2F 64 JMP ($642F)
EA1Fが文字で表現できないので、($642F)に書かれているEA1Fを拾って間接ジャンプ。
このルーチンが終わると先程のJSRの次の$0643に戻ってきます。
この時、CPUのAレジスタとYレジスタには前フレーム差分と現フレームのキーが入ってます。
- $0643: 0A ASL
キーはそれぞれ A[80],B[40],Sel[20],sT[10],↑[08],↓[04],←[02],→[01]
が合わさったものが入ります。
- $0644: 10 02 BPL $0648
つまりAが押されていた場合はキャリー・フラグが発生します。
ASLで2倍にされたAレジスタが[80]以上だった場合、
つまりBが押されていた場合にはここでネガティブ・フラグが立ち、
Bが押されていなかった場合にはネガティブ・フラグはクリアになっています。
BPL命令によってネガティブ・フラグがクリアならば$0648へ相対ジャンプします。
つまりBが押されたフレームは$0646が実行され、そうでない場合は次の命令へ飛びます。
- $0646: 33 02 RLA ($02),Y
($02)にはこの時$0602という値が入っているので、$0602+Yレジスタのメモリが
キャリーつき左ローテートされ、Aレジスタはメモリとの論理積になります。
左ローテートは左シフトの後にキャリーフラグがあった場合に+1されます。
つまりAB右が新規に押された場合はキャリーフラグとネガティブフラグが立ち、
$0602+Y[C1]= $06C3 のメモリが2倍+1になり、
前フレームにAが押され、次フレームにAB左が押された場合はネガティブフラグのみで、
$0602+Y[C2]= $06C4 のメモリは単に2倍になります。
- $0648: 4C 40 06 JMP $0640
Bが新規に押されたフレームのみ$0646が一度だけ実行されるので、
実質的に新規コードを書き込む速度は2フレームに1bitとなります。
2フレームに1バイトではなくとてもゆっくりです(;´Д`)
入力の終わりに$064Bを2倍に書き換えてループを解きます。
$06C3から書かれた新規コードは5秒弱で24バイトで
29 02 20 4C 84 09 09 85 10 6E 00 20 A5 3C D0 FC 09 13 20 4C 84 20 7B 63
となっています。
エンディングはLevel9ダンジョンじゃないと読み込まれないのではないかと思います。
このコードの詳細はまだMasterjun氏が解説してないので略しますが、
- ゲームモードを読み込み状態に書き換え
- マップIDをLevel9のダンジョンに書き換え
- ディスクを読み込み
- 笛で止まった時間のタイマーが0になるまでループすることで読み込み終了を検知し
- ゲームモードをイベント状態に書き換えてイベントを暴走させ
- メインループのNMI待ちの箇所へジャンプしてエンディングを待つ