- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2023-04-30T22:11:42+09:00","","")
#author("2023-04-30T22:42:29+09:00","","")
* ウィンドウ [#d3110733]
ウィンドウ機能は、画面の一定の領域を指定し、その内部と外部で各BG面やスプライトなどを表示するか表示しないかを指定する機能です。ウィンドウは2つまで個別に設定できます。利用する手順としては、SetMode()で使用するウィンドウを指定します。そして使用するウィンドウについてウィンドウの範囲と、内部と外部に表示するものを設定します。~
ウィンドウ機能は、画面の一定の領域を指定し、その内部と外部で各BG面やスプライトなどを表示するか表示しないかを指定する機能です。ウィンドウは2つまで個別に設定できます。利用する手順としては、REG_DISPCNTで使用するウィンドウを指定します。そして使用するウィンドウについてウィンドウの範囲と、内部と外部に表示するものを設定します。~
** DISPCNT [#tabf5820]
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.
** WIN0H, WIN1H [#qf3c56dd]
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.
** WIN0V, WIN1V [#w42fe6ac]
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.
** WININ [#j305cc91]
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
** WINOUT [#c6830243]
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
** I/Oアドレス [#i281b1de]
#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やスプライトを表示します。~
** ウィンドウを使用した例 [#l46d1f73]
#include "lib/gba.h"
#include "res.h"
#include "bg.h"
#include "irq.arm.h"
#include "key.h"
#define BG_MAX_CNT 4
typedef struct {
u32 mapBase;
u16* mapBaseAdr;
u32 tileBase;
u16* tileBaseAdr;
} ST_BG;
//---------------------------------------------------------------------------
ST_BG Bg[BG_MAX_CNT];
//---------------------------------------------------------------------------
void WaitForVsync(void)
{
while(*(vu16*)0x4000006 >= 160) {};
while(*(vu16*)0x4000006 < 160) {};
}
//---------------------------------------------------------------------------
void BgInitMem(void)
{
const u32 mapBase[] = { 11, 12, 0, 0 };
const u32 tileBase[] = { 0, 2, 0, 0 };
s32 i;
for(i=0; i<BG_MAX_CNT; i++)
{
Bg[i].mapBase = MAP_BASE(mapBase[i]);
Bg[i].mapBaseAdr = MAP_BASE_ADR(mapBase[i]);
Bg[i].tileBase = TILE_BASE(tileBase[i]);
Bg[i].tileBaseAdr = TILE_BASE_ADR(tileBase[i]);
}
for(i=0; i<32*32; i++)
{
Bg[0].mapBaseAdr[i] = 0;
Bg[1].mapBaseAdr[i] = 0;
Bg[2].mapBaseAdr[i] = 0;
Bg[3].mapBaseAdr[i] = 0;
}
for(i=0; i<0x2000; i++)
{
Bg[0].tileBaseAdr[i] = 0;
Bg[1].tileBaseAdr[i] = 0;
Bg[2].tileBaseAdr[i] = 0;
Bg[3].tileBaseAdr[i] = 0;
}
}
//---------------------------------------------------------------------------
void BgInit(void)
{
BgInitMem();
REG_DISPCNT = (MODE_0 | BG0_ON | BG1_ON | WIN0_ENABLE);
REG_BG0CNT = (BG_SIZE_0 | BG_16_COLOR | Bg[0].tileBase | Bg[0].mapBase);
REG_BG1CNT = (BG_SIZE_0 | BG_16_COLOR | Bg[1].tileBase | Bg[1].mapBase);
}
//---------------------------------------------------------------------------
void BgSetTile(u32 bg, u16* pDat, u32 size)
{
volatile u32 i;
for(i=0; i<size; i++)
{
Bg[bg].tileBaseAdr[i] = pDat[i];
}
}
//---------------------------------------------------------------------------
void BgSetPal(u32 pal, u16* pDat)
{
volatile u32 i;
for(i=0; i<16; i++)
{
BG_PALETTE[pal*16+i] |= pDat[i];
}
}
//---------------------------------------------------------------------------
void BgSetMap(void)
{
volatile u32 i;
for(i=0; i<32*20; i++)
{
Bg[0].mapBaseAdr[i] = i;
Bg[1].mapBaseAdr[i] = i | (1 << 12);
}
}
//---------------------------------------------------------------------------
int main(void)
{
REG_WSCNT = 0x4317;
BgInit();
IrqInit();
KeyInit();
BgSetTile(0, (u16*)&imageTiles, imageTilesLen/2);
BgSetTile(1, (u16*)&image2Tiles, image2TilesLen/2);
BgSetPal(0, (u16*)&imagePal);
BgSetPal(1, (u16*)&image2Pal);
BgSetMap();
// ウィンドウの中にBG1,外にBG0を表示
REG_WININ = WIN_0_BG1;
REG_WINOUT = WIN_0_BG0;
s32 ofx = 20;
s32 ofy = 20;
u16 cnt;
for(;;)
{
WaitForVsync();
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( !(REG_KEYINPUT & KEY_UP) ) ofy--;
if( !(REG_KEYINPUT & KEY_DOWN) ) ofy++;
if( !(REG_KEYINPUT & KEY_LEFT) ) ofx--;
if( !(REG_KEYINPUT & KEY_RIGHT) ) ofx++;
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;
}
}
}
*** 動作画面 [#k1733dea]
#ref(clip_1.png,nolink)
上記のコードにはないですが、bg.c内で一つ目のウィンドウを表示するようにします。
REG_DISPCNT = (MODE_0 | BG0_ON | BG1_ON | WIN0_ENABLE);
上記のコードにて、一つ目のウィンドウの内部にBG0、外部にBG1を表示する設定にします。
REG_WININ = WIN_0_BG1;
REG_WINOUT = WIN_0_BG0;
*** 動作画面 [#k1733dea]
-[[github:https://github.com/akkera102/gbadev-ja/tree/main/tut15%20%E3%82%A6%E3%82%A3%E3%83%B3%E3%83%89%E3%82%A6]]
#ref(1.png,nolink)
** 履歴 [#h7fc0fad]
- 2014/12/30
- 2023/04/30
- 2007/09/06