ビットマップモード1

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

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

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

ビットマップモード

このモードはとあるメモリ領域に値を書き込むと、それがそのまま画面に反映されます。GBAの画面サイズは240x160ドットで、1ドットにつき2バイトです。メモリ領域(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で表現できますよ、と書いてあります。ちなみにGBATEKとはGBAエミュレータNO$GBA製作者が書き起こしてくれた技術ドキュメントです。とても参考になるためチュートリアルで頻繁に引用させて頂いてます。英語ではありますけれど、ココは慣れないといけない部分と思うので軽く読んでみてください。

BG Mode 3 - 240x160 pixels, 32768 colors
Two bytes are associated to each pixel, directly defining one of the 32768 colors
(without using palette data, and thus not supporting a 'transparent' BG color).

  Bit   Expl.
  0-4   Red Intensity   (0-31)
  5-9   Green Intensity (0-31)
  10-14 Blue Intensity  (0-31)
  15    Not used in GBA Mode (in NDS Mode: Alpha=0=Transparent, Alpha=1=Normal)

モード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);

グラフィックモードの設定はヘッダファイル(lib/gba.h)にある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

と同じ意味になり、u16単位で0x04000000に値を入れることで設定を行います。

入っている値は0x403です。0,1BitはBG Mode3、10BitはBG2となります。BGとは画面のことです。チュートリアルの後半、タイルモードにて詳しく説明します。今はBG2の画面を使っていると考えてください。

履歴


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