タイルモード2

前回のmode0を簡単にまとめてみました。合わせてmode1、mode2も載せておきます。色々モードの紹介していきましたが、個人開発で使うのはmode0か3が主流です。あとはほとんど使っていないように思います。他は参考程度に見てください。

mode1には、伸縮回転可能なBG、不可能なBGの2種類があります。

GBATEKは次のように書かれています。こちらの方がわかりやすいかもしれません。

The table summarizes the facilities of the separate BG modes (video modes).

  Mode  Rot/Scal Layers Size               Tiles Colors       Features
  0     No       0123   256x256..512x515   1024  16/16..256/1 SFMABP
  1     Mixed    012-   (BG0,BG1 as above Mode 0, BG2 as below Mode 2)
  2     Yes      --23   128x128..1024x1024 256   256/1        S-MABP
  3     Yes      --2-   240x160            1     32768        --MABP
  4     Yes      --2-   240x160            2     256/1        --MABP
  5     Yes      --2-   160x128            2     32768        --MABP

モード0でBG0、BG1

再度モード0にて、2つの絵をレイヤー表示してみます。メモリ領域(VRAM)に入るか確認をしながらやってみましょう。

画像のサイズは(240ではなく)256x160の16色です。
タイルは32x20 = 640個。640個 * 32バイト(1タイル分のバイト数) = 20480バイト(0x5000)。
色が全く同じの重複タイルも構わず使用します。

マップは256x256ドットサイズを使うので32 * 32 * 2 = 2048バイト(0x800)となります。
それでは対応表にうまく収まるよう、領域を確保してみます。

うまく収まりましたね。レイヤー表示は上層がbg0、下層はbg3です。
逆にすると当然、kusaタイルは表示されません。

#include "lib/gba.h"
#include "res.h"

#define BG_MAX_CNT 4

typedef struct {
	u32  mapBase;
	u16* mapBaseAdr;
	u32  tileBase;
	u16* tileBaseAdr;
} ST_BG;

//---------------------------------------------------------------------------
ST_BG Bg[BG_MAX_CNT];

//---------------------------------------------------------------------------
void WaitForVsync(void)
{
	while(*(vu16*)0x4000006 >= 160) {};
	while(*(vu16*)0x4000006 <  160) {};
}
//---------------------------------------------------------------------------
void BgInitMem(void)
{
	const u32 mapBase[]  = { 11, 12,  0,  0 };
	const u32 tileBase[] = {  0,  2,  0,  0 };
	s32 i;

	for(i=0; i<BG_MAX_CNT; i++)
	{
		Bg[i].mapBase     = MAP_BASE(mapBase[i]);
		Bg[i].mapBaseAdr  = MAP_BASE_ADR(mapBase[i]);
		Bg[i].tileBase    = TILE_BASE(tileBase[i]);
		Bg[i].tileBaseAdr = TILE_BASE_ADR(tileBase[i]);
	}

	for(i=0; i<32*32; i++)
	{
		Bg[0].mapBaseAdr[i] = 0;
		Bg[1].mapBaseAdr[i] = 0;
		Bg[2].mapBaseAdr[i] = 0;
		Bg[3].mapBaseAdr[i] = 0;
	}

	for(i=0; i<0x2000; i++)
	{
		Bg[0].tileBaseAdr[i] = 0;
		Bg[1].tileBaseAdr[i] = 0;
		Bg[2].tileBaseAdr[i] = 0;
		Bg[3].tileBaseAdr[i] = 0;
	}
}
//---------------------------------------------------------------------------
void BgInit(void)
{
	BgInitMem();

	REG_DISPCNT = (MODE_0 | BG0_ON | BG1_ON);

	REG_BG0CNT = (BG_SIZE_0 | BG_16_COLOR | Bg[0].tileBase | Bg[0].mapBase);
	REG_BG1CNT = (BG_SIZE_0 | BG_16_COLOR | Bg[1].tileBase | Bg[1].mapBase);
}
//---------------------------------------------------------------------------
void BgSetTile(u32 bg, u16* pDat, u32 size)
{
	volatile u32 i;

	for(i=0; i<size; i++)
	{
		Bg[bg].tileBaseAdr[i] = pDat[i];
	}
}
//---------------------------------------------------------------------------
void BgSetPal(u32 pal, u16* pDat)
{
	volatile u32 i;

	for(i=0; i<16; i++)
	{
		BG_PALETTE[pal*16+i] |= pDat[i];
	}
}
//---------------------------------------------------------------------------
void BgSetMap(void)
{
	volatile u32 i;

	for(i=0; i<32*20; i++)
	{
		Bg[0].mapBaseAdr[i] = i;
		Bg[1].mapBaseAdr[i] = i | (1 << 12);
	}
}
//---------------------------------------------------------------------------
int main(void)
{
	BgInit();

	BgSetTile(0, (u16*)&bg0kusaTiles, bg0kusaTilesLen/2);
	BgSetTile(1, (u16*)&bg1kumoTiles, bg1kumoTilesLen/2);

	BgSetPal(0, (u16*)&bg0kusaPal);
	BgSetPal(1, (u16*)&bg1kumoPal);

	BgSetMap();

	for(;;)
	{
		WaitForVsync();
	}
}

動作画面

#ref(): File not found: "clip_1.png" at page "tutorial.11"

履歴


トップ   一覧 検索 最終更新   ヘルプ   最終更新のRSS