GBAの画面の表示方法には大きく分けて2種類あります。それはビットマップモードとタイルモードです。さらにビットマップモードではMode0, 1, 2とあってビットマップモードではMode3, 4, 5と別れています。図にすると次のようなものです。
Mode | 名称 |
0-2 | タイルモード |
3-5 | ビットマップモード |
まず最初はビットマップモードの3~5を練習してみましょう。
このモードはとあるメモリ領域に値を書き込むと、それがそのまま画面に反映されます。C言語ではint変数に123を代入するとき「int abc = 123;」という書き方をしますが、123が色データの役割を持ち、abcはメモリ領域(そのまま画面に反映されるもの)だ、と思ってください。GBAの画面サイズは240x160ドットです。1ドットにつき2バイトで表現します。240x160x2バイトなので容量は76800バイト。メモリ領域(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~240、引数yの幅は0~160。それ以上の値を放り込むと簡単に壊れてしまう関数ではあります。最後の引数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 |
下位ビットから順番に赤、緑、青がそれぞれ5bitづつ、0~31の32段階を指定して使います。いきなりビットシフトは難しいかもしれません。そこで白色を代入した場合のプログラム的な動きを見ていきましょう。
u16 color = RGB5(31,31,31);
マクロですので次のように分解されます。
u16 color = ((31)|((31)<<5)|((31)<<10));
31とは2進数でいくつでしょうか。windowsに標準装備されている電卓をプログラマー設定して入力してみます。
2進数表現を入れてみます。
u16 color = ((0001 1111b)|((0001 1111b)<<5)|((0001 1111b)<<10));
値はu16単位。つまり2バイト16bitです。拡張します。
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目は使わないようですね。
In BG Modes 3-5 the background is defined in form of a bitmap (unlike as for Tile/Map based BG modes). Bitmaps are implemented as BG2, with Rotation/Scaling support. As bitmap modes are occupying 80KBytes of BG memory, only 16KBytes of VRAM can be used for OBJ tiles. 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)
先ほどの関数を使ってドットを書いてみます。GBA版Hallo Worldです。
#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を引用します。
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 Modeは3、10BitのBG2となります。BGはチュートリアルの後半タイルモードにて説明します。今はおまじない程度なものと考えていてください。