FC ダブルムーン伝説 in 19:50.34

frames: 71538, re-records: 42695
movie: website | microstorage
encode: nicovideo (account | free)

前回から9分弱更新。更新点は:

  • 預けアイテム個数が48を超えているとさらにアイテムを預けられる現象を利用し、メモリ書き換え効率を改善
  • 細かい最適化

預かり所バグの詳細については別記事を参照。

メモリ書き換えの流れ

まず必要なイベントフラグを確認しておきます。今回は船座標を直接いじるので前回より必要なフラグは少なくなっています:

フラグ アドレス bit 対応する預けアイテムアドレス
ファンタム島浮上 $05DA bit1 $6417
アルテミス号入手 $05E3 bit6 $6420
サモイレンコを撃破していない(0にする) $05E5 bit3 $6422
プリンセスムーン排除 $05E5 bit1 $6422

なお、預けアイテムアドレスは49番目の空欄引き出し処理による2Byteシフトを考慮したものです。

預かり所に到達したら、最初にかいふくそう(0x3C)、次にディスペのしょ(0x7C)を預け、後はイベントフラグを考慮しつつ48個預けます。このときメモリは以下のようになります:

      00 01 02 03 04 05 06 07   08 09 0A 0B 0C 0D 0E 0F
63F0: .. .. .. .. .. .. .. .. - .. .. .. .. .. .. 30 3C  # 預けアイテム個数預けアイテム
6400: 7C 3E 3F 3F 3F 3F 3F 3F - 3F 3F 05 3F 3F 3F 3F 3F
6410: 24 05 3F 3F 3F 3F 3F 3F - 3F 3F 3F 3F 3F 3F 3F 3F
6420: 55 3F 03 21 74 3A 2D 3F - 3F 3F 3F 24 05 67 77 40  # 宝箱フラグ
6430: 12 03 00 00 00 00 00 00 - 7B AD 0D 00 00 .. .. ..  # 船y/x座標町ブックマーク
...
6470: .. .. .. .. .. .. .. 00 - 03 04 01 00 00 .. .. ..  # PTキャラID

次に49番目の空欄を1回引き出します:

      00 01 02 03 04 05 06 07   08 09 0A 0B 0C 0D 0E 0F
63F0: .. .. .. .. .. .. .. .. - .. .. .. .. .. .. 3B 7C
6400: 3E 3F 3F 3F 3F 3F 3F 3F - 3F 05 3F 3F 3F 3F 3F 24
6410: 05 3F 3F 3F 3F 3F 3F 3F - 3F 3F 3F 3F 3F 3F 3F 55
6420: 3F 03 21 74 3A 2D 3F 3F - 3F 3F 24 05 67 77 77 12
6430: 03 00 00 00 00 00 00 7B - AD 0D 00 00 00 .. .. ..
...
6470: .. .. .. .. .. .. .. 03 - 04 01 00 00 .. .. .. ..

預け個数が 0x3B になったので、この状態でアイテムを預ければ $643A, $643B, ... (町ブックマーク)を書き換えられます。そこでヒーリンのしょ(0x91)、アウフレのしょ(0x71)の順に預けます(これが後に船y/x座標になります。ただしx座標については補正が必要(後述)):

      00 01 02 03 04 05 06 07   08 09 0A 0B 0C 0D 0E 0F
63F0: .. .. .. .. .. .. .. .. - .. .. .. .. .. .. 3D 7C
6400: 3E 3F 3F 3F 3F 3F 3F 3F - 3F 05 3F 3F 3F 3F 3F 24
6410: 05 3F 3F 3F 3F 3F 3F 3F - 3F 3F 3F 3F 3F 3F 3F 55
6420: 3F 03 21 74 3A 2D 3F 3F - 3F 3F 24 05 67 77 77 12
6430: 03 00 00 00 00 00 00 7B - AD 0D 91 71 00 .. .. ..
...
6470: .. .. .. .. .. .. .. 03 - 04 01 00 00 .. .. .. ..

再び49番目の空欄を1回引き出します:

      00 01 02 03 04 05 06 07   08 09 0A 0B 0C 0D 0E 0F
