⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gba开发c语言内功补习.txt

📁 嵌入式GBA掌机开发源码
💻 TXT
字号:
GBA开发C语言内功补习 
 
作者:HuangYZ 文章来源:CGDS 更新时间:2004-1-22    
 
 
自从学习开发GBA后,便对其开发的容易性,效率为之吸引. 
想必大家也是如此. 
因为GBA开发多数是使用C语言的, 
这里写一点基本的C语言的使用技巧. 
希望能增加大家的内功. 

1 对内存里的寄存器进行操作. 

任何一个GBA开发库的GBA头文件都包含了很多由#define定义的符号. 
如 #define VRAM 0x06000000 // VRAM 

这里的VRAM是一个宏符号,后面的0x06000000是一个立即数 
说明VRAM所代替的是0x06000000. 
和变量不同的是,变量会占内存,而宏定义是不占内存的.因为宏只对编译器负责. 

由于GBA是使用了统一编地址.所有逻辑功能部件都是直接连接CPU片总线 
所以,GBA要对其他部件操作的时候,就如同操作内存一样容易. 

下面讲一下如何直接对内存进行操作. 
就拿VRAM来说,如果想对这个地址写入一个 8 位无符号数的话,可以如下操作. 

*(u8*)VRAM = 0xff; // u8 是 unsigned char 

也可以这样写 

*(u8*)0x06000000 = 0xff 

这样的操作在C语言中是合法的.相当与把一个指针直接指定地址后类型转换成U8然后对内容操作. 

其结果是 06000000h 的位置为 0xff 

如果你想写入一个u16的数的话,可以这样写 

*(u16*)VRAM=0xaaff 或 *(u16*)0x06000000 

其结果是 06000000h 为 0xff 
06000001h 为 0xaa 

以高位存放高地址,低位存放低地址的(大数端)原则存放数据. 

当然,地址是固定的,如何使用就要看实际情况了. 

上面这样的操作是GBA里最普遍的.由于98%的C语言的书上都没有提到这类用法, 
所以在某种程度上,成了新手学习的绊脚石. 

2 利用结构型直接对位进行定义名称. 

结构型是C语言里极重要和普遍的定义数据的手段. 
但是恰恰许多人对结构型了解不是很深入. 

结构型的基本定义方式为 

struct 
{ 
u8 a, 
u8 b; 
u8 c; 
u8 *d; 
}mystr; 

如此便定义好了一个结构,其中包括a,b,c三个U8类型的成员.和一个指针d 
这个结构的大小是 3 * 8 + 16 = 40 bit. = 5 byte 

因为一个指针的大小等于字长,GBA里多数情况下是用THUMB模式开发程序.故为16位. 

然后到我们今天的重点. 

举个例子,定义一个15bit颜色结构RGB ,其包含 R,G, B.是一共是16位. 
格式为 a bbbbb ggggg rrrrr 最高位无用. 

许多人会定义成 
typedef struct { 
U8 R,G,B; 
}RGB; 

这个结构占3字节,使用的时候用逻辑运算,压成一个16位的点的数据. 

其实此操作太麻烦. 
先进的定义方式是: 

typedef struct { 
u16 r : 5 ; 
u16 g : 5 ; 
u16 b : 5 ; 
u16 dummy : 1 ; 
}RGB; 

此结构大小为 16bit 符合RGB的规则. 

关键在于在成员变量的后面加上 冒号 和 定义的位数.就完成了直接给位进行定义名称. 
其中 严格按照从低位到高位的原则,先定义这为低位.后面定义的会接在前面一个后面的位定义. 
由于RGB定义完了,使用了15位,有最高位空闲,.所以定义个1位的DUMMY,防止浪费. 

使用的时候和一般的结构型一样使用.不过如果数值超出范围的话,超出的部分无效. 

如果这样定义 

typedef struct 
{ 
u8 a:5 ; 
u8 b; 
u8 c:4; 
}ABC 

那么这个结构仍然为3BYTE. 因为成员b没有说明是跟在a后面定义,而是另外重新定义一个成员.故 
无法连在a后. 
也就是说 a 的高3位就浪费了. 



3 实例 

就拿GBA里一个十分重要的寄存器DISPCNT来说 
位于0x4000000 大小为16bit 
头文件里定义为 
#define DISPCNT 0x4000000 

具体内容为 

F E D C B A 9 8 7 6 5 4 3 2 1 0 
W V U S L K J I F D B A C M M M 
0-2 (M) = BG模式 0 ~ 5 
3 (C) = Game Boy Color 模式 
4 (A) = BG反转 
5 (B) = hblnk 
6 (D) = 1D 方式还是2D方式 
7 (F) = MODE4中使用.用于检测是哪个FRAME有效. 
8 (I) = BG0. 允许显示 
9 (J) = BG1. 允许显示 
A (K) = BG2. 允许显示 
B (L) = BG3. 允许显示 
C (S) = OAM 允许显示 
E (V) = Window允许 
F (W) = Sprite Windows允许 


按照上面说的,可以如此定义结构. 

typedef struct DispCnt{ 
u16 BgMode:3; // BG Mode Select 
u16 CgbMode:1; // CGB Mode Select 
u16 Bmp_FrameNo:1; // Bitmap Mode Display Frame Select 
u16 Obj_H_Off:1; // OBJ Processing in H Blank OFF 
u16 ObjCharMapType:1; // OBJ Character Data Mapping Type 
u16 Lcdc_Off:1; // LCDC OFF 
u16 Bg0_On:1; // BG 0 ON 
u16 Bg1_On:1; // BG 1 ON 
u16 Bg2_On:1; // BG 2 ON 
u16 Bg3_On:1; // BG 3 ON 
u16 Obj_On:1; // OBJ ON 
u16 Win0_On:1; // Window 0 ON 
u16 Win1_On:1; // Window 1 ON 
u16 ObjWin_On:1; // OBJ Window ON 
} DispCnt; 


对其进行操作: 

((DispCnt*) DISPCNT)->成员变量. 

把DISPCNT的地址转换成DispCnt类型然后指针化,把这个指针操作其内部的成员. 


这样够方便了把.不用理会那些麻烦的标志,和逻辑操作. 
直接赋值就可以了. 



(此种方法在99%的C语言书里也没提到过. ……..心寒) 

由于GBA里类似的寄存器实在太多,请切记,上述方法使用不要过度. 
否则一大堆指针,会占太多的内存.使可用的内存减少,造成资源短缺. 
请一定要注意. 


写完后,有点累了.希望能帮助大家进入GBA的开发圈子,提高自己的C语言内功. 

 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -