- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2023-05-15T09:27:35+09:00;2023-04-22T17:11:08+09:00","","")
#author("2023-05-24T16:16:32+09:00","","")
* ビットマップモード1 [#s37d3144]
GBAの画面の表示方法には大きく分けて2種類あります。それはビットマップモードとタイルモードです。さらにビットマップモードではMode0, 1, 2とあってビットマップモードではMode3, 4, 5と別れています。図にすると次のようになります。
GBAの画面の表示方法には大きく分けて2種類あります。それはビットマップモードとタイルモードです。さらにビットマップモードではMode0, 1, 2とあって、ビットマップモードではMode3, 4, 5と別れています。図にすると次のようになります。
| Mode | 名称 |
| 0-2 | タイルモード |
| 3-5 | ビットマップモード |
まず最初はビットマップモードの3~5を練習してみましょう。
** ビットマップモード [#z9cbb8fc]
このモードはとあるメモリ領域に値を書き込むと、それがそのまま画面に反映されます。C言語ではint変数に123を代入するとき「int abc = 123;」という書き方をしますが、123が色データの役割を持ち、abcはメモリ領域(そのまま画面に反映されるもの)だ、と思ってください。GBAの画面サイズは240x160ドットです。1ドットにつき2バイトで表現します。240x160x2バイトなので容量は76800バイト。メモリ領域(VRAM)は、0x6000000番地から開始されます。
このモードはとあるメモリ領域に値を書き込むと、それがそのまま画面に反映されます。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)データでマクロを使って表します。
引数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段階を指定して使います。いきなりビットシフトは難しいかもしれません。白色を代入した場合のプログラム的な動きを見ていきましょう。
下位ビットから順番に赤、緑、青がそれぞれ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)
このことから2進数表現を入れてみます。
代入するとこんな感じになりました。
u16 color = ((0001 1111b)|((0001 1111b)<<5)|((0001 1111b)<<10));
値はu16単位。つまり2バイト16bitです。
次に、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目は使わないようですね。
というわけで結果は16進数でいう0x7fffとなりました。GBATEKでは32*32*32色で32768 colorsで表現できますよ、と書いてあります。15Bit目は使わないようですね。ちなみに[[GBATEK:https://problemkaputt.de/gbatek.htm]]とはGBAエミュレータNO$GBA製作者が書き起こしてくれた技術ドキュメントです。参考になるためチュートリアルで頻繁に引用していきます。英語ではありますけれど、慣れないといけない部分と思うのでがんばって読んでください。
- LCD VRAM Bitmap BG Modes
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)
** モード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を設定します。
SetMode(MODE_3 | BG2_ENABLE);
グラフィックモードの設定はヘッダファイルにあるSetMode()マクロを使っています。内容を分解してみると
- gba.h
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を引用します。
- 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とは、という話はチュートリアルの後半タイルモードにて説明します。今はおまじない程度なものと考えていてください。
** 履歴 [#h46dccbb]
- 2023/04/20
- 2014/12/21