63F0: .. .. .. .. .. .. .. .. - .. .. .. .. .. .. 7B 3E
6400: 3F 3F 3F 3F 3F 3F 3F 3F - 05 3F 3F 3F 3F 3F 24 05
6410: 3F 3F 3F 3F 3F 3F 3F 3F - 3F 3F 3F 3F 3F 3F 55 3F
6420: 03 21 74 3A 2D 3F 3F 3F - 3F 24 05 67 77 77 77 03
6430: 00 00 00 00 00 00 7B AD - 0D 91 71 00 00 .. .. ..
...
6470: .. .. .. .. .. .. .. 04 - 01 00 00 .. .. .. .. ..

預け個数が 0x7B になったので、この状態でアイテムを預ければ $647A (PT4人目キャラID)以降を書き換えられます。そこでまほうのもと(0x5D)を預け、4人目キャラIDを 0x5D にします:

      00 01 02 03 04 05 06 07   08 09 0A 0B 0C 0D 0E 0F
63F0: .. .. .. .. .. .. .. .. - .. .. .. .. .. .. 7C 3E
6400: 3F 3F 3F 3F 3F 3F 3F 3F - 05 3F 3F 3F 3F 3F 24 05
6410: 3F 3F 3F 3F 3F 3F 3F 3F - 3F 3F 3F 3F 3F 3F 55 3F
6420: 03 21 74 3A 2D 3F 3F 3F - 3F 24 05 67 77 77 77 03
6430: 00 00 00 00 00 00 7B AD - 0D 91 71 00 00 .. .. ..
...
6470: .. .. .. .. .. .. .. 04 - 01 00 5D .. .. .. .. ..

ここで一旦セーブしてデータ2からロードし、キャラID 0x5D のデータをロードします(キャラIDを 0x70 に変更してからこのデータをセーブすればイベントフラグが適切に書き換わります)。またこのとき同時に船x座標の補正も行われます。この時点ではまだ船x座標の値は町ブックマーク領域($643A)にあり、ロード時は「現在の町と最初の町(アレス)を町ブックマークに加える」処理が行われるため、$643A のbit0とbit3が1になり、結果として船x座標は 0x71 → 0x79 と変化します:

      00 01 02 03 04 05 06 07   08 09 0A 0B 0C 0D 0E 0F
63F0: .. .. .. .. .. .. .. .. - .. .. .. .. .. .. 7C 3E
6400: 3F 3F 3F 3F 3F 3F 3F 3F - 05 3F 3F 3F 3F 3F 24 05
6410: 3F 3F 3F 3F 3F 3F 3F 3F - 3F 3F 3F 3F 3F 3F 55 3F
6420: 03 21 74 3A 2D 3F 3F 3F - 3F 24 05 67 77 77 77 03
6430: 00 00 00 00 00 00 7B AD - 0D 91 79 00 00 .. .. ..
...
6470: .. .. .. .. .. .. .. 04 - 01 00 5D .. .. .. .. ..

次にアウコーのしょ(0x70)を預けます。預け個数は 0x7C になっているので、$647B (4人目キャラIDの次のアドレス)が 0x70 に書き換わります:

      00 01 02 03 04 05 06 07   08 09 0A 0B 0C 0D 0E 0F
63F0: .. .. .. .. .. .. .. .. - .. .. .. .. .. .. 7D 3E
6400: 3F 3F 3F 3F 3F 3F 3F 3F - 05 3F 3F 3F 3F 3F 24 05
6410: 3F 3F 3F 3F 3F 3F 3F 3F - 3F 3F 3F 3F 3F 3F 55 3F
6420: 03 21 74 3A 2D 3F 3F 3F - 3F 24 05 67 77 77 77 03
6430: 00 00 00 00 00 00 7B AD - 0D 91 79 00 00 .. .. ..
...
6470: .. .. .. .. .. .. .. 04 - 01 00 5D 70 .. .. .. ..

ここで49番目の空欄を1回引き出せば、船y/x座標の値が正しいアドレスに移動し、さらに4人目キャラIDが 0x70 になります:

      00 01 02 03 04 05 06 07   08 09 0A 0B 0C 0D 0E 0F
