axsoft
版主
發表:681 回覆:1056 積分:969 註冊:2002-03-13
發送簡訊給我
|
作者:樂水
GBA編程初解 資料來源:http://www.gameres.com/Other/GBA/GBAProgram.htm 在具體介紹gba編程之前,我想先感謝一個人,他就是 水銀 兄。在我學習的過程中水銀兄給了我很多有用的寶貴資料,在此我向他表示感謝。 GBA是新一代的32位手掌機,強大的機能吸引了無數玩家和編程愛好者。現在用於開發的編譯器有兩種,一種是完全免費的GCC,和收費的ARM SDT,目前我在使用的是gcc,雖然網上也有D過來的arm sdt但我是無福享用的,23MB的大家伙啊,當初下載gcc這個12MB的東東時我就已經吐血了,可憐我的小貓啊。 好了,廢話少說,進入正題。GBA使用的是卡帶也就是只讀rom為存儲載體雖然容量可以很大,但問題也不少。也就是說我們不可能動態的分配使用卡上的內存了盡管它可以有128MB。當然gba也為我們提供了ram,至於容量嘛……,看下面的資料知道了。 單詞含義:
1. GBA - 'Game Boy Advance' ^_^
2. BG(Backgroud) - '背景'
3. Sprite - '精靈'
4. Tile - '地圖圖塊'
5. RAM(Random Access Memory) - '隨機訪問存儲器'
接口地址 :
外部 RAM: 地址: 0x02000000 大小: 256Kb 作用: 存放程序及數據
內部 RAM: 地址: 0x03000000 大小: 32Kb? 作用: 我想是高速內存,和cache作用一樣吧
IO RAM: 地址: 0x04000000 大小: 1Kb 作用: 控制圖像,聲音,DMA等內存映射IO
Palette - '調色板'
地址: 0x05000000 大小: 0x400 bytes 作用: 存放調色板數據
VRAM(Video RAM) - '視頻內存'
地址: 0x06000000 大小: 0x20000 bytes 作用: 位圖模式下存放幀緩衝數據,圖塊模式下存放圖塊數據及圖塊地圖數據
OAM(Object Attribute Memory) - '精靈對象屬性內存'
地址: 0x07000000 大小: 0x400 bytes 作用: 用於控制精靈 6. ROM(Read Only Memory) - '只讀存儲器'
地址: 0x08000000 大小: 看你的游戲卡的大小羅 作用: 存放所有的程序和數據
7. ARM - 32bit 指令系統 (RISC,精簡指令集)
8. Thumb - 16bit 指令系統 (具體區別詳見 http://gbadev.org/files/armthumb-romram.txt)
9. DMA(Direct Memory Access) - 直接內存訪問
10.DISPCNT(Display Controller) - 顯示控制(內存地址) 當初看水銀兄寫的gba教程時一直不明白明明是256色模式,可指向VRAM的指針卻是short型的。後來才知道,gba訪問VRAM時一次必須讀寫2個字節,即16bit。我暈~~!所以我只好嚴格要求自己的blit函數。雖然也找到一個可以寫8bit的putpixel函數代碼,但速度太慢了不適合用在顯示大量圖片的地方。 需要注意的地方大概都說完了,我們可以進入代碼部分了。 雖然是專用游戲機,但顯示模式也需要設定才行。 #define REG_DISPCNT *(u16*)0x04000000// 顯示寄存器地址
#define VRAM 0x06000000 // 圖像緩衝區地址
#define M5_VRAM 0x0600A000 // M5緩衝區地址
#define BACKBUFFER 0x010// 雙緩衝/背緩衝地址
#define PALETTE 0x5000000// 調色板地址
#define MODE_3 0x03 // 240*160 15位/單緩衝區
#define MODE_4 0x04 // 240*160 8位/雙緩衝區
#define MODE_5 0x05 // 160*128 15位/雙緩衝區
#define BG2_ENABLE 0x0400 // BG_2
#define SetMode(Mode) REG_DISPCNT=(Mode) // 設置顯示模式的宏定義 typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32; typedef struct BITMAP
{
int x,y,w,h;
u16 MskCol;
float bitx,bity;
u8 flag;
u16 *dat;
}BITMAP; BITMAP screen; u16 *palette_mem = (u16 *)PALETTE; void grp_init()
{
SetMode(MODE_4|BG2_ENABLE);
screen.w=240;
screen.h=160;
screen.dat=(u16 *)VRAM;
} 這樣我們就進入了240*160*256的模式了, SetMode中的BG2_ENABLE這個參數不能少否則將沒有任何顯示。為了能夠正常的顯示圖象還需要設置調色板。 void set_palette(unsigned short *palette)
{
int loop;
for(loop=0;loop<256;loop )
{
palette_mem[loop] = palette[loop];
}
} 調色板數據可以從bmp2gba轉換bmp圖象後的.h中得到,需要注意的是bmp2gba不能夠正確的轉換過大的圖象,大概是240*160以上的圖片轉換後都有問題,所以我自己寫了一個pic2gba,可以轉換256色的pcx,bmp(未壓縮,轉換前還需要進行一下旋轉處理),gif格式的程序,但我不知道bmp2gba是如何轉換調色板數據的,所以這部分數據是不正確的。 pic2gba使用方法:pic2gba in-file out-file。 水銀兄的教程中是直接使用圖象數據的,這對以後寫game可不是一個好的方法,所以我才定義了BITMAP結構既然要顯示圖象就需要將圖象數據裝入BITMAP: BITMAP load_bitmap(int width,int height,const unsigned char *dat)
{
BITMAP bitmap;
bitmap.dat=(u16*)dat;
bitmap.x=bitmap.y =0;
bitmap.w=width;
bitmap.h=height;
bitmap.MskCol=*bitmap.dat;
bitmap.flag=TRUE;
return bitmap;
} 然後再blit: void blit(BITMAP dst,BITMAP src,int x1,int y1,int x,int y,int w,int h)
{
register int i=0,j;
register u16 *_bak1,*_bak2;
_bak1=dst.dat;
_bak2=src.dat;
_bak1 =x1 y1*(dst.w>>1);
_bak2 =x y*(src.w>>1); while(i >1;
i ;
}
} 這個是最快的方法了。哦,對了還有更快的方法:直接使用DMA,可惜我這沒資料。 如果是要顯示漢字,除了水銀兄的方法外(比較適合游戲中使用)也可以把整個漢字庫都放到rom中去,用這個rhzk程序來轉換數據。(需要UCDOS的HZK16,ASC16兩個字庫。)因為這裡要寫點,速度要求也比較低可以使用這個函數: inline void putpixel(BITMAP bmp,int x,int y,u8 col)
{
u16 *tc;
tc=bmp.dat (y)*(bmp.w>>1) (x>>1);
if(x&1)*tc=((*tc&255) (col<<8));
else
*tc=(*tc&65280) col;
} 下面的是顯示漢字的主體部分了, struct ChinaHzk{
short len;
const u8 *CHzkBuf,*AHzkBuf;
char Loadhzk,HZK;
ChinaHzk();
}ChinaHzk; ChinaHzk::ChinaHzk()
{CHzkBuf=_CHzkBuf;
AHzkBuf=_AHzkBuf;//這兩個指針在rhzk程序轉換後的.h中定義
} void hzput(int x,int y,int col,BITMAP bitmap1)
{
u8 dot;
register int i,j,k,mask;
if(ChinaHzk.HZK){
for(i=0;i<=15;i )
{for(j=0;j<=1;j )
{
dot=*ChinaHzk.CHzkBuf ;
mask=0x80;
for(k=0;k<=7;k )
{if(dot&mask)
putpixel(bitmap1,x j*8 k,y i,col);
mask>>=1;
}
}
} }else
for(i=0;i<=15;i )
{
dot=*ChinaHzk.AHzkBuf ;
mask=0x80;
for(k=0;k<=7;k )
{if(dot&mask)
putpixel(bitmap1,x k,y i,col);
mask>>=1;
}
}
ChinaHzk.HZK=1;
}
//顯示字符
void textout(BITMAP bitmap1,char *Str,int x,int y,unsigned char col)
{
register unsigned long offset1;
int oldx;
const u8 *_bakCHzkBuf,*_bakAHzkBuf; _bakCHzkBuf=ChinaHzk.CHzkBuf;
_bakAHzkBuf=ChinaHzk.AHzkBuf;
oldx=x;
while(*Str)
{if(*Str=='\n'){y =17;x=oldx;*Str ;continue;}
if(*Str==' '){x =8;*Str ;continue;} if(!(*Str&0x80)){
offset1=*Str<<4;
ChinaHzk.HZK=0;
ChinaHzk.AHzkBuf =offset1;
hzput(x,y,col,bitmap1);
if(x 8 ChinaHzk.lenGBA.ZIP
也許你看了這些會覺得有些眼熟,是的,如果你以前曾用過我寫的游戲開發庫Beauty的話,會發現基本上代碼沒有改變,而我當初也的確是有著樣的想法, 即使在不同的平台上,不同的系統但使用一套相似的開發庫進行開發可以為以後的移植工作省下很大力氣。我在進行gba程序編寫時就一直在使用Beauty庫做測試相比之下要比用gba模擬器方便的多。
時間就是金錢---[ 發問前請先找找舊文章] 發表人 - axsoft 於 2002/08/14 15:21:37
|