前回の続きです。
C言語でスーファミ用のソフト開発(2)Hello World - takuya matsubara blog
前回はhello_worldを改造して、オリジナルのフォントで表示しましたが、色を3色しか使っていません(透明色・白色・灰色)。せっかく16色のBG画面なのに、もったいないです。
そこで、16色のBG1を使わず、4色のBG3にテキストを表示することにします。
BG3を他よりも手前に表示するには、次のようにコードを書き換えます。
setMode(BG_MODE1, 0);
↓
setMode(BG_MODE1, BG3_MODE1_PRIORITY_HIGH);
makefile内の画像変換も16色→4色に変えます。
$(GFXCONV) -s 8 -o 16 -u 16 -p -e 0 -t bmp -i $<↓
$(GFXCONV) -s 8 -o 4 -u 4 -p -e 0 -t bmp -i $<
使い方については、ここに書いてあります。
https://github.com/alekmaul/pvsneslib/blob/master/tools/gfx4snes/readme.md
関数のBG番号を全部書き換えて、表示してみた結果がこちら。
パレットがおかしいです。
setPaletteColor関数を使って8,9,10番目のカラーを変更すると、うまく表示されましたが、バグなのか仕様なのかわかりません。console系関数は16色専用で、4色は非対応な気がします。
そこで、console系関数を使わず、直接VRAMに書き込むことにしました。
// BG3に文字表示
void bg3print(u8 x, u8 y, u8 *ptr)
{
u16 vramaddr;
u16 length=0;
u8 *dst;
dst = (u8 *)vramwork;
// タイルマップに変換
while(*ptr != 0){
*dst++ = *ptr++ - 0x20;
*dst++ = (1 << 5)+(PAL_TXT << 2);
// priority bit + palette
length += 2;
}
vramaddr = VRAM_TXTMAP+(32*y)+x;
dmaCopyVram(vramwork, vramaddr, length);
}
たったこれだけのコードで済みます。一旦、タイル番号とパレットと反転情報をワークに格納して、それからdmaCopyVram関数でタイルマップに書き込んでいます。dmaCopyVramはVブランク中にDMA転送をやってくれるという便利な関数です。タイルマップの書き換えだけじゃなくて、パターンの書き換えにも使えます。
以上で、BG1が空いたので、何か表示してみます。
BG1に表示したい画像を用意します。
お絵描きソフトを使い、この画像を256×224ピクセルに縮小して、さらに16色に減色。16色のbmpファイルで保存します。
ファイル名を「resource_bg.bmp」とした場合、makefileの書式はこうなります。
この時点でパレット番号を決定している必要があります。この画像はパレット1に割り振ります。重複しないように、フォントはパレット0を使うことにします。
画像を変換すると、拡張子が「pic」「pal」「map」のファイルが生成されます。picがパターン、palがパレット、mapがタイルマップのバイナリファイルです。これらのバイナリデータをC言語ではグローバルな配列変数として扱います。詳しくは公式のWikiを参照してください。
https://github.com/alekmaul/pvsneslib/wiki/Backgrounds
画像の複雑さによって、パターンのサイズが変わってしまいます。そのまま変換すると、サイズが28KBになってしまいました。1枚だけなら表示可能ですが、複数枚を同時に表示したいので、もっと容量を節約することにします。
画像をアニメ調に塗りつぶすのが良い解決方法ですが、面倒なので、ここでは縮小するだけで済ませました。結果、7KBに落ちました。
まだVRAMに余裕があるので、BG2の画像も作ります。これも7KBくらいでした。こちらはパレット2を使うことにしました。
各データをVRAMに割り振ってみました。将来、スプライトを表示することを考えて、0x0000番地あたりを空けてあります。
出来上がったデモプログラムです。BG1とBG2がスクロールして、その上にBG3(テキスト)が表示されます。さすが、スーファミ。色彩が豊かです。
作ったコードはこちらです。
↓
続き