分享到新浪微博 分享到QQ空间 打印

[原创改版教程] nds 3d游戏hack入门(1) 显存控制

nds 3d游戏hack入门(1) 显存控制

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 编辑 ]
附件: 您所在的用户组无法下载或查看附件
本帖最近评分记录
  • 阴魂君 PT币 +50 好教程 2013-3-14 19:02
  • 阴魂君 热度 +5 好教程 2013-3-14 19:02

TOP

即使没怎么看懂也要装作看懂的样子!【够了
不过以后一定能看懂的……只要开始改ds的话
今之众人,其下圣人也远矣,而耻于师。
是故圣亦圣,愚亦愚。
圣人之所以为圣,愚人之所以为愚,
其皆出于此乎?

TOP