国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

嵌入式GameBoyAdvance模擬器移植實(shí)驗(yàn)

2016-07-04 20:25:46葉立威姜海陽(yáng)
電腦知識(shí)與技術(shù) 2016年15期
關(guān)鍵詞:源代碼模擬器按鍵

葉立威+姜海陽(yáng)

摘要:論文將GameBoyAdvance游戲模擬器移植到嵌入式系統(tǒng)中。借助開(kāi)放源代碼的跨平臺(tái)多媒體開(kāi)發(fā)庫(kù)SDL,實(shí)現(xiàn)對(duì)現(xiàn)有基于PC的GameBoyAdvance模擬器源代碼進(jìn)行移植,包括對(duì)窗口的設(shè)計(jì)、按鍵事件的判斷和音頻播放等人機(jī)交互界面設(shè)計(jì),最終實(shí)現(xiàn)了GameBoyAdvance游戲在凌動(dòng)平臺(tái)上的運(yùn)行。

關(guān)鍵詞: GameBoyAdvance游戲;SDL庫(kù);嵌入式系統(tǒng)

中圖分類(lèi)號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2016)15-0122-04

Abstract: GameBoyAdvance game simulator is transplanted to the embedded system. With open source cross platform multimedia development library SDL, the simulator source code based on PC is transplanted, including function such as the window design, key events of judgment and audio playback man-machine interface design, eventually the GameBoyAdvance game in the SDL operation is completed.

Key words: GameBoyAdvance; SDL library; embedded system

1 背景

GameBoyAdvance游戲以其獨(dú)特的魅力吸引了大量的游戲愛(ài)好者。相對(duì)Game Boy游戲的早期版本,如GameBoy、Game BoyColor游戲,GameBoyAdvance游戲需要耗費(fèi)龐大的系統(tǒng)資源,隨著嵌入式處理器處理能力的迅猛發(fā)展,GBA游戲模擬器在嵌入式處理器的移植、運(yùn)行成為了可能。模擬器的移植工作是本論文中最大的內(nèi)容之一,移植工作顯得非常重要,它決定著這個(gè)論文是否能順利進(jìn)行下去。但是移植過(guò)程中會(huì)出現(xiàn)許多不確定因素,因素是多樣的,有被移植代碼的因素,也有來(lái)自SDL本身接口函數(shù)處理的因素,因此被移植代碼是否最終能夠在系統(tǒng)中正常運(yùn)行將遇到許多障礙。由于windows下的開(kāi)發(fā)工具非常方便,因此我們的思路是先拋開(kāi)SDL的移植,在去掉windows的API接口后先能夠確保代碼在windows上編譯通過(guò),然后再將代碼進(jìn)行SDL移植,雖然看似多走了一段路,但這樣將移植風(fēng)險(xiǎn)降到了最低。

GameBoyAdvance模擬器能夠正常在嵌入式系統(tǒng)下運(yùn)行,其移植過(guò)程是一個(gè)充滿(mǎn)挑戰(zhàn)的旅程,我們選擇VC++6.0,通過(guò)VC++6.0 windows開(kāi)發(fā)工具的調(diào)試修改,使得GBA游戲能夠在windows下運(yùn)行,最終能夠移植到嵌入式系統(tǒng)下運(yùn)行。

2 GameBoyAdvance在SDL上的移植

由于GameBoyAdvance模擬器是開(kāi)源代碼,所以在網(wǎng)上可以找到GameBoyAdvance模擬器的部分代碼,但這些代碼都只能在系統(tǒng)上編譯以及對(duì)GBA文件進(jìn)行解碼,但是調(diào)用windows的AIP函數(shù)會(huì)出錯(cuò),所以沒(méi)有游戲運(yùn)行窗口、按鍵響應(yīng)、音頻播放等基本功能,也就是說(shuō),一般用網(wǎng)上的開(kāi)源源代碼編譯出來(lái)的可執(zhí)行程序不能直接運(yùn)行GBA游戲。

SDL是一個(gè)用C語(yǔ)言編寫(xiě)的免費(fèi)跨平臺(tái)多媒體開(kāi)發(fā)庫(kù),使用LGPL許可證,可用于游戲、游戲開(kāi)發(fā)工具、模擬器、樣本演示、多媒體應(yīng)用等。[1]為了添加人機(jī)交互界面,我們直接將工程中的windows的API函數(shù)拋棄,與跨平臺(tái)的SDL相結(jié)合起來(lái),調(diào)用SDL中的一些庫(kù)函數(shù),從而實(shí)現(xiàn)對(duì)GameBoyAdvance模擬器的移植。

