ウィンドウ機能は、画面の一定の領域を指定し、その内部と外部で各BG面やスプライトなどを表示するか表示しないかを指定する機能です。ウィンドウは2つまで個別に設定できます。利用する手順としては、まずREG_DISPCNTで使用するウィンドウを指定します。使用するウィンドウについてはウィンドウの範囲と、内部と外部に表示するものを設定します。
The DISPCNT Register DISPCNT Bits 13-15 are used to enable Window 0, Window 1, and/or OBJ Window regions, if any of these regions is enabled then the "Outside of Windows" region is automatically enabled, too. DISPCNT Bits 8-12 are kept used as master enable bits for the BG0-3,OBJ layers, a layer is displayed only if both DISPCNT and WININ/OUT enable bits are set.
4000040h - WIN0H - Window 0 Horizontal Dimensions (W) 4000042h - WIN1H - Window 1 Horizontal Dimensions (W) Bit Expl. 0-7 X2, Rightmost coordinate of window, plus 1 8-15 X1, Leftmost coordinate of window Garbage values of X2>240 or X1>X2 are interpreted as X2=240.
4000044h - WIN0V - Window 0 Vertical Dimensions (W) 4000046h - WIN1V - Window 1 Vertical Dimensions (W) Bit Expl. 0-7 Y2, Bottom-most coordinate of window, plus 1 8-15 Y1, Top-most coordinate of window Garbage values of Y2>160 or Y1>Y2 are interpreted as Y2=160.
4000048h - WININ - Control of Inside of Window(s) (R/W) Bit Expl. 0-3 Window 0 BG0-BG3 Enable Bits (0=No Display, 1=Display) 4 Window 0 OBJ Enable Bit (0=No Display, 1=Display) 5 Window 0 Color Special Effect (0=Disable, 1=Enable) 6-7 Not used 8-11 Window 1 BG0-BG3 Enable Bits (0=No Display, 1=Display) 12 Window 1 OBJ Enable Bit (0=No Display, 1=Display) 13 Window 1 Color Special Effect (0=Disable, 1=Enable) 14-15 Not used
400004Ah - WINOUT - Control of Outside of Windows & Inside of OBJ Window (R/W) Bit Expl. 0-3 Outside BG0-BG3 Enable Bits (0=No Display, 1=Display) 4 Outside OBJ Enable Bit (0=No Display, 1=Display) 5 Outside Color Special Effect (0=Disable, 1=Enable) 6-7 Not used 8-11 OBJ Window BG0-BG3 Enable Bits (0=No Display, 1=Display) 12 OBJ Window OBJ Enable Bit (0=No Display, 1=Display) 13 OBJ Window Color Special Effect (0=Disable, 1=Enable) 14-15 Not used
#define REG_WIN0H *((vu16 *)(REG_BASE + 0x40)) #define REG_WIN1H *((vu16 *)(REG_BASE + 0x42)) #define REG_WIN0V *((vu16 *)(REG_BASE + 0x44)) #define REG_WIN1V *((vu16 *)(REG_BASE + 0x46)) #define REG_WININ *((vu16 *)(REG_BASE + 0x48)) #define REG_WINOUT *((vu16 *)(REG_BASE + 0x4A)) // REG_WIN0H,WIN1H #define WIN_RIGHT(x) ((x)<<0) #define WIN_LEFT(x) ((x)<<8) // REG_WIN0V,WIN1V #define WIN_DOWN(x) ((x)<<0) #define WIN_TOP(x) ((x)<<8)
ウィンドウの領域を設定するI/Oレジスタです。WIN0HとWIN0V、WIN1HとWIN1Vでそれぞれセット(対)となっています。RIGHTにウィンドウの右端、LEFTに左端、DOWNに下端、TOPに上端の位置を格納します。単位はドットです。RIGHTの値よりLEFTの値を大きくしたりすると、変わった表示になります。
// REG_WININ,WINOUT #define WIN_0_BG0 (1<<0) #define WIN_0_BG1 (1<<1) #define WIN_0_BG2 (1<<2) #define WIN_0_BG3 (1<<3) #define WIN_0_OBJ (1<<4) #define WIN_0_SPE (1<<5) #define WIN_1_BG0 (1<<8) #define WIN_1_BG1 (1<<9) #define WIN_1_BG2 (1<<10) #define WIN_1_BG3 (1<<11) #define WIN_1_OBJ (1<<12) #define WIN_1_SPE (1<<13)
ウィンドウの内部と外部にどれを表示させるかの設定です。BG0-BG3はそれぞれの番号のBGを、OBJはスプライトを、SPEは特殊効果を適用したBGやスプライトを表示します。
#include "lib/gba.h"
#include "bg.h"
#include "irq.arm.h"
#include "key.h"
//---------------------------------------------------------------------------
int main(void)
{
REG_WSCNT = 0x4317;
BgInit();
IrqInit();
KeyInit();
REG_WININ = WIN_0_BG1;
REG_WINOUT = WIN_0_BG0;
s32 ofx = 20;
s32 ofy = 20;
u16 cnt;
for(;;)
{
VBlankIntrWait();
KeyExec();
cnt = KeyGetCnt();
if(cnt & KEY_UP ) ofy--;
if(cnt & KEY_DOWN ) ofy++;
if(cnt & KEY_LEFT ) ofx--;
if(cnt & KEY_RIGHT) ofx++;
if(ofx < 0) ofx = 0;
if(ofx > 240-64) ofx = 240-64;
if(ofy < 0) ofy = 0;
if(ofy > 160-64) ofy = 160-64;
REG_WIN0H = WIN_LEFT(ofx) | WIN_RIGHT(ofx+64);
REG_WIN0V = WIN_TOP(ofy) | WIN_DOWN(ofy+64);
if(cnt & KEY_A)
{
REG_WININ = WIN_0_BG1;
REG_WINOUT = WIN_0_BG0;
}
if(cnt & KEY_B)
{
REG_WININ = WIN_0_BG0;
REG_WINOUT = WIN_0_BG1;
}
}
}
上記のコードにはないですが、bg.c内で一つ目のウィンドウを表示させています。
REG_DISPCNT = (MODE_0 | BG0_ON | BG1_ON | WIN0_ENABLE);
一つ目のウィンドウの内部にBG0、外部にBG1を表示する設定にします。BG0は縞模様、BG1はGBA文字となっています。
REG_WININ = WIN_0_BG1; REG_WINOUT = WIN_0_BG0;
基本的にウィンドウは自分で考えるより、気になる市販ゲームの動作を参考にした方がいいと思っています。どのように重ね、スライドして、優先度を高くしているのか。言い方はちょっとアレですけれど、市販ゲームは教材として最高のサンプルです。