63F0: .. .. .. .. .. .. .. .. - .. .. .. .. .. .. 3D 3F
6400: 3F 3F 3F 3F 3F 3F 3F 05 - 3F 3F 3F 3F 3F 24 05 3F
6410: 3F 3F 3F 3F 3F 3F 3F 3F - 3F 3F 3F 3F 3F 55 3F 03
6420: 21 74 3A 2D 3F 3F 3F 3F - 24 05 67 77 77 77 77 00
6430: 00 00 00 00 00 7B AD 0D - 91 79 00 00 00 .. .. ..
...
6470: .. .. .. .. .. .. .. 01 - 00 5D 70 .. .. .. .. ..

後はセーブしてイベントフラグを書き換え、船に乗ってラストダンジョンへ行けばOK。

ダークマスター戦

今回はダークマスター戦が前回より1ターン余計にかかっていますが、これはロウィーナを謀殺したためです。ダークマスター戦を4ターンで終えるためには、1ターン目で主人公が聖なる光を発動し、直後にリオナが「ねらう」による守備力低下を決める必要がありますが、乱数更新ルーチンを見る限りそれは発生しえないと思われます。

乱数は $83-$84 で、聖なる光の発動条件は $83 <= 0x09 であること、「ねらう」の成功条件は $84 の最上位bitが立っていること*1です。乱数更新ルーチンは以下のようになっています:

; # $83-$84:乱数
; # $01:フレームカウンタ
; C = $84!=0x01 && $84!=0x80
; ROL($83)
; ROL($84)
; $83 ^= $01
FEDA : lda $84
FEDC : and #$81
FEDE : beq $FEE8
FEE0 : cmp #$01
FEE2 : beq $FEEB
FEE4 : cmp #$80
FEE6 : beq $FEEB
FEE8 : sec
FEE9 : bcs $FEEC ; bra
FEEB : clc
FEEC : rol $83
FEEE : rol $84
FEF0 : lda $83
FEF2 : eor $01
FEF4 : sta $83
FEF6 : rts

つまり $83 の最上位bitは $84 の最下位bitへそのまま伝播することになります。そして、聖なる光が発動した直後に「ねらう」成功判定が行われるまでには乱数が8回更新されます(聖なる光に会心を組み合わせても同様)。ということは、聖なる光が発動した時点で $83 の最上位bitが1でなければ直後の「ねらう」は成功しないわけですが、聖なる光の発動条件は $83 <= 0x09 なので、それはありえません。よって聖なる光の直後に「ねらう」が成功することはないと思われます。

なお、ロウィーナが生きていれば聖なる光と「ねらう」の間に防御を挟むことで乱数を動かせるので、ダークマスター戦は4ターンで終えられます。

ダークドラゴン戦

ダークドラゴン戦では回避も先制も不可能なので、リオナをデコイとして使っています。このためサモイレンコ戦終了時にリオナを生存させておく必要があり、LVUP処理に若干時間がかかっています。

ダークドラゴンの打撃は命中力255で、こちらはどう頑張っても回避力(命中/2+回避)は150程度にしかならず、乱数による回避ボーナスは最大64のようなので命中力を上回るのは無理と思われます。ということで回避はおそらく不可能です。

ダークドラゴンの回避は100で、ジーナス(初期LV5, 初期素早さ29, 最大素早さ上昇4)はサモイレンコ戦でLV20になりますが、完璧に吟味を行っても素早さは89止まりで、炎の洞窟で拾える小型の盾を装備しても99止まりです。行動順は回避順(ランダム要素なし)なので、ジーナスが先制するのも難しいようです(別途装備を入手して回避を上げれば一応先制できるが、時間がかかりすぎる)。

雑多なこと

今回は預かり所を埋めるアイテムとは別にアウコーのしょを購入しましたが、バグキャラ 0x5D のアイテム欄に入るような形でアウコーのしょを預ければどくけしそうは1つ少なくて済むかもしれません。ただしバグキャラ 0x5D のアイテムを操作するとフリーズしたり、5人目以降のアイテム欄が開けるようになるなど妙な現象が起こるので、検証してみないと何ともいえないところです。

町での移動(もしかしたらフィールド/ダンジョンも?)は経路によって所要フレーム数が異なる場合があります。例えば、ガルガンダの宿からギルドの階段に行くだけでも経路により最大5Fの差が出ます。今回はこれについてはそこまで厳密にはチェックしていません。

*1:本来は対象の防御力で判定を行う意図だったように見えるが、cmp 命令を入れ忘れている模様。そのため乱数更新時の rol 命令でキャリーが発生したかどうかで判定される