2.1 SDL庫(kù)函數(shù)的添加

先將開(kāi)源源代碼工程中的main.cpp文件更名newMain.cpp,把 GameBoyAdvance整個(gè)工程文件和newMain.cpp文件添加到VC++6.0的工程中,當(dāng)執(zhí)行編譯時(shí)會(huì)產(chǎn)生許多錯(cuò)誤,部分錯(cuò)誤如下:

C:\GBV\vb_no_MMX\vb_no_MMX\win32\newMain.cpp(16): error C2062:type 'int' unexpected

C:\GBV\vb_no_MMX\vb_no_MMX\win32\newMain.cpp(17) : error C2146: syntax error : missing ';' before identifier 'CALLBACK'

C:\GBV\vb_no_MMX\vb_no_MMX\win32\newMain.cpp(17) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

C:\GBV\vb_no_MMX\vb_no_MMX\win32\newMain.cpp(17) : error C2146: syntax error : missing ';' before identifier 'WndProc'

C:\GBV\vb_no_MMX\vb_no_MMX\win32\newMain.cpp(17) : error C2065: 'HWND' : undeclared identifier

C:\GBV\vb_no_MMX\vb_no_MMX\win32\newMain.cpp(17) : error C2065: 'UINT' : undeclared identifier

C:\GBV\vb_no_MMX\vb_no_MMX\win32\newMain.cpp(17) : error C2065: 'WPARAM' : undeclared identifier

C:\GBV\vb_no_MMX\vb_no_MMX\win32\newMain.cpp(17) : error C2065: 'LPARAM' : undeclared identifier

可以看出,編譯出錯(cuò)主要是因?yàn)樵垂こ淌侵苯诱{(diào)用windows下API函數(shù),但我們?cè)谝浦渤鯇⑦@些API函數(shù)的頭文件刪除了,部分刪除內(nèi)容如下:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

所以,如果要進(jìn)行SDL移植,就要加上SDL庫(kù)和模擬器源代碼的頭文件,添加內(nèi)容如下:

#include

#include

#include

#include

#include

#include

#include "SDL.h"

#include "GBA.h"

#include "agbprint.h"

#include "Flash.h"

#include "Port.h"

#include "debugger.h"

#include "RTC.h"

#include "Sound.h"

#include "Text.h"

#include "unzip.h"

#include "Util.h"

#include "gb/GB.h"

#include "gb/gbGlobals.h"

至此,GameBoyAdvance模擬器開(kāi)源源代碼成功用SDL移植成無(wú)人機(jī)交互界面的模擬器。

3 為GameBoyAdvance模擬器增加人機(jī)交互界面

當(dāng)GameBoyAdvance在Windows上利用SDL實(shí)現(xiàn)了無(wú)人機(jī)交互界面移植成功后,模擬器還只是 “又聾又啞”,還需要添加人機(jī)交互界面才是一個(gè)完整的模擬器。這個(gè)過(guò)程包括了3大部分的內(nèi)容:游戲畫(huà)面、鍵盤(pán)響應(yīng)、聲音播放。

3.1 窗體設(shè)計(jì)

通過(guò)SDL建立窗口界面,在newMain.cpp的main函數(shù)里添加創(chuàng)建窗口語(yǔ)句,就可以建立在windows下的窗口,部分程序如下:

if(cartridgeType == 0) {

srcWidth = 240;

srcHeight = 160;

systemFrameSkip = frameSkip;

} else if (cartridgeType == 1) {

if(gbBorderOn) {

srcWidth = 256;

srcHeight = 224;

gbBorderLineSkip = 256;

gbBorderColumnSkip = 48;

gbBorderRowSkip = 40;

} else {

srcWidth = 160;

srcHeight = 144;

gbBorderLineSkip = 160;

gbBorderColumnSkip = 0;

gbBorderRowSkip = 0;

}

systemFrameSkip = gbFrameSkip;

} else {

srcWidth = 320;

srcHeight = 240;

}

destWidth = (sizeOption+1)*srcWidth;

destHeight = (sizeOption+1)*srcHeight;

surface = SDL_SetVideoMode(destWidth, destHeight, 16,SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF | (fullscreen ? SDL_FULLSCREEN : 0));

3.2 加入鍵盤(pán)響應(yīng)

