GBA的VRAM中有數塊特殊的區域用來描述在一個BG中如何排列tile,我們將其稱呼為BG map memory,本文將會詳細說明其格式與特點
Map data format
Map data內部紀錄了渲染一塊tile所需要知道的資訊,其格式根據BG為Text或者Affine會有所不同:
Text BG
欄位功能描述如下:
- Character name
- 雖然叫做name,但實際上是一個offset,當你從BG_CNT上計算出tile block base之後,假設BG_CNT上標明這是一個4bpp tile,則此map data所對應的tile data的address為:
- base block addr + chara. name * 0x20(4bpp的一個完整tile size)
- 假若是8bpp,則tile data會位於
- base block addr + chara. name * 0x40(8bpp的一個完整tile size)
- 有關tile data詳見GBA圖形處理邏輯模擬 - Tile format
- Character name
Affine BG
對,沒錯,真的就只有Character name,Affine BG的tile是強制256色的,考慮到Affine BG是利用仿射矩陣直接將screen pixel映射到map memory上,這樣的設計是最合理的
- 因為tile一定是0x40,所以tile data的位置算法就是8bpp算法
Horizontal flip flag
- 此tile在渲染時是否要左右顛倒,我這裡是直接將讀出來的tile data做inverse
- 考慮tile是4bpp的情況
1
2
3
4
5
6
7
8
9
10
11
12
13if (xInverse) {
// Swap the nibbles of each byte.
buf = (buf & 0x0F0F0F0F) << 4
| (buf & 0xF0F0F0F0) >> 4;
// Swap the bytes of each byte pair.
buf = (buf & 0x00FF00FF) << 8
| (buf & 0xFF00FF00) >> 8;
// Swap the byte pairs.
buf = (buf & 0x0000FFFF) << 16
| (buf & 0xFFFF0000) >> 16;
} // if - 8bpp會比較簡單
1
2
3
4
5
6
7
8
9if (xInverse) {
// Swap the bytes of each byte pair.
buf = (buf & 0x00FF00FF) << 8
| (buf & 0xFF00FF00) >> 8;
// Swap the byte pairs.
buf = (buf & 0x0000FFFF) << 16
| (buf & 0xFFFF0000) >> 16;
} // if
Vertical flip flag
- 此tile在渲染時是否要上下顛倒
Color palette
- 如果BG_CNT有聲明是4bpp,則最後tile在繪製時所參考的palette number就會是這個欄位所描述的
- 你可以把此欄位理解成row number,假設palette number是4,那tile就會變成全黑(因為tile 4所有16色都是黑色)
Virtual screen
Map memory基本上就是一塊由map data以二維排列而成的記憶體區塊,我們可以回顧一下這張表格:
其中我們可以注意到Character format BG screen下有一個size的欄位,裏頭描述幾種螢幕大小組合,但可以確定的是都與我們所知道的GBA螢幕大小240*160不同
這就是所謂的Virtual screen機制,我們可以把他想像成我們利用一個240*160的取景視窗,在一個很大的虛構區域內移動,接下來我們要來討論兩個重點:
- 虛構區域的大小
- 我們能夠移動的虛構區域大小是依靠BG_CNT中的Screen size控制的,其大小如下表所述:
- 圖表中明確提到了Text/Affine的狀態下,map data的尺寸與記憶體占用皆不同
- 如何移動可視範圍
我們在確認Virtual screen的大小後,下一步自然就是要把取景範圍移動到我們想要的地方,這一個步驟在Text BG與Affine BG下的操作方式並不相同:
- Text BG: 我們需要調整HOFS以及VOFS兩個register來移動取景範圍的左上角座標,如果這兩個暫存器的數值超過的virtual screen的尺寸的話,真正對應到的數值將會被 %screen size
不同的Screen size,移動時看起來會像是這樣
- Affine BG:Affine模式下是直接依靠仿射矩陣來決定每一個螢幕上的pixel對應到的tile data,因此並不需要依靠HOFS以及VOFS,詳細請見GBA圖形處理邏輯模擬 - Affine background
Address formula
最後附上一個Text BG計算某一個screen pixel,其所在的tile對應到那一個map data的計算公式:
- Physical screen X, Y = Sx, Sy
- Virtual Screen Width, Height = Vw, Vh
- Viewing area X = (Sx + HOFS) % Vw = S_vx, Viewing area Y = (Sy + VOFS) % Vh = S_vy
- Screen Base Block in BG_CNT = Sb
- map data address = 0x0600'0000 + (0x800 * Sb) + {((Vw / 8)*(S_vy /
8)) + (S_vx / 8)} * 2
- 每一個tile為8*8,所以S_v(x|y) / 8是為了把pixel XY轉換為tile XY
- 最後*2是因為Text BG每一個map data為2 bytes