GBA探索日记(二)

原创 2003年01月15日 09:52:00

GBA探索日记(二)
OBJ及OAM
OBJ就是指的一个个的精灵,或者说就是GBA中的小块小块的图片.它其实跟BG差不多.只是它要小一些.它也算个图层.比如GBA中的RPG游戏就喜欢把一个个的人物用OBJ来实现.这样方便控制他们的位置.当然,从GBA探索日记(-)中也可以看到BG的控制其实也是很方便的.而OBJ和BG的差别就是大小.

设置显示模式
如果你的程序里要用OBJ那么,
在设置显示模式的时候需要把DISP_OBJ_ON和DISP_OBJ_CHAR_1D_MAP加进去
*(vu16 *)REG_DISPCNT = DISP_MODE_1 |  DISP_OBJ_ON | DISP_OBJ_CHAR_1D_MAP;
#define DISP_OBJ_CHAR_1D_MAP    0x0040      // OBJ Character Data 1D Mapping
#define DISP_OBJ_ON             0x1000      // OBJ ON


下面就直接来看看OBJ在GBA中怎么实现的.
首先要说明的就是OBJ在GBA中显示也是由一个个8x8的小图块拼成,跟BG一样.
共有下面12种大小.
0000: 8  x 8         1000: 8  x 16
0001: 16 x 16        1001: 8  x 32
0010: 32 x 32        1010: 16 x 32
0011: 64 x 64        1011: 32 x 64
0100: 16 x 8        
0101: 32 x 8        
0110: 32 x 16       
0111: 64 x 32       
OBJ的数据分三部分.
1.Character
它跟BG的数据格式是一样的,都是由8x8的小图块的图像数据.而且你也可以通过转换BG的工具来转换OBJ的Character.所以说BG和OBJ的数据结构基本是一样的.不过所有的OBJ总共的Character不能超过32K.
256色的OBJ能有512个Characters,每个Characters占8*8=64bytes.而16色的Characters能有1024个.每个Character占8*8/2=32Bytes.似乎比一个BG的256个Character多?但是BG可以有多个,不同的BG可以有不同的Character,而所有OBJ只能共用这512个Charater.
2.Palette
调色板就不用说了,它跟BG一样,支持一个256色调色板或16个16色的调色板.
3.OAM
OAM就是OBJ Attribure Memory的缩写.它就是控制OBJ属性的数据部分.比如OBJ的位置,大小等数据部分就放在这里.每个OBJ的OAM占8个字节,OAM是从内存中07000000h到070003FFh,共1024=8*128,所以OAM总共能有128个.

如何创建一个OBJ呢?
前面我就说过通过转换BG的工具也可以用于转换OBJ.
以前转换BG我建议使用的是AgbLib里的bmp2map.exe,同样,转换OBJ也同样用bmp2map.exe这个工具.
比如我把Character Data放到sprite_gfx这个数组里,把Palette放到sprite_pal里面.(OBJ中没有Map Data,你的转换时可以把Map data也转换进来,只不过后面用不着)
然后在程序里写入:

DmaArrayCopy(3, sprite_gfx,OBJ_MODE1_VRAM,32);
DmaArrayCopy(3, sprite_pal,OBJ_PLTT,32);

把sprite_gfx,sprite_pal拷贝到指定内存中去.
这里又设计到OBJ_MODE1_VRAM和OBJ_PLTT两个内存地址
还是看看AgbLib中是怎么定义它们的吧.
#define PLTT                    0x05000000          // Palette RAM
#define PLTT_END                (PLTT +      0x400)
#define BG_PLTT                 (PLTT +        0x0) // BG Palette RAM
#define BG_PLTT_END             (PLTT +      0x200)
#define OBJ_PLTT                (PLTT +      0x200) // OBJ Palette RAM
#define OBJ_PLTT_END            (PLTT +      0x400)
#define VRAM                    0x06000000          // VRAM
#define VRAM_END                (VRAM +    0x18000)
#define BG_VRAM                 (VRAM +        0x0) // BG Character/Screen RAM
#define OBJ_MODE0_VRAM          (VRAM +    0x10000) // OBJ Character RAM
#define OBJ_MODE1_VRAM          (VRAM +    0x10000)
#define OBJ_MODE2_VRAM          (VRAM +    0x10000)
#define OBJ_MODE3_VRAM          (VRAM +    0x14000)
#define OBJ_MODE4_VRAM          (VRAM +    0x14000)
#define OBJ_MODE5_VRAM          (VRAM +    0x14000)
#define OBJ_VRAM_END            (VRAM +    0x18000)
这里我把BG中的地址也包含近来了,你可以对比一下BG和OBJ中的地址.

然后就是设置OAM(OBJ Attribure Memory).
这里先看看官方文档中是怎么说这个OAM的数据结构的.