為了能響應(yīng)到按鍵事件,我們?cè)趎ewMain.cpp文件中利用SDL對(duì)按鍵事件響應(yīng)的判斷,自行編寫(xiě)按鍵事件響應(yīng)函數(shù),從而可以達(dá)到對(duì)按鍵進(jìn)行響應(yīng),程序如下:

while(SDL_PollEvent(&event) {

if(event.type == SDL_KEYDOWN) {

switch(event.key.keysym.sym) {

case SDLK_UP: // GBA_UP

ZSC_Key_UP();

break;

case SDLK_DOWN : //GBA_DOWN

ZSC_Key_DOWN();

break;

case SDLK_LEFT: //GBA_LEFT

ZSC_Key_LEFT();

break;

case SDLK_RIGHT: //GBA_RIGJT

ZSC_Key_RIGHT();

break;

case SDLK_Enter: //GBA_Enter

ZSC_Key_ Enter ();

break;

case SDLK_A: //GBA_A

ZSC_Key_ A ();

break;

case SDLK_Z: //GBA_Z

ZSC_Key_ Z ();

break;

case SDLK_X: //GBA_X

ZSC_Key_ X ();

break;

case SDLK_Esc:

ZSC_GameExit();

break;

………

}

}

}

3.3 加入聲音播放引擎

到目前為止,我們還剩最后的聲音處理了,怎樣處理聲音這一塊呢?借助SDL庫(kù),將解碼聲音播放出來(lái),我們最終解決了這個(gè)問(wèn)題。在原本newMain.cpp中被注銷(xiāo)掉的代碼位置中填入SDL聲音引擎。

首先在ZSC_systemSoundInit填入內(nèi)容下,其中是SDL庫(kù)對(duì)聲音驅(qū)動(dòng)的初始化代碼如下:

bool ZSC_systemSoundInit()

{

SDL_AudioSpec audio;

switch(soundQuality) {

case 1:

audio.freq = 44100;

soundBufferLen = 1470*2;

break;

case 2:

audio.freq = 22050;

soundBufferLen = 736*2;

break;

case 4:

audio.freq = 11025;

soundBufferLen = 368*2;

break;

}

audio.format=AUDIO_S16SYS;

audio.channels = 2;

audio.samples = 1024;

audio.callback = ZSC_soundCallback;

audio.userdata = NULL;

if(SDL_OpenAudio(&audio, NULL)) {

fprintf(stderr,"Failed to open audio: %s\n", SDL_GetError());

return false;

}

soundBufferTotalLen = soundBufferLen*10;

cond = SDL_CreateCond();

mutex = SDL_CreateMutex();

sdlSoundLen = 0;

systemSoundOn = true;

return true; }

在SDL_AudioSpec audio結(jié)構(gòu)中,定義了聲音播放的回調(diào)函數(shù)ZSC_soundCallback,該函數(shù)將游戲中解碼的音頻數(shù)據(jù)sdlBuffer不斷拷貝到播放數(shù)據(jù)流中。部分程序如下:

void ZSC_soundCallback(void *,u8 *stream,int len)

{

if(!emulating)

return;

SDL_mutexP(mutex);

if(!speedup && !throttle) {

while(sdlSoundLen < 2048*2) {

if(emulating)

SDL_CondWait(cond, mutex);

else

break;

}

}

if(emulating) {

memcpy(stream, sdlBuffer, len);

}

sdlSoundLen = 0;

if(mutex)

SDL_mutexV(mutex);

}

經(jīng)過(guò)分析,所播放的音頻數(shù)據(jù)是通過(guò)WriteSample函數(shù)來(lái)實(shí)現(xiàn)解碼程序和播放程序相互連接的,由 WriteSample函數(shù)代碼和WriteSample在sound.c中被調(diào)用可以看出來(lái)WriteSample函數(shù)是聲音處理的關(guān)鍵函數(shù),部分程序如下:

void WriteSample(short int l, short int r)

{

if (audio_is_open == 0) {

return;

}

sample[0][sample_pos] = (short) (l >> 8);

sample[1][sample_pos] = (short) (r >> 8);

sample_pos++;

if (sample_pos >= AUDIOBUFFER) {

play_sample(sample[0], sample[1]);

sample_pos = 0;

}

}

WriteSample中,當(dāng)音頻數(shù)據(jù)采集到AUDIOBUFFER的長(zhǎng)度后 ,音頻數(shù)據(jù)通過(guò) play_sample播放出去。我們將play_sample填入代碼,將采集到的音頻數(shù)據(jù)存儲(chǔ)在final_wave中,由回調(diào)函數(shù)waveout播放出去。部分程序如下所示:

void play_sample(signed char *dataL, signed char *dataR)

{

int i;

for (i = 0; i < 2049; i++)

{

sdlBuffer [waveptr] = (dataL[i] +dataR[i] );

waveptr++;

if ( waveptr == 2048 )

{

waveptr = 0;

wavflag = 2; wavdone=0;

}

else if ( waveptr == 1024 )

{

wavflag = 1; wavdone=0;

}

while (!wavdone) SDL_Delay(0);

}

}

因?yàn)樵a中的close_audio用來(lái)關(guān)閉聲音設(shè)備,而SDL的 SDL_CloseAudio()函數(shù)可以用來(lái)實(shí)現(xiàn)對(duì)聲音設(shè)備的關(guān)閉,因此在close_audio中填入代碼:

