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) | 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 |
下位ビットから順番に赤、緑、青がそれぞれ5bitづつ、0~31の32段階を指定して使います。いきなりビットシフトは難しいかもしれません。白色を代入した場合の動作を見ていきましょう。
u16 color = RGB5(31,31,31);
マクロですので次のように分解されます。
u16 color = ((31)|((31)<<5)|((31)<<10));
31を2進数に変換します。windowsに標準装備されている電卓をプログラマー設定して入力してみます。
代入するとこんな感じになりました。
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製作者が書き起こしてくれた技術ドキュメントです。参考になるためチュートリアルで頻繁に引用していきます。英語ではありますけれど、慣れないといけない部分と思うのでがんばって読んでください。
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 Mode3、10BitはBG2となります。BGとは、という話はチュートリアルの後半タイルモードにて説明します。今はおまじない程度なものと考えていてください。