ビットマップモード1

GBAの画面の表示方法には大きく分けて2種類あります。それはビットマップモードとタイルモードです。さらにビットマップモードではMode0, 1, 2とあって、ビットマップモードではMode3, 4, 5と別れています。図にすると次のようになります。

Mode名称
0-2タイルモード
3-5ビットマップモード

まず最初はビットマップモードの3~5を練習してみましょう。

ビットマップモード

このモードはとあるメモリ領域に値を書き込むと、それがそのまま画面に反映されます。GBAの画面サイズは240x160ドットで1ドットにつき2バイトです。240x160x2の容量は76800バイト。メモリ領域(VRAM)は0x6000000番地から開始されます。

領域名称開始位置終了位置大きさ(バイト)
VRAM(Video RAM)0x60000000x6012C0076800

ドットを表示する関数をソースコードで書くと以下になります。

void Mode3PutPixel(u32 x, u32 y, u16 color)
{
	u16* ScreenBuffer     = (u16*)0x6000000;
	ScreenBuffer[y*240+x] = col;
}

引数xの幅は0~239、引数yの幅は0~159で最後の引数colorは、色(RGB)データでマクロを使って表します。

#define RGB5(r,g,b) ((r)|((g)<<5)|((b)<<10))
rgb
313131
3100
0310
0031
000
3.png

下位ビットから順番に赤、緑、青がそれぞれ5bitづつ、0~31の32段階を指定して使います。いきなりビットシフトは難しいかもしれません。白色を代入した場合の動作を見ていきましょう。

u16 color = RGB5(31,31,31);

マクロですので次のように分解されます。

u16 color = ((31)|((31)<<5)|((31)<<10));

31を2進数に変換します。windowsに標準装備されている電卓をプログラマー設定して入力してみます。

1.png

代入するとこんな感じになりました。

u16 color = ((0001 1111b)|((0001 1111b)<<5)|((0001 1111b)<<10));

次に、u16 colorは2バイトのサイズです。u8からu16に変えましょう。

u16 color = ((0000 0000 0001 1111b)        |
            ((0000 0000 0001 1111b) <<  5) | 
            ((0000 0000 0001 1111b) << 10)  );

シフトビット計算をします。

u16 color = ((0000 0000 0001 1111b) |
            ((0000 0011 1110 0000b) | 
            ((0111 1100 0000 0000b)  );

OR計算をします。

u16 color = 0111 1111 1111 1111b

というわけで結果は16進数でいう0x7fffとなりました。GBATEKでは32*32*32色で32768 colorsで表現できますよ、と書いてあります。15Bit目は使わないようですね。ちなみにGBATEKとはGBAエミュレータNO$GBA製作者が書き起こしてくれた技術ドキュメントです。参考になるためチュートリアルで頻繁に引用していきます。英語ではありますけれど、慣れないといけない部分と思うのでがんばって読んでください。

モード3でドットを描く

先ほどの関数を使ってドットを書いてみます。GBA版Hallo Worldです。

2.png
#include "lib/gba.h"

//---------------------------------------------------------------------------
void WaitForVsync(void)
{
	while(*(vu16*)0x4000006 >= 160) {};
	while(*(vu16*)0x4000006 <  160) {};
}
//---------------------------------------------------------------------------
void Mode3PutPixel(u32 x, u32 y, u16 color)
{
	u16* ScreenBuffer     = (u16*)0x6000000;
	ScreenBuffer[y*240+x] = color;
}
//---------------------------------------------------------------------------
int main(void)
{
	SetMode(MODE_3 | BG2_ENABLE);

	s32 i;

	for(i=0; i<20; i++)
	{
		Mode3PutPixel(5+i, 5+i, RGB5(31, 31, 31));
	}

	for(i=0; i<32; i++)
	{
		Mode3PutPixel(20+i*2, 50, RGB5(i, 0, 0));
		Mode3PutPixel(20+i*2, 60, RGB5(0, i, 0));
		Mode3PutPixel(20+i*2, 70, RGB5(0, 0, i));
		Mode3PutPixel(20+i*2, 80, RGB5(i, i, i));
	}


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

まず始めにグラフィックモードをmode3を設定します。

SetMode(MODE_3 | BG2_ENABLE);

グラフィックモードの設定はヘッダファイルにあるSetMode()マクロを使っています。内容を分解してみると

static inline void SetMode(int mode)	{REG_DISPCNT = mode;}

#define	REG_BASE	0x04000000
#define	REG_DISPCNT	*((vu16 *)(REG_BASE + 0x00))

*((vu16*)(0x04000000 + 0x00)) = MODE_3 | BG2_ENABLE

と同じ意味になり、0x04000000~0x04000001に値を入れることで設定をしています。GBATEKを引用します。

入っている値が0x403です。0, 1BitはBG Mode3、10BitはBG2となります。BGとは、という話はチュートリアルの後半タイルモードにて説明します。今はおまじない程度なものと考えていてください。

履歴


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