特别指出的是上面表格中Character Name是指这个OBJ的起始Character的引索

我将介绍两中方法来设置.

 


第一种方法很直观,也很简单.这是我在网上看到最多的.
首先定义了数据结构
typedef struct tagOAMEntry
{
 u16 attribute0;
 u16 attribute1;
 u16 attribute2;
 u16 attribute3;
}OAMEntry, *pOAMEntry;
//attribute0
#define ROTATION_FLAG  0x100
#define SIZE_DOUBLE  0x200
#define MODE_NORMAL  0x0
#define MODE_TRANSPARENT 0x400
#define MODE_WINDOWED  0x800
#define MOSAIC   0x1000
#define COLOR_16  0x0000
#define COLOR_256  0x2000
#define SQUARE   0x0
#define TALL   0x4000
#define WIDE   0x8000

//attribute1
#define ROTDATA(n)  ((n)<<9)
#define HORIZONTAL_FLIP  0x1000
#define VERTICAL_FLIP  0x2000
#define SIZE_8   0x0
#define SIZE_16   0x4000
#define SIZE_32   0x8000
#define SIZE_64   0xC000

//atrribute2
#define PRIORITY(n)         ((n)<<10)
#define PALETTE(n)  ((n)<<12)

然后写入代码:
OAMEntry sprites[128]; // 这里把总共128个OBJ都定义了,不过我们现在只使用第一个
void InitializeSprites()
{
 u16 loop;
 for(loop = 0; loop < 128; loop++)
 {
  sprites[loop].attribute0 = 160;  //y to > 159
  sprites[loop].attribute1 = 240;  //x to > 239
 }
}
void CopyOAM()
{
 u16 loop;
 u16* temp;
 u16* _OAM = (u16*)0x7000000;
 temp = (u16*)sprites;
 for(loop = 0; loop < 128*4; loop++)
 {
  _OAM[loop] = temp[loop];
 }
}

u16 spriteY=100;
u16 spriteX=100;
InitializeSprites();
sprites[0].attribute0 = COLOR_256 | SQUARE | spriteY;
sprites[0].attribute1 = SIZE_16 | spriteX;
sprites[0].attribute2 = 0 | PRIORITY(0);

由于这个OBJ的Character是从OBJ_MODE1_VRAM的首地址开始写入的,所以它的Character Name就应该是0.所以sprites[0].attribute2 = 0 | PRIORITY(0);

由于GBA中16色的OBJ和256色的OBJ中对于Characters的寻址方式是一样的.那么无论是16色的还是256色的OBJ,它们的起始Characters都应该是OBJ的VRAM+Character Name*32(虽然256色下的Character占64Bytes).

比如看看下面的例子:

如果传输256色的sprite的Character Data到OBJ_MODE1_VRAM+N*32的地址
DmaArrayCopy(3,sprite_gfx,OBJ_MODE1_VRAM+N*32,32);
那么它对应的的attribute2中的Character Name应该是N.
sprites[0].attribute2 = N;
N的范围是0-1023

对于attribute3,我们现在暂时不用.

接下来就是把sprites写到OAM中
要在程序的主循环中不断更新OAM
while(1)
{
  // 等待图像缓冲同步
  WaitSync();
  CopyOAM();
}

 

第二种方法是AgbLib里面使用的方法.
比如我要显示一个是OBJ
就直接定义个
vu32 bg_oam_buffer[2];
然后同样要写Character和Palette数据进去
DmaArrayCopy(3, sprite_gfx,OBJ_MODE1_VRAM,32);
DmaArrayCopy(3, sprite_pal,OBJ_PLTT,32);
设置OAM的时候就这样写
bg_oam_buffer[0] = OAM_COLOR_256 |  OAM_SQUARE |OAM_SIZE_16x16
   | (100) << OAM_H_POS_SHIFT
   | (72) << OAM_V_POS_SHIFT;
bg_oam_buffer[1] = 0x0400;
下面给出AgbLib中对于上面的宏的定义:
#define OAM_V_POS_SHIFT         0
#define OAM_H_POS_SHIFT         16

#define OAM_COLOR_16            0x00000000  // Select 16
#define OAM_COLOR_256           0x00002000  // Select 256 colors

