ブレンドはBGやスプライトから2つのグループを選択し、一定の割合で色を混ぜて表示するアルファブレンドと、白か黒を一定の割合で混ぜて表示するフェードがあります。
#define REG_BLDCNT *((vu16 *)(REG_BASE + 0x50)) #define BLEND_TOP_BG0 (1<<0) //TOP #define BLEND_TOP_BG1 (1<<1) #define BLEND_TOP_BG2 (1<<2) #define BLEND_TOP_BG3 (1<<3) #define BLEND_TOP_OBJ (1<<4) #define BLEND_TOP_BD (1<<5) #define BLEND_LOW_BG0 (1<<8) //LOW #define BLEND_LOW_BG1 (1<<9) #define BLEND_LOW_BG2 (1<<10) #define BLEND_LOW_BG3 (1<<11) #define BLEND_LOW_OBJ (1<<12) #define BLEND_LOW_BD (1<<13) #define BLEND_MODE_OFF (0<<6) //MODE #define BLEND_MODE_ALPHA (1<<6) #define BLEND_MODE_LIGHT (2<<6) #define BLEND_MODE_DARK (3<<6)
一番目のグループと二番目のグループに、どのBGやスプライトを割り当てるかの設定を行います。TOPのほうは一番目のグループに、LOWのほうは二番目のグループに割り当てます。両方のグループに同じものを割り当てることも可能です。BG0-BG3はその番号のBG、OBJはスプライトすべて、BDは背景(詳細は不明)です。フェードモードのときはTOPに設定したものだけが対象になります。スプライトはスプライト同士の色の混ぜ合わせは行われないようです。
MODEはブレンドの種類です。OFFは何もしません。
#define REG_BLDALPHA *((vu16 *)(REG_BASE + 0x52)) #define BLEND_LOW(n) ((n)<<0) #define BLEND_HIGH(n) ((n)<<8) #define BLEND_LEVEL(n) (BLEND_LOW(n) | BLEND_HIGH(n)) #define BLEND_BALANCE(n) (BLEND_LOW(n) | BLEND_HIGH(16-n))
アルファブレンドを選んだ場合のそれぞれのグループの色を混ぜる割合です。LOWが2番目のグループ、HIGHが1番目のグループの割合になります。数値は0-16が設定できます。
0が全くそのグループの色を発色せず、数値が大きくなるとその色が濃くなりますが、16が最高の割合で、それ以上の数値になっても変化しません。LEVELは2つのグループの発色を同じにします。BALANCEは2つのグループの値の合計が16(100%)になるようにします。
#define REG_BLDY *((vu16 *)(REG_BASE + 0x54)) #define BLEND_DEPTH(n) ((n)<<0)
こちらはフェードを選んだ場合の黒または白と混ぜ合わせる割合となります。値は0が元の画像と同じ、16が最高(真っ黒または真っ白)で、それ以上は変化なしです。
#include "lib/gba.h" #include "res.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; REG_BLDCNT = BLEND_TOP_BG0 | BLEND_LOW_BG1 | BLEND_MODE_ALPHA ; 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) { BgInit(); BgSetTile(0, (u16*)&imageTiles, imageTilesLen/2); BgSetTile(1, (u16*)&image2Tiles, image2TilesLen/2); BgSetPal(0, (u16*)&imagePal); BgSetPal(1, (u16*)&image2Pal); BgSetMap(); s16 vcnt = 10; for(;;) { WaitForVsync(); REG_BLDALPHA = BLEND_BALANCE(vcnt); if( !(REG_KEYINPUT & KEY_UP) ) vcnt--; if( !(REG_KEYINPUT & KEY_DOWN) ) vcnt++; if(vcnt < 0) vcnt = 0; if(vcnt > 16) vcnt = 16; } }