DQ3 ループアニメーションの仕組み

DQ6のマップをインポートした際に気がついたのですが、燭台の炎など、明らかにパレットアニメーションではなく、画像自体が変化しているアニメーションがあります。これを再現できないと完全に移植できたとはいえないので例によって必要に迫られて調べてみました。

  • SR: $0A5B38 ダーマ神殿進入時初期化処理
0A5B64JSL $C77889SR: $077889 引数:1#$CAE5D7ループアニメーション2設定

  • SR: $0AE5D7 ダーマ神殿ループアニメーション設定
0AE5D7JSL $CBDF05SR: $0BDF05ループアニメーション設定(BG1,2用)
0AE5DBJSL $CBDF25SR: $0BDF25ループアニメーション設定(BG1,2用)
0AE5DFJSL $CBE064SR: $0BE064パレットアニメーション設定(夜のみ)
0AE5E3JSL $CAEB35SR: $0AEB35パレットアニメーション設定?
0AE5E7RTLreturn

  • SR: $0BDF05 ループアニメーション設定(BG1,2用)
0BDF05LDA #$000EA=#$000E
0BDF08JSL $C472D7SR: $0472D7ループアニメーションアクセス(BG1,2用)
0BDF0CRTLreturn

  • SR: $0472D7 ループアニメーションアクセス(BG1,2用)
04730BJSL $C90501SR: $090501 引数:1#$00 引数:2#$0007 引数:3#$C54E84 引数:4#$4A構造体アクセス Y番目の先頭アドレスをDP($00,第4引数)にセット

ざっくり言うと、最終的に$054E84-の固定長のデータにアクセスしています。上で例示した#$0E番目のレコードは以下のようになっています。便宜上ループアニメーションインデックスと呼びます。

アニメーションパターン開始アドレスループアニメーション実データ開始アドレス使用SNES4BPP画像数
EE502BEE503404

それぞれのアドレスの先は可変長のデータです。まず1つめは#$FFをターミネーターにして2バイト1セットでループするフレーム数*1、パターンIDを記述します。$2E502Bから9バイトは以下のようになっています。

フレーム数パターンID
0800
0801
0802
0803
FF

8フレームごとに0→1→2→3→0とループしていく、ということを意味します。

次に実データを見ていきます。まず各フレームごとの開始アドレス(3バイト*パターン数)が来ます。

ID0EE5040
ID1EE5048
ID2EE5050
ID3EE5058

1パターンごとにいくつのSNES4BPP画像を使用するかはループアニメーションインデックスの7バイト目で規定しています。この場合は4です。ターミネーターは存在しません。

ID022CE22D722CD22D6
ID13EE03EDA3EDF3ED9
ID23EE13EDC3EDF3EDB
ID33EE33EDE3EE23EDD

これは8フレームごとにマップ中のSNES4BPP画像ID #$22CEのものを#$3EE0、#$3EE1、#$3EE3に置き換えていく、という事を意味します(残りも同様)。画像IDで指定しているので、反転した画像も対象になるようです。データフォーマットはスプライトと非常によく似ています。わかってしまえばそれほど難しくないわけで、ループ中に使われる画像も一緒に抜いてきて追加して上記のデータをポチポチとバイナリエディタで打っていけば移植完了です。データ量も大して大きくないので手打ちで乗り切りました。この手法はすごろく場のスライムのアニメーションにも使用されており、強エンカウントの画像をスライムからドラゴンに差し替えた時も同様のレコードを追加して対応しています。

*1:正確にはフレーム数ではなく恐らく1処理単位と思われるが便宜上フレームと呼ぶ

コメント

タイトルとURLをコピーしました