#define OAM_SIZE_8x8            0x00000000  // OBJ 8 x 8 dot
#define OAM_SIZE_16x16          0x40000000  // OBJ 16 x 16 dot
#define OAM_SIZE_32x32          0x80000000  // OBJ 32 x 32 dot
#define OAM_SIZE_64x64          0xc0000000  // OBJ 64 x 64 dot
#define OAM_SIZE_16x8           0x00004000  // OBJ 16 x 8 dot
#define OAM_SIZE_32x8           0x40004000  // OBJ 32 x 8 dot
#define OAM_SIZE_32x16          0x80004000  // OBJ 32 x 16 dot
#define OAM_SIZE_64x32          0xc0004000  // OBJ 64 x 32 dot
#define OAM_SIZE_8x16           0x00008000  // OBJ 8 x 16 dot
#define OAM_SIZE_8x32           0x40008000  // OBJ 8 x 32 dot
#define OAM_SIZE_16x32          0x80008000  // OBJ 16 x 32 dot
#define OAM_SIZE_32x64          0xc0008000  // OBJ 32 x 64 dot
你可以看出.
bg_oam_buffer[0]其实就是第一种方法的attribute0,attribute1的集合.
bg_oam_buffer[1]就是第一种方法的attribute2,attribute3的集合.
然后同样地在程序住循环里不断更新写入OAM
while(1)
{
 DmaCopy(3, bg_oam_buffer, OAM, 8 , 32);
}
这是OAM的定义:
#define OAM                     0x07000000          // OAM
#define OAM_END                 (OAM +       0x400)

GBA探索日记(二)

GBA探索日记(二) OBJ及OAM OBJ就是指的一个个的精灵,或者说就是GBA中的小块小块的图片.它其实跟BG差不多.只是它要小一些.它也算个图层.比如GBA中的RPG游戏就喜欢把一个个的人物用...
  • passren
  • passren
  • 2004年07月02日 17:19
  • 932

GBA探索日记(-)

GBA探索日记(-) mode0-2的BG与VRAM   GBA的VRAM总共96KB,在mode3-5中,VRAM跟计算机的显示内存一样.屏幕上一个点对应一个显示内存地址. 可以看看下面两个函数,...
  • passren
  • passren
  • 2004年07月02日 17:18
  • 947

GBA的内存其实很大

2011-1-10        以前当看到GBA的ram只用几百KB的时候,感到有点不可思议—怎么那么小啊,根本就不跟GBA游戏精致的界面相称。       后来注意到GBA使用的的闪存是Nor F...
  • Koupoo
  • Koupoo
  • 2011年01月10日 11:30
  • 1004

GBA MOD音乐播放探索!

这是一篇老文章了,最早放在CGDS上. GBA MOD音乐播放探索  写在前面  我并不是搞音乐的,甚至五音不全,仅仅是为了能在GBA上播放MOD音乐,我进行了一些学习,  找了大量资料后,基...
  • lrb2010
  • lrb2010
  • 2013年06月15日 13:33
  • 631

GBA编程和汉化常用软件汇总

内容来自GBA吧中的痴狂小黑,本人只是做个汇总和搬运。 1.简易图片导入导出套装(PicSimpleImEx & AutoPicRock)Ver1.0 这两个软件是用C#写的,想要用,先装...
  • u012260499
  • u012260499
  • 2016年10月19日 10:33
  • 640

GBA程序开发入门3

下面我将一一讲解上篇的程序前三行:typedef unsigned char u8;typedef unsigned short u16;typedef unsigned long u32;定义GBA...
  • tangl_99
  • tangl_99
  • 2003年06月13日 17:07
  • 9411

GBA multiBoot时的Arduino源代码~

//Description: The GBA connector pinouts are as follows: //(Looing at GBA) // __________________ ...
  • ESZETA
  • ESZETA
  • 2013年09月22日 20:51
  • 1060

自己动手丰衣足食-自己动手修改GBA ROM游戏文件

经过一天的努力终于琢磨出怎么修改GBA的游戏文件也就是俗称的ROM文件,起因是因为偶然看到二手GBM,顿时抑制不住买了一台,可惜买得晚了,完美运行游戏又带金手指功能的烧录卡买不到了。SUPERCARD...
  • l198738655
  • l198738655
  • 2017年03月21日 12:06
  • 3888

gba 中的ARM 汇编

工作还是没搞定……“编写GBA游戏的时候我们所看的教程都用C来写,用纯汇编来学习写GBA游戏仅仅是让大家熟悉一下ARM汇编……”真是人闲得闲死,什么东西都在学,郁闷的郁闷,虚空的虚空……整理一下过去在...
  • excuseser
  • excuseser
  • 2005年04月22日 21:01
  • 1349

【通用引导架构】基于GBA的AKA认证机制

基于GBA(Generic Bootstrapping Architecture)的AKA认证机制 本课题提出的物联网安全框架中,众多的业务采用的是集中认证的方式。所以需要采用相同的鉴权机制。同一种...
  • dreamstone_xiaoqw
  • dreamstone_xiaoqw
  • 2017年09月01日 09:37
  • 341
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:GBA探索日记(二)
举报原因:
原因补充:

(最多只允许输入30个字)