前回のmode0を簡単にまとめてみました。合わせてmode1、mode2も載せておきます。色々モードの紹介していきましたが、個人開発で使うのはmode0か3が主流です。あとはほとんど使っていないように思います。他は参考程度に見てください。
| サイズ | 256*256~512*512 | 
| 画面数 | 4 (BG0-3) | 
| 色/パレット | 16色*16パレット/256色*1パレット | 
| キャラクタ定義数 | 1024 | 
| 伸縮回転 | 不可能 | 
| サイズ | 256x256~512x512 | 128x128~1024x1024 | 
| 画面数 | 2(BG0-1) | 1(BG2) | 
| 色/パレット | 16色/16パレットor256色/1パレット | 256色/1パレット | 
| キャラクタ定義数 | 1024 | 256 | 
| 伸縮回転 | 不可能 | 可能 | 
mode1には、伸縮回転可能なBG、不可能なBGの2種類があります。
| サイズ | 128x128~1024x1024 | 
| 画面数 | 2(BG2-3) | 
| 色/パレット | 256色*1パレット | 
| キャラクタ定義数 | 256 | 
| 伸縮回転 | 可能 | 
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にて、2つの絵をレイヤー表示してみます。メモリ領域(VRAM)に入るか確認をしながらやってみましょう。
#ref(): File not found: "clip_2.png" at page "tutorial.11"
#ref(): File not found: "clip_3.png" at page "tutorial.11"
画像のサイズは(240ではなく)256x160の16色です。
タイルは32x20 = 640個。640個 * 32バイト(1タイル分のバイト数) = 20480バイト(0x5000)。
色が全く同じの重複タイルも構わず使用します。
マップは256x256ドットサイズを使うので32 * 32 * 2 = 2048バイト(0x800)となります。
それでは対応表にうまく収まるよう、領域を確保してみます。
| アドレス | マップ | キャラクタ | 確保 | 
| 0x6000000 | 0 | 0 | bg0(kusa) | 
| 0x6000800 | 1 | 0 | bg0(kusa) | 
| 0x6001000 | 2 | 0 | bg0(kusa) | 
| 0x6001800 | 3 | 0 | bg0(kusa) | 
| 0x6002000 | 4 | 0 | bg0(kusa) | 
| 0x6002800 | 5 | 0 | bg0(kusa) | 
| 0x6003000 | 6 | 0 | bg0(kusa) | 
| 0x6003800 | 7 | 0 | bg0(kusa) | 
| 0x6004000 | 8 | 1 | bg0(kusa) | 
| 0x6004800 | 9 | 1 | bg0(kusa) | 
| 0x6005000 | 10 | 1 | |
| 0x6005800 | 11 | 1 | bg0 map | 
| 0x6006000 | 12 | 1 | bg1 map | 
| 0x6006800 | 13 | 1 | |
| 0x6007000 | 14 | 1 | |
| 0x6007800 | 15 | 1 | |
| 0x6008000 | 16 | 2 | bg1(kumo) | 
| 0x6008800 | 17 | 2 | bg1(kumo) | 
| 0x6009000 | 18 | 2 | bg1(kumo) | 
| 0x6009800 | 19 | 2 | bg1(kumo) | 
| 0x600A000 | 20 | 2 | bg1(kumo) | 
| 0x600A800 | 21 | 2 | bg1(kumo) | 
| 0x600B000 | 22 | 2 | bg1(kumo) | 
| 0x600B800 | 23 | 2 | bg1(kumo) | 
| 0x600C000 | 24 | 3 | bg1(kumo) | 
| 0x600C800 | 25 | 3 | bg1(kumo) | 
| 0x600D000 | 26 | 3 | |
| 0x600D800 | 27 | 3 | |
| 0x600E000 | 28 | 3 | |
| 0x600E800 | 29 | 3 | |
| 0x600F000 | 30 | 3 | |
| 0x600F800 | 31 | 3 | 
うまく収まりましたね。レイヤー表示は上層が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"