久しぶりの更新です例によって「ダウンロード」ページにうpしてあります。今回はバグフィックス版ではなく、いろいろと機能追加をしています。
- 固定長データの中途レコード挿入/削除機能
- ROM基本情報の編集(ROM名、チェックサムのみ変更可能)
- スプライトデコード部分の改良
- スプライト編集機能の実装
1は使いどころは限定されるのですが、例えばDQ3で「アイテム整列順」を変更する場合には便利になると思います。2はまああってもなくてもどうでもいいですね。3は4の作業中に発見したもので、今までデコードが不完全だったDQ3の鳥(スプライトID:#$3)、DQ6のデスタムーア第2形態(スプライトID:#$D4)も正しくデコードできるようになり、スプライトの解析はかなり完成度が高まりました(詳細は後述)。今回の目玉はやはり4です。目玉と言ってもまだまだ機能としてはプリミティブで改良の余地はあるのですが、「編集が極めて面倒くさい」DQ36のスプライトの編集が曲がりなりにもできるようになったのは前進だと思います。ただ、この機能があったとしても、実際にオリジナルのモンスターをアニメーション(しかも複数パターン)させるには大量の画像データが必要なため、残念ながらこの機能を活用するケースはかなり限られるでしょう。今回自分がこの機能を実装したのは、マップ上にNPCでは表現しきれないキャラクターを配置するためで、スプライトの数も2個としょぼいのですが、今回実装した機能で問題なくアニメーション(笑)できました。今後の課題は
- 無駄なデータの圧縮機能を実装する
- ビットマップデータからスプライトを構成できるようにする
- 実際のアニメーションのプレビューができるようにする
かなと思うのですが、需要の問題ですね。いくら環境があっても絵がないとしょうがないので。さて、現状わかっている範囲でスプライトデータの説明をします。大体は以前ろだに86氏がうpしてくれた情報*1とかぶっています。
まず、スプライトグラフィックインデックス($0542A6-)の0-2バイトが1)アニメーションデータの開始アドレス、3-5バイトが2)個別スプライトデータの開始アドレスとなっています。先に全体構造を示すと以下のようになります。
- 1)アニメーションデータ
- 1-1)各アニメーションパターン開始アドレス
- 1-2)アニメーションパターンデータ
- 2)個別スプライトデータ
- 2-1)各スプライトデータ開始アドレス
- 2-2)各スプライトデータ
- 2-2-1)スプライト内画像インデックス情報
- 2-2-2)画像配置情報
今回スプライトをマップ上に配置するにあたって「2枚のスプライトしか使わないわけだし、バイナリエディタ上で直接やればいいか」と最初は思ったのですが、実際やってみるとえらく面倒です。なにしろ後ろのデータによって前のデータのアドレスが変わるので、ちょっとやったところで「これは無理」と判断してツール実装と相成ったわけですww。1次元配列になっているものをばらして個別編集できるようにして、それぞれ編集した後また1次元配列に戻すだけなわけで、作業自体はそれほど難しくはないのですが、何より面倒くさかったのと、どう直感的にデータを表示するかという部分があまりイメージできなかったためにモチベーションが上がらず、だらだらと時間をかけてしまいました。といってもリリースしたバージョンでもただ単にバイナリデータをばらばらにして並べただけなんですが。では、個別の部分の説明に移ります。
- 1-1)各アニメーションパターン開始アドレス(3バイトxパターン数)
スプライトが持つアニメーションパターンの数だけ開始アドレスが存在し、それぞれ1-2)の開始アドレスを指します。モンスターで言えば5パターンあるスライム系は3バイトx5の15バイト開始アドレスが並ぶことになります。
- 1-2)アニメーションパターンデータ(4バイトx可変+1バイト(#$FF))
4バイト1セットでターミネーターの#$FFが来るまで繰り返します。4バイトの内訳は以下の通り。
00 | スプライトID |
01 | フレーム数? |
02 | X軸方向移動ピクセル/フレーム(Singed Byte,マイナスもありうる) |
03 | Y軸方向移動ピクセル(同上) |
スプライトデータと比べていまいちよくわからないのですが、最初の2つについてはほぼ確定でしょう。後ろ2つについては、それぞれX方向、Y方向に関する指定のようですが、ピクセルでもなさそうで、詳細は不明です。どうやら後ろ2つは、「1フレームにおけるX軸,Y軸方向への移動座標(ピクセル)」のようです。つまり、速く移動させたければ、フレーム数を少なく、移動ピクセルを多く、ゆっくり移動させたければフレーム数を多く、移動ピクセルを少なくすることで制御する、ということのようです。
- 2-1)各スプライトデータ開始アドレス(3バイトxスプライト数)
スプライトの数だけ開始アドレスが存在し、それぞれ2-2-1)の開始アドレスを指します。例えばスライム系は27スプライトあるので、3バイトx27の81バイト開始アドレスが並ぶことになります。
- 2-2-1)スプライト内画像インデックス情報(可変)
00-01 | 2-2-2)開始位置へのオフセットバイト数 |
02-03 | 画像数 |
・・・・ | グラフィックインデックス |
以降$00-01のオフセットに到達するまで、以下のルールで2バイトづつデータが格納されている | |
a) $FFXXの場合 スプライト内インデックスを$XXジャンプする | |
b) a)以外の場合 画像実データへのインデックス($0E0080 + $20 * $XXXXでアドレスを取得できる) |
ここでは、スプライトを構成する8×8のSNES4BPPの画像データにインデックスを振るためのデータを格納しています。$FFXXが特殊な意味で使われているので画像データインデックスは$FF00より小さくないといけません。また、スプライトによっては、画像情報を全て1枚目のスプライトに記述しないと正しく表示できないケースがあるようですが、何が条件になっているか不明です。
- 2-2-2)画像配置情報(可変)
00 | 画像配置情報の個数 | |
・・・・ | 画像配置情報 | |
以降$00の数だけ4バイトづつデータが格納されている | ||
00 | X座標(Singed Byte,マイナスもありうる) | |
01 | Y座標(同上) | |
02 | スプライト内画像インデックス(03バイト目1ビット目も使用) | |
03 | 0bit | 02の続き |
1bit | 不明 | |
2bit | 不明 | |
3bit | 不明 | |
4bit | 0: 8×8の1マスを配置 1: 16×16の4マスを配置 | |
5bit | 0: 「スプライト内画像インデックス」を1枚目のスプライトの画像群を対象にする 1:「スプライト内画像インデックス」を現在のスプライトの画像群を対象にする | |
6bit | 1: 左右反転 | |
7bit | 1: 上下反転 |
ここでは、2-2-1)でインデックスを振った画像データをどの座標に配置するかのデータを格納しています。3バイト目1bit~3bitの意味は未だ不明です。なお、16×16配置する場合は、スプライト内画像インデックスの値が$Xとすると、
左上:$X, 右上:$X+1, 左下:$X+$10, 右下:$X+$11
の画像をそれぞれ配置します。左右反転の場合は左右逆に配置し、画像自体も反転させます(上下反転の場合も同様)。
*1:よく見たら元々は45氏作成のようですね、スイマセン
コメント
記事よんだだけど何もしてないで言ってしまうけど
「画像配置情報」ということはOAM辺りの情報でしょうかね
優先度で2bit、色情報で3bitなわけですが
特に色情報は船は2つある共有のを使ってますが、ラーミアと飛行時のキラキラは専用パレットがあるようですので
優先度は竜の女王辺りがタマゴ出して消える時とかに使ってますね
勘違いの検討違いすぎたらすまそ。その時はまともに覗いてみま
しかしDQ凄いなぁ、たった2つのパレットでほぼ全てのキャラグラ作っていたのか・・・使い回しすぎだろw
ごぶさたです。優先度やら色情報はおそらく「不明」になっている部分か、スプライトインデックスのほうにあるんでしょうね。これ以上突っ込んでも得るものはあんまりなさそうなのでもう調べないかもしれませんが。