void close_audio(void)

{

SDL_CloseAudio();

audio_is_open = 0;

}

至此模擬器能夠顯示游戲畫(huà)面、播放游戲音樂(lè)、響應(yīng)用戶(hù)指令,已經(jīng)能夠運(yùn)行在凌動(dòng)平臺(tái)下了,有了上述基礎(chǔ)下一步只需要做一些小小改動(dòng)即可運(yùn)行在嵌入式系統(tǒng),如linux系統(tǒng)、WinCE等等。移植GameBoyAdvance模擬器運(yùn)行游戲如圖1所示:

4 結(jié)束語(yǔ)

論文成功的將GameBoyAdvance游戲模擬器成功移植到凌動(dòng)平臺(tái)上。通過(guò)測(cè)試,支持大部分網(wǎng)絡(luò)下載的GBA文件格式的游戲。游戲畫(huà)面清晰流暢,聲音,按鍵操作可靠。論文雖然達(dá)到了預(yù)期目的,但仍有許多可以改善的地方,如在游戲運(yùn)行中存在聲音有輕微不流暢,畫(huà)面有輕微卡、頓的現(xiàn)象,將在后續(xù)的研究過(guò)程中進(jìn)行改進(jìn)。

參考文獻(xiàn):

[1] 王園園, 高明煜, 曾毓. 基于 SDL 庫(kù)的嵌入式平臺(tái)中文顯示技術(shù)研究[J]. 計(jì)算機(jī)系統(tǒng)應(yīng)用, 2009(4).

[2] 顧葉鋒,付宇卓,魯欣. 基于ARM Linux 的GameBoy模擬器移植和優(yōu)化研究[J]. 計(jì)算機(jī)仿真, 2005(9).

[3] 趙成. 嵌入式系統(tǒng)應(yīng)用基礎(chǔ):基于S3C2410A的SKYEYE的仿真與實(shí)踐[M]. 北京: 國(guó)防工業(yè)出版社, 2012.

[4] 謝蓉, 巢愛(ài)棠. Linux基礎(chǔ)及應(yīng)用[M]. 北京: 中國(guó)鐵道出版社, 2005.

猜你喜歡
源代碼模擬器按鍵
人工智能下復(fù)雜軟件源代碼缺陷精準(zhǔn)校正
飛行模擬器大揭秘
航空世界(2022年3期)2022-06-01 06:13:42
了不起的安檢模擬器
基于有限狀態(tài)機(jī)的按鍵檢測(cè)程序設(shè)計(jì)
電子制作(2021年3期)2021-06-16 03:14:26
基于TXL的源代碼插樁技術(shù)研究
盲盒模擬器
劃船模擬器
軟件源代碼非公知性司法鑒定方法探析
一種多方向?qū)Ч獍存I結(jié)構(gòu)設(shè)計(jì)
電子制作(2016年1期)2016-11-07 08:43:05
揭秘龍湖產(chǎn)品“源代碼”
个旧市| 栖霞市| 平昌县| 安丘市| 淅川县| 永胜县| 安康市| 台中市| 长垣县| 漠河县| 陕西省| 会同县| 贵溪市| 皋兰县| 偃师市| 黑龙江省| 深水埗区| 名山县| 黄山市| 西华县| 南江县| 葵青区| 余姚市| 怀集县| 桑植县| 松潘县| 聊城市| 乳山市| 曲靖市| 姚安县| 丹巴县| 阜阳市| 望都县| 靖宇县| 广德县| 丰原市| 息烽县| 婺源县| 平昌县| 精河县| 七台河市|