SpriteToolとPIXIのスプライトの違いって、なんなのー? 備考録とエトセトラ
英語資料とか、スペイン語資料とかはわりと豊富だけど、日本語での資料はそんなになかったりする印象なので、 てきとうに書き記しておきます。
私自身はスプライトを全然書かないので、内容はかなり雑です。
もくじ
ロジック的な違いはないよ
まず、大事な知識として、SpriteToolとPIXIで、スプライトの動作ロジックとかに関する違いというのはありません。
よほど特殊なことを考えない限り、SpriteToolのスプライト作成知識と似たような感じでコーディングできます。 (SuperFXチップを使う、とか、そういう場合とかはハナシは別)
また、SA-1パッチを導入しない場合は、SpriteTool用のスプライトを、PIXIで(ほぼそのまま)使うことができます。 (たしか)
じゃあ違いってなんなんだろう
違いとしては、以下の4点になると思います。
- アセンブラ
- エントリポイントの書き方
- cfg / json
- LoROM / SA-1 Hybrid メモリマップ対応(条件付きアセンブル)
これらの他にも、Xレジスタを変更したときに、後でスタックから復元されるか否か、等の細かい違いがありますが、 詳細なことはすっかりわすれてしまったので割愛。
アセンブラ
SpriteTool
特に指定がない限り、TRASMを使います。
cfgファイルのXKAS使用情報を有効にした場合、v1.40ではXKASを、v1.41(?)以降ではASARを使います。
(厳密に、v1.4系のどのバージョンからASARに移行したかは把握してません)
PIXI
ASARを使います。
エントリポイントの書き方
SpriteTool (v1.35以前)
SpriteTool用のスプライト(特に、v1.35以前のもの)は、エントリポイントの検出に、以下のTRASMの疑似命令を使います
イニシャルルーチン:
dcb "INIT"
メインルーチン:
dcb "MAIN"
これは、スプライトの中に INIT
および MAIN
という文字列を仕込んでおくものです。
スプライトのasmソースをアセンブルした後、SpriteTool側でバイナリデータ内からこの文字列を検索し、ルーチンの位置を特定します。
PIXI(またはSpriteTool v1.40以降のxkas用)
PIXI用のスプライトでは、エントリポイントの検出に、以下のASAR(XKAS)の疑似命令を使います。
イニシャルルーチン:
print "INIT ", pc
メインルーチン:
print "MAIN ", pc
これは、スプライトをアセンブルした際に、標準出力にそれぞれのルーチンのアドレスを出力するものです。
PIXIは、この出力を受け取り、ルーチンの位置を特定します。
SpriteToolでの手法と異なり、アセンブル後のバイナリデータに文字列が含まれない為、その分データ量が少なくなります。 ( といっても、8バイト程度ではありますが )
cfg / json
スプライトの設定ファイルとして、SpriteToolでは、拡張子が .cfg の、テキストベースの独自の設定ファイルを使用していました。
PIXIでは、この .cfg ファイルに加えて、汎用的な設定記述言語であるJSON( .json ) でスプライトの設定を記述することができます。
JSONファイルは、従来のcfgファイルよりも柔軟な記述が可能なことに加え、拡張設定の記述もしやすくなっています。 そのため、cfgファイルは使われなくなってきています。
PIXIに付属のCFG Editorで作成できるので、これ以上の説明はいらないでしょう。
私がよくしらないので説明できない
LoROM / SA-1 Hybrid メモリマップ対応
実はこれは必須ではなかったりするのですが、SMWCの多くのスプライトはこれの対応をしており、デファクトスタンダードになっているので、 メモっておきます。
とりあえず、ざっくりどう書いておけばいいか
ダイレクトページ(1バイト指定アドレス)
スプライトに関係するもの等で、今まで LDA $9E,x
等と書いてたものは、 LDA !9E,x
に
スプライトに無関係な汎用RAMの場合、LDA $00
でそのまま使用可能
絶対アドレス(2バイト指定)
$00FF以前の場合、今まで STZ $00EE
等と書いてたものは、 STZ $00EE|!Base1
もしくは STZ $00EE|!dp
としておけばよし
$0100以降の場合、今まで STA $1DFC
等と書いてたものは、 STA $1DFC|!Base2
もしくは STA $1DFC|!addr
としておけばよし
絶対ロングアドレス(3バイト指定)
RAMの場合、LDA $7E0100
等と書いてたものは、LDA $000100|!BankA
としておけばよし
ROMの場合、LDA $80D800
等と書いてたものは、 LDA $00D800|!BankB
もしくは LDA $00D800|!bank
としておけばよし
以下、ざっくりメモ
SA-1パッチ
SMWCにあるパッチの1つとして、SA-1 Pack(通称 SA1パッチ)があります。
これは、SMWでSA-1チップの機能を利用できるように機能拡張を行うもので、もっさり動作の軽減や、1度に使えるスプライトの上限増加等を実現することができます。
ただし、SA-1チップの制約上、従来のメモリマップでは、SNESCPUとSA-1チップとでデータのやりとりができない為、 多くのメモリのアドレスに変更が加えられています。
ただし、このメモリマップの変更については、無作為に行われているわけではなく、一定の法則に従って再配置が行われています。 詳細な内容は、SA1パッチに付属のテキストを読んでいただくのが良いかと思いますが、おおまかには、以下の通りです。
Origin SA-1
$7E0000 - $7E00FF -> $003000 - $0030FF
$7E0200 - $7E1FFF -> $400200 - $401FFF
ただし、スプライト用のメモリ等については一部この限りではありません。
また、覚えておくとよい内容として、SA1パッチを導入した場合、Dレジスタの値は、$0300になります。
その他、SA1チップからは、SNES WRAMに直接アクセスできないので、例えば $7F:8000
等にアクセスすることはできません。
(ただし、重要なものは、おおよそ代替のメモリが提供されているので、SA1パッチの付属ドキュメントを読みましょう)
ROMデータには制限なくアクセス可能なので、ROMのテーブルデータの読み出し等はSpriteToolの頃と同様に可能です。
PIXI内でのメモリの扱い
PIXIでは、上記SA1パッチのメモリマップ変更に、ASARのdefine機能を使うことで対応しています。
その内容については、PIXIに付属する、asm/sa1def.asm をご覧いただくのが良いと思います。
ROMのSA-1チップの仕様有無により、メモリアドレスの内容をアセンブル時に決定しているというわけです。
(スプライトによっては、if節を使うことで、SNESCPU もしくは SA-1 に最適な処理を選択させる、ということもしています)
PIXIにしかない仕様
SpriteToolになく、PIXIにしかない仕様として、以下があります。
- 共有ルーチン
- ExtraBytes
- PerLevelSprite
- SpriteToolにない種類のスプライト
特に、共有ルーチンに関しては、データ量の削減に非常に貢献するので、覚えておきましょう。 (SMWCにスプライトを投稿する場合、この知識は必須といって良いでしょう)
あとの2つは、この記事の趣向からはずれる気がするので、おまけ知識程度。 気になる方は、PIXIのreadme等を呼んでみましょう。
共有ルーチン
名前の通り、全てのスプライトで共通で使うようなルーチン。
GetDrawInfo や SubOffScreen 等の汎用ルーチンは、全てのスプライトでそれぞれ挿入すると、それだけでそこそこのサイズになってしまうので、 挿入は1回だけにしよう、というもの。
これは、ASARのマクロ機能により実現されており、%GetDrawInfo()
等としてマクロを呼び出すことで使用することができます。
この機能を使う場合、routines フォルダ内に、マクロと同じ名前の、処理を記述したASMファイルを用意しておく必要があります。
ExtraBytes
Lunar Magic v1.80 から追加された、スプライトに情報を追加できる仕組みです。 例えば、Lunar Magic上からスプライトの速度を決定したりといった使い方ができます。
PerLevelSprite
同じスプライト番号に、レベルごとに違ったスプライトを挿入できるものです。 例えば、1ステージしか登場しないボスキャラクター等をこれに割り当てるといった使い方ができるでしょう。
SpriteToolにない種類のスプライト
PIXIでは、普通のスプライトに加え、拡張スプライト(もしくはエキストラスプライト)と呼ばれるスプライトと、クラスタースプライトを挿入できます。
これらは、通常のスプライトとはメモリの使い方が異なります。 どういうふうに作れば良いのかは、SMW既存の処理を眺めるか、もしくはSMWCに投稿されているスプライトのソースを見て研究するのが良いでしょう。
以上おわり。
blog comments powered by Disqus