#author("2023-05-26T18:59:09+09:00","","")
#author("2023-05-30T10:26:43+09:00","","")
* ビットマップモード1 [#s37d3144]

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

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

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

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

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

ドットを表示する関数をソースコードで書くと以下のようになります。ポインタを使ってアクセスするわけです。

 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))

| 色 |  r  |  g  |  b  |
| 白 |  31 |  31 |  31 |
| 赤 |  31 |   0 |   0 |
| 緑 |   0 |  31 |   0 |
| 青 |   0 |   0 |  31 |
| 黒 |   0 |   0 |   0 |

#ref(3.png,nolink)

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

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

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

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

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

#ref(1.png,nolink)

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

 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:https://problemkaputt.de/gbatek.htm]]とはGBAエミュレータNO$GBA製作者が書き起こしてくれた技術ドキュメントです。とても参考になるためチュートリアルで頻繁に引用させて頂いてます。英語ではありますけれど、ココは慣れないといけない部分と思うので軽く読んでみてください。

- LCD VRAM Bitmap BG Modes

 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でドットを描く [#g30f34b7]

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

#ref(2.png,nolink)

 #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に設定します。
始めにグラフィックモードを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に値を入れることで設定を行います。

- 4000000h - DISPCNT - LCD Control (Read/Write)
   Bit   Expl.
   0-2   BG Mode                (0-5=Video Mode 0-5, 6-7=Prohibited)
   3     Reserved / CGB Mode    (0=GBA, 1=CGB; can be set only by BIOS opcodes)
   4     Display Frame Select   (0-1=Frame 0-1) (for BG Modes 4,5 only)
   5     H-Blank Interval Free  (1=Allow access to OAM during H-Blank)
   6     OBJ Character VRAM Mapping (0=Two dimensional, 1=One dimensional)
   7     Forced Blank           (1=Allow FAST access to VRAM,Palette,OAM)
   8     Screen Display BG0  (0=Off, 1=On)
   9     Screen Display BG1  (0=Off, 1=On)
   10    Screen Display BG2  (0=Off, 1=On)
   11    Screen Display BG3  (0=Off, 1=On)
   12    Screen Display OBJ  (0=Off, 1=On)
   13    Window 0 Display Flag   (0=Off, 1=On)
   14    Window 1 Display Flag   (0=Off, 1=On)
   15    OBJ Window Display Flag (0=Off, 1=On)

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

** 履歴 [#h46dccbb]
- 2023/04/20
- 2014/12/21

トップ   差分 履歴 リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS