#author("2023-05-24T19:09:38+09:00","","") #author("2023-05-25T18:31:14+09:00","","") * タイルモード2 [#mef3ef53] 前回のmode0を簡単にまとめてみました。合わせてmode1、mode2も載せておきます。色々モードの紹介していきましたが、個人開発で使うのはmode0か3が主流です。あとはほとんど使っていないように思います。他は参考程度に見てください。 *** mode0 [#t450ef33] | サイズ | 256*256~512*512 | | 画面数 | 4 (BG0-3) | | 色/パレット | 16色*16パレット/256色*1パレット | | キャラクタ定義数 | 1024 | | 伸縮回転 | 不可能 | *** mode1 [#t5bcbf48] mode1には、伸縮回転可能なBG、不可能なBGの2種類があります。~ | サイズ | 256x256~512x512 | 128x128~1024x1024 | | 画面数 | 2(BG0-1) | 1(BG2) | | 色/パレット | 16色/16パレットor256色/1パレット | 256色/1パレット | | キャラクタ定義数 | 1024 | 256 | | 伸縮回転 | 不可能 | 可能 | *** mode2 [#g85b73fc] | サイズ | 128x128~1024x1024 | | 画面数 | 2(BG2-3) | | 色/パレット | 256色*1パレット | | キャラクタ定義数 | 256 | | 伸縮回転 | 可能 | GBATEKは次のように書かれています。こちらの方がわかりやすいかもしれません。 The table summarizes the facilities of the separate BG modes (video modes). Mode Rot/Scal Layers Size Tiles Colors Features 0 No 0123 256x256..512x515 1024 16/16..256/1 SFMABP 1 Mixed 012- (BG0,BG1 as above Mode 0, BG2 as below Mode 2) 2 Yes --23 128x128..1024x1024 256 256/1 S-MABP 3 Yes --2- 240x160 1 32768 --MABP 4 Yes --2- 240x160 2 256/1 --MABP 5 Yes --2- 160x128 2 32768 --MABP ** モード0でBG0、BG1 [#d6db3825] 再度モード0にて、2つの絵をレイヤー表示してみます。まずメモリ領域(VRAM)に入るか確認をしながらやってみましょう。 - bg0kusa.png #ref(bg0kusa.png,nolink) - bg1kumo.png #ref(bg1kumo.png,nolink) 画像のサイズは(240ではなく)256x160の16色です。タイルは32x20 = 640個。640個 * 32バイト(1タイル分のバイト数) = 20480バイト(0x5000)。全く同じ重複タイルも構わず使用します。マップは256x256ドットサイズを使うので32 * 32 * 2 = 2048バイト(0x800)となります。それでは対応表にうまく収まるよう、領域を確保してみます。 画像のサイズは(240ではなく)256x160の16色です。タイルは32x20 = 640個。640個 * 32バイト(1タイル分のバイト数) = 20480バイト(0x5000)。同じ重複タイルも構わず使用します。マップは256x256ドットサイズを使うので32 * 32 * 2 = 2048バイト(0x800)となります。それでは対応表にうまく収まるよう、領域を確保してみます。 - 対応表 | アドレス | マップ | キャラクタ | 確保 | | 0x6000000 | 0 | 0 | bg0(kusa) | | 0x6000800 | 1 | 0 | bg0(kusa) | | 0x6001000 | 2 | 0 | bg0(kusa) | | 0x6001800 | 3 | 0 | bg0(kusa) | | 0x6002000 | 4 | 0 | bg0(kusa) | | 0x6002800 | 5 | 0 | bg0(kusa) | | 0x6003000 | 6 | 0 | bg0(kusa) | | 0x6003800 | 7 | 0 | bg0(kusa) | | 0x6004000 | 8 | 1 | bg0(kusa) | | 0x6004800 | 9 | 1 | bg0(kusa) | | 0x6005000 | 10 | 1 | | | 0x6005800 | 11 | 1 | bg0 map | | 0x6006000 | 12 | 1 | bg1 map | | 0x6006800 | 13 | 1 | | | 0x6007000 | 14 | 1 | | | 0x6007800 | 15 | 1 | | | 0x6008000 | 16 | 2 | bg1(kumo) | | 0x6008800 | 17 | 2 | bg1(kumo) | | 0x6009000 | 18 | 2 | bg1(kumo) | | 0x6009800 | 19 | 2 | bg1(kumo) | | 0x600A000 | 20 | 2 | bg1(kumo) | | 0x600A800 | 21 | 2 | bg1(kumo) | | 0x600B000 | 22 | 2 | bg1(kumo) | | 0x600B800 | 23 | 2 | bg1(kumo) | | 0x600C000 | 24 | 3 | bg1(kumo) | | 0x600C800 | 25 | 3 | bg1(kumo) | | 0x600D000 | 26 | 3 | | | 0x600D800 | 27 | 3 | | | 0x600E000 | 28 | 3 | | | 0x600E800 | 29 | 3 | | | 0x600F000 | 30 | 3 | | | 0x600F800 | 31 | 3 | | うまく収まりましたね。レイヤー表示は上層がbg0、下層はbg3です。逆にすると当然、kusaタイルは表示されません。 ** サンプルコード [#yfa302ad] #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 }; vs32 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_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) { vu32 i; for(i=0; i<size; i++) { Bg[bg].tileBaseAdr[i] = pDat[i]; } } //--------------------------------------------------------------------------- void BgSetPal(u32 pal, u16* pDat) { vu32 i; for(i=0; i<16; i++) { BG_PALETTE[pal*16+i] |= pDat[i]; } } //--------------------------------------------------------------------------- void BgSetMap(void) { vu32 i; for(i=0; i<32*20; i++) { Bg[0].mapBaseAdr[i] = i; Bg[1].mapBaseAdr[i] = i | (1 << 12); // バレット番号1を選択 } } //--------------------------------------------------------------------------- int main(void) { BgInit(); BgSetTile(0, (u16*)&bg0kusaTiles, bg0kusaTilesLen/2); BgSetTile(1, (u16*)&bg1kumoTiles, bg1kumoTilesLen/2); BgSetPal(0, (u16*)&bg0kusaPal); BgSetPal(1, (u16*)&bg1kumoPal); BgSetMap(); for(;;) { WaitForVsync(); } } *** 動作画面 [#wf86950d] #ref(1.png,nolink) ** 履歴 [#k82dbea7] - 2023/04/26 - 2014/12/27