nds的显存用得十分出彩,一共10个bank(vram_a vram_b..vram_i),加起来有656k,可用于2个2D引擎的BG/OBJ图跟调色板的存储,以及3D引擎的纹理贴图、调色板的存储
理解显存的控制,有利于理解后面的文章,先从控制10个显存bank的I/O寄存器开始介绍
引用:
复制内容到剪贴板
代码:
4000240h - NDS9 - VRAMCNT_A - 8bit - VRAM-A (128K) Bank Control (W)
4000241h - NDS9 - VRAMCNT_B - 8bit - VRAM-B (128K) Bank Control (W)
4000242h - NDS9 - VRAMCNT_C - 8bit - VRAM-C (128K) Bank Control (W)
4000243h - NDS9 - VRAMCNT_D - 8bit - VRAM-D (128K) Bank Control (W)
4000244h - NDS9 - VRAMCNT_E - 8bit - VRAM-E (64K) Bank Control (W)
4000245h - NDS9 - VRAMCNT_F - 8bit - VRAM-F (16K) Bank Control (W)
4000246h - NDS9 - VRAMCNT_G - 8bit - VRAM-G (16K) Bank Control (W)
4000248h - NDS9 - VRAMCNT_H - 8bit - VRAM-H (32K) Bank Control (W)
4000249h - NDS9 - VRAMCNT_I - 8bit - VRAM-I (16K) Bank Control (W)
0-2 VRAM MST ;Bit2 not used by VRAM-A,B,H,I
3-4 VRAM Offset (0-3) ;Offset not used by VRAM-E,H,I
5-6 Not used
7 VRAM Enable (0=Disable, 1=Enable)
这个引用自no$gba的帮助文档gbatek
从这份资料可以看出,10个显存bank的控制由这10个I/O寄存器完成,从0x4000240到0x4000249,每个bank的大小也都清楚地标示出来了
每个I/O寄存器的设置属性都是一样的 bit0-bit2存储vram mst,bit3-bit4存储vram offset,bit5-bit6不使用,bit7标示是否启用显存的flag
当mst为0时,它有如下对应关系,依旧是引用
引用
复制内容到剪贴板
代码:
VRAM SIZE MST OFS ARM9, Plain ARM9-CPU Access (so-called LCDC mode)
A 128K 0 - 6800000h-681FFFFh
B 128K 0 - 6820000h-683FFFFh
C 128K 0 - 6840000h-685FFFFh
D 128K 0 - 6860000h-687FFFFh
E 64K 0 - 6880000h-688FFFFh
F 16K 0 - 6890000h-6893FFFh
G 16K 0 - 6894000h-6897FFFh
H 32K 0 - 6898000h-689FFFFh
I 16K 0 - 68A0000h-68A3FFFh
这个模式叫做平坦模式,SDK用LCDC模式来描述它,可以注意到当mst属性值为0时,offset属性值不起作用
SDK内对应的API为
复制内容到剪贴板
代码:
void GX_SetBankForLCDC(int lcdc);
这个函数的用法稍微讲解一下,如果你要将vram_a设置为lcdc模式,那么把1作为参数传进去就行了,vram_b就是(1<<1),以此类推,vram_i就是(1<<9)
可以通过位或运算,一次性将多个vram bank设置为lcdc模式
由于本系列教程只讲3D,2D图像部分的显存控制就跳过了,有兴趣请查gbatek
将vram_a到vram_d的MST设置为3时,将分给3D纹理贴图的存储,vram_e到vram_g则是3D纹理贴图的调色板
引用
复制内容到剪贴板
代码:
VRAM SIZE MST OFS Texture/Rear-plane Image
A,B,C,D 128K 3 0..3 Slot OFS(0-3) ;(Slot2-3: Texture, or Rear-plane)
VRAM SIZE MST OFS Texture Palette
E 64K 3 - Slots 0-3 ;OFS=don't care
F,G 16K 3 0..3 Slot (OFS.0*1)+(OFS.1*4) ;ie. Slot 0, 1, 4, or 5
注意,这里有个slot的概念,图形引擎在寻址的时候,是按照slot的顺序的,3D纹理贴图的slot的值直接等于VRAMCNT的offset值
比如,VRAMCNT_B的offset=0的话,那么,寻址的时候,要从vram_b开始,3D纹理贴图的地址计算也要从这个bank开始
调色板的slot,根据不同的vram bank,有不同的情况,如果是vram_e,则slot0到slot3均存储在vram_e
vram_f/vram_g则有offset=0 slot=0;offset=1 slot=1;offset=2 slot=4;offset=3 slot=5;
SDK内对应的API为
复制内容到剪贴板
代码:
void GX_SetBankForTex(GXVRamTex tex);//这是设置3D纹理贴图的
void GX_SetBankForTexPltt(GXVRamTexPltt texPltt);//这是设置3D纹理贴图的调色板的
参数跟上面那个函数其实一样,但要注意,因为只有a b c d这4个bank可以作为3D纹理贴图,不能把之后的bank作为参数传给GX_SetBankForTex
还需要注意,这里也可以通过位或运算,一次性设置多个,但是slot的设置是从最前面的bank开始的,比如"vram_c|vram_b|vram_d"这样子传进去的话,
vram_b会被设置为slot0,vram_c会被设置为slot1,依此类推
纹理的调色板也是一样的,要注意
另外,一旦将显存设置为3D纹理跟3D纹理的调色板,将无法被CPU访问,你要想修改这段它们,就必须要把显存切换回LCDC模式,然后再切换回来,
现在知道我为什么要在一开始介绍LCDC模式了吧
最后提一下,在no$gba debugger中,按下F10,打开I/O map视窗,切换到Cpmem9这个标签页上,可以在左下角看到10个显存bank的具体分配,这样不需要一个个去计算了
[
本帖最后由 enler 于 2013-3-11 22:22 编辑 ]