當前位置:首頁 » 編程軟體 » 什麼是t1編譯環境

什麼是t1編譯環境

發布時間: 2025-01-05 14:42:04

A. socket編程在windows和linux下的區別

下面大概分幾個方面進行羅列:

Linux要包含

[cpp]
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
等頭文件,而windows下則是包含
[cpp]
#include <winsock.h>


Linux中socket為整形,Windows中為一個SOCKET。
Linux中關閉socket為close,Windows中為closesocket。
Linux中有變數socklen_t,Windows中直接為int。
因為linux中的socket與普通的fd一樣,所以可以在TCP的socket中,發送與接收數據時,直接使用read和write。而windows只能使用recv和send。
設置socet選項,比如設置socket為非阻塞的。Linux下為

[cpp]
flag = fcntl (fd, F_GETFL);
fcntl (fd, F_SETFL, flag | O_NONBLOCK);
,Windows下為
[cpp]
flag = 1;
ioctlsocket (fd, FIONBIO, (unsigned long *) &flag);

當非阻塞socket的TCP連接正在進行時,Linux的錯誤號為EINPROGRESS,Windows的錯誤號為WSAEWOULDBLOCK。

file
Linux下面,文件換行是"\n",而windows下面是"\r\n"。
Linux下面,目錄分隔符是"/",而windows下面是"\"。
Linux與Windows下面,均可以使用stat調用來查詢文件信息。但是,Linux只支持2G大小,而Windows只支持4G大小。為了支持更大的文件查詢,可以在Linux環境下加

_FILE_OFFSET_BITS=64定義,在Windows下面使用_stat64調用,入參為struct __stat64。
Linux中可根據stat的st_mode判斷文件類型,有S_ISREG、S_ISDIR等宏。Windows中沒有,需要自己定義相應的宏,如

[cpp]
#define S_ISREG(m) (((m) & 0170000) == (0100000))
#define S_ISDIR(m) (((m) & 0170000) == (0040000))
Linux中刪除文件是unlink,Windows中為DeleteFile。

time

Linux中,time_t結構是長整形。而windows中,time_t結構是64位的整形。如果要在windows始time_t為32位無符號整形,可以加宏定義,_USE_32BIT_TIME_T。
Linux中,sleep的單位為秒。Windows中,Sleep的單位為毫秒。即,Linux下sleep (1),在Windows環境下則需要Sleep (1000)。
Windows中的timecmp宏,不支持大於等於或者小於等於。
Windows中沒有struct timeval結構的加減宏可以使用,需要手動定義:

[cpp]
#define MICROSECONDS (1000 * 1000)

#define timeradd(t1, t2, t3) do { \
(t3)->tv_sec = (t1)->tv_sec + (t2)->tv_sec; \
(t3)->tv_usec = (t1)->tv_usec + (t2)->tv_usec % MICROSECONDS; \
if ((t1)->tv_usec + (t2)->tv_usec > MICROSECONDS) (t3)->tv_sec ++; \
} while (0)

#define timersub(t1, t2, t3) do { \
(t3)->tv_sec = (t1)->tv_sec - (t2)->tv_sec; \
(t3)->tv_usec = (t1)->tv_usec - (t2)->tv_usec; \
if ((t1)->tv_usec - (t2)->tv_usec < 0) (t3)->tv_usec --, (t3)->tv_usec += MICROSECONDS; \
} while (0)

調用進程

Linux下可以直接使用system來調用外部程序。Windows最好使用WinExec,因為WinExec可以支持是打開還是隱藏程序窗口。用WinExec的第二個入參指明,如

SW_SHOW/SW_HIDE。

雜項

Linux為srandom和random函數,Windows為srand和rand函數。
Linux為snprintf,Windows為_snprintf。
同理,Linux中的strcasecmp,Windows為_stricmp。

錯誤處理

Linux下面,通常使用全局變數errno來表示函數執行的錯誤號。Windows下要使用GetLastError ()調用來取得。

Linux環境下僅有的
這些函數或者宏,Windows中完全沒有,需要用戶手動實現。
atoll

[cpp]
long long
atoll (const char *p)
{
int minus = 0;
long long value = 0;
if (*p == '-')
{
minus ++;
p ++;
}
while (*p >= '0' && *p <= '9')
{
value *= 10;
value += *p - '0';
p ++;
}
return minus ? 0 - value : value;
}
gettimeofday

[cpp]
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define EPOCHFILETIME 11644473600000000Ui64
#else
#define EPOCHFILETIME 11644473600000000ULL
#endif

struct timezone
{
int tz_minuteswest;
int tz_dsttime;
};

int
gettimeofday (struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
LARGE_INTEGER li;
__int64 t;
static int tzflag;

if (tv)
{
GetSystemTimeAsFileTime (&ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
t = li.QuadPart; /* In 100-nanosecond intervals */
t -= EPOCHFILETIME; /* Offset to the Epoch time */
t /= 10; /* In microseconds */
tv->tv_sec = (long) (t / 1000000);
tv->tv_usec = (long) (t % 1000000);
}

if (tz)
{
if (!tzflag)
{
_tzset ();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}

return 0;
}

編譯相關
當前函數,Linux用__FUNCTION__表示,Windows用__func__表示。
--------------------------------------------------------------------------------
Socket 編程 windows到Linux代碼移植遇到的問題
1)頭文件
windows下winsock.h/winsock2.h
linux下sys/socket.h
錯誤處理:errno.h

2)初始化
windows下需要用WSAStartup
linux下不需要

3)關閉socket
windows下closesocket(...)
linux下close(...)

4)類型
windows下SOCKET
linux下int
如我用到的一些宏:
#ifdef WIN32
typedef int socklen_t;
typedef int ssize_t;
#endif

#ifdef __LINUX__
typedef int SOCKET;
typedef unsigned char BYTE;
typedef unsigned long DWORD;
#define FALSE 0
#define SOCKET_ERROR (-1)
#endif

5)獲取錯誤碼
windows下getlasterror()/WSAGetLastError()
linux下errno變數

6)設置非阻塞
windows下ioctlsocket()
linux下fcntl() <fcntl.h>

7)send函數最後一個參數
windows下一般設置為0
linux下最好設置為MSG_NOSIGNAL,如果不設置,在發送出錯後有可 能會導致程序退出。

8)毫秒級時間獲取
windows下GetTickCount()
linux下gettimeofday()

3、多線程
多線程: (win)process.h --〉(linux)pthread.h
_beginthread --> pthread_create
_endthread --> pthread_exit
-----------------------------------------------------------------
windows與linux平台使用的socket均繼承自Berkeley socket(rfc3493),他們都支持select I/O模型,均支持使用getaddrinfo與getnameinfo實現協議無關編程。但存在細微差別,

主要有:

頭文件及類庫。windows使用winsock2.h(需要在windows.h前包含),並要鏈接庫ws2_32.lib;linux使用netinet/in.h, netdb.h等。
windows下在使用socket之前與之後要分別使用WSAStartup與WSAClean。
關閉socket,windows使用closesocket,linux使用close。
send*與recv*函數參數之socket長度的類型,windows為int,linux為socklen_t,可預編譯指令中處理這一差異,當平台為windows時#define socklen_t unsigned int。
select函數第一個參數,windows忽略該參數,linux下該參數表示集合中socket的上限值,一般設為sockfd(需select的socket) + 1。
windows下socket函數返回值類型為SOCKET(unsigned int),其中發生錯誤時返回INVALID_SOCKET(0),linux下socket函數返回值類型int, 發生錯誤時返回-1。
另外,如果綁定本機回環地址,windows下sendto函數可以通過,linux下sendto回報錯:errno=22, Invalid arguement。一般情況下均綁定通配地址。
轉載jlins

B. 編譯原理 四元式

四元式是一種比較普遍採用的中間代碼形式。

代碼段的四元式表達式:

101 T:=0 (表達式為假的出口)

103 T:=1 (表達式為真的出口)

因為用戶的表達式只有一個A<B,因此A<B的真假出口就是表達式的真假出口,所以

100: if a<b goto 103 (a<b為真,跳到真出口103)

101: T:=0(否則,進入假出口)

102: goto 104 (要跳過真出口,否則T的值不就又進入真出口了,為真)

103: T:=1

104:(程序繼續執行)

(2)什麼是t1編譯環境擴展閱讀:

四元式是一種更接近目標代碼的中間代碼形式。由於這種形式的中間代碼便於優化處理,因此,在目前許多編譯程序中得到了廣泛的應用。

四元式實際上是一種「三地址語句」的等價表示。它的一般形式為:

(op,arg1,arg2,result)

其中, op為一個二元 (也可是一元或零元)運算符;arg1,arg2分別為它的兩個運算 (或操作)對象,它們可以是變數、常數或系統定義的臨時變數名;運算的結果將放入result中。四元式還可寫為類似於PASCAL語言賦值語句的形式:

result ∶= arg1 op arg2

需要指出的是,每個四元式只能有一個運算符,所以,一個復雜的表達式須由多個四元式構成的序列來表示。例如,表達式A+B*C可寫為序列

T1∶=B*C

T2∶=A+T1

其中,T1,T2是編譯系統所產生的臨時變數名。當op為一元、零元運算符 (如無條件轉移)時,arg2甚至arg1應預設,即result∶=op arg1或 op result ;對應的一般形式為:

(op,arg1,,result)

(op,,,result)

C. 成功javaC JAVA不成功

從錯誤信息看,可能是因為類中沒有main方法,檢查別寫錯了,如果不是,你檢查my文件夾裡面有沒有Hello.class文件,如果沒有就用javac編譯一下,成功後再執行,另外異常提示中有wrong name,看看你的類名和文件名是否一致,且都是Hello。

D. 如何用C++編寫一個小游戲

一個用C++編程的小游戲,可以實現的功能如下:

1、隨機生成數字;

2、數字消除合並;

3、判定游戲結束;

一、游戲主體:

因為用C++寫的,所以用了類,棋盤用了一個二維數組,m是棋盤規格,取了4。

class game

{

public:

int i, j;

game() {

count1 = 0;

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

for (j = 0; j < m; j++)

chessboard[i][j] = 0;

srand((unsigned)time(NULL));

x = rand() % m;

y = rand() % m;

if (count1 == 1 || count1 == 0)

chessboard[x][y] = 2;

else

chessboard[x][y] = 4;

showchessboard();

}//構造初始棋盤

void add(int count1);//新增數字

void showchessboard();//顯示棋盤

void up();

void down();

void left();

void right();

bool gameover();//游戲失敗

private:

int chessboard[m][m];

int x, y, count1, count2, temp1, temp2, k;//c1-連消,c2-空位標記,t1-判連消,t2,k-臨時變數

bool flag;//判消

};

二、隨機生成數字

void game::add(int count1)

{

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

for (j = 0; j < m; j++)

{

if (chessboard[i][j] == 0)

goto loop;

}

showchessboard();

return;

loop:srand((unsigned)time(NULL));

do {

x = rand() % m;

y = rand() % m;

} while (chessboard[x][y] != 0);

if (count1 < 2)

chessboard[x][y] = 2;

else

chessboard[x][y] = 4;

showchessboard();

}

三、數字消除合並

void game::up()

{

temp1 = count1;

flag = false;

for (j = 0; j < m; j++)

for (i = 0; i < m;)

{

for (; i < 4 && chessboard[i][j] == 0; i++); // 找非零值

if (i == 4)

break;

else

{

for (k = i + 1; k < 4 && chessboard[k][j] == 0; k++);//找下一個非零值

if (k == 4)

break;

else if (chessboard[i][j] == chessboard[k][j])//匹配

{

chessboard[i][j] *= 2;

chessboard[k][j] = 0;

i = k + 1;

flag = true;

}

else if (chessboard[i][j] != chessboard[k][j] && k < 4)//不匹配

{

i = k;

}

}

}

for (j = 0; j < m; j++)//排列棋盤

for (i = 0, count2 = 0; i < m; i++)

{

if (chessboard[i][j] != 0)

{

temp2 = chessboard[i][j];

chessboard[i][j] = 0;

chessboard[count2][j] = temp2;

count2++;

}

}

}

四、判斷游戲結束

bool game::gameover()

{

if (flag)

count1++;//判連消

if (temp1 == count1)

count1 = 0;//未消除,連消歸零

add(count1);

for (i = m - 1, j = 0; j < m; j++)//最後一行

{

if (j == m - 1)//右下角

{

if (chessboard[i][j] == 0)

return false;

else if (chessboard[i][j] == 2048)

{

cout << "You Win~ ";

return true;

}

}

else

{

if (chessboard[i][j] == 0 || chessboard[i][j] == chessboard[i][j + 1])

return false;

else if (chessboard[i][j] == 2048)

{

cout << "You Win~ ";

return true;

}

}

}

for (i = 0, j = m - 1; i < m; i++)//最後一列

{

if (i == m - 1)//右下角

{

if (chessboard[i][j] == 0)

return false;

else if (chessboard[i][j] == 2048)

{

cout << "You Win~ ";

return true;

}

}

else

{

if (chessboard[i][j] == 0 || chessboard[i][j] == chessboard[i + 1][j])

return false;

else if (chessboard[i][j] == 2048)

{

cout << "You Win~ ";

return true;

}

}

}

for (i = 0; i < m - 1; i++)

for (j = 0; j < m - 1; j++)

{

if (chessboard[i][j] == 2048)

{

cout << "You Win! ";

return true;

}

else if (chessboard[i][j] == chessboard[i][j + 1] || chessboard[i][j] == chessboard[i + 1][j] || chessboard[i][j] == 0)

return false;

}

cout << "Game over. ";

return true;

}

(4)什麼是t1編譯環境擴展閱讀:

C++語言的程序因為要體現高性能,所以都是編譯型的。但其開發環境,為了方便測試,將調試環境做成解釋型的。

生成程序是指將源碼(C++語句)轉換成一個可以運行的應用程序的過程。如果程序的編寫是正確的,那麼通常只需按一個功能鍵,即可搞定這個過程。但是該過程實際上分成兩個步驟。

第一步是對程序進行編譯,這需要用到編譯器(compiler)。編譯器將C++語句轉換成機器碼(也稱為目標碼);

第二步就是對程序進行鏈接,這需要用到鏈接器(linker)。鏈接器將編譯獲得機器碼與C++庫中的代碼進行合並。C++庫包含了執行某些常見任務的函數(「函數」是子程序的另一種稱呼)。

參考資料來源:

網路-C++

E. 如何製作GBA游戲

GBAS 是 GameBoy Advance development System (GameBoy Advance 開發系統)的縮寫,它主要的功能便是用來做 GameBoy Advance 游戲以及數據的傳輸,使用者可以自行將自己所撰寫的 GameBoy Advance 軟體透過 GBAS 燒錄機傳至 GBAS 64M 或 GBS 128M 的覆寫卡上面,然後插入 GameBoy Advance 的主機執行。就是說,如果你自己也會開發GBA的游戲的話(據說對於好的程序員不是很難),那麼你根本不需要任天堂的授權,就可以把自己開發的GBA游戲直接通過GBAS系統在GBA上遊玩。
GBAS 燒錄機的功能除了負責將 GameBoy Advance 的軟體傳輸至覆寫卡外,他還具備可將原版 GameBoy Advance 卡帶備份至計算機儲存成 *.GBA 的計算機檔案,或者將原版 GameBoy Advance 卡帶以及 GBAS 覆寫卡中的記憶存檔備份成 *.SAV 的計算機檔案。這些備份的檔案均可配合各種 GameBoy Advance 計算機模擬器執行。而這就意味著你可以利用這款系統自由把網路上的GBA游戲的ROM通過GBAS燒錄機直接拷貝到專用GBAS卡帶上,想想網路上已經可以執行的GBA游戲ROM的數量,是不是有些心動了?
應該說GBAS是一個相當完善的系統,雖然這款系統剛剛開發完畢,但是它在功能上已經相當優秀了,那我們現在看看它有那些特點。
一、EEPROM 特殊記憶支持: 這款GBAS是目前唯一支持 EEPROM 記憶格式的 GBA 開發工具,也是目前唯一可以對應 Super Mario Advance (日/美)的開發工具。哈哈,要知道超級MARIO大冒險的美版還沒有出啊,而在網路上,這個游戲的ROM早就有了,所以大家可以看到在圖片中執行的GBA游戲就是超級MARIO大冒險的美版。

二、超大電池記憶: 超大 1M 電池記憶,支持所有游戲記憶(包括游戲王五代的超大電池記憶也能支持)。 這個特點是相當好的,也比較貼近玩家的特點,一般來說,用了這個東西,什麼游戲的記錄都不會出問題了,玩家完全沒有必要擔心、GBAS的記憶空間不足。
三、合卡功能: GBAS 支持合卡,64M 版本可支持兩個 32M 的游戲合卡。這樣,玩家可以一次錄進兩個32M的游戲,使GBAS成為一個合卡,要是玩家擁有的是128M的覆寫卡,嘿嘿,那就可以讓你的GBAS成為4合1卡了,這樣就節約了游戲燒錄拷貝的時間,當然,128M的卡幾個自然要高得多了。
四、操作介面:全新窗口下燒錄介面(包含游戲上載,下載以及游戲記錄文件上載下載功能)全新修正了游戲傳輸問題,更快速更准確,支持窗口 9X 作業平台,安裝容易使用方便,使用者完全不用擔心會出什麼問題。
GBA的軟體製作燒錄系統—GBAS

簡單入門-
一. GBA開發包--DevKitAdv 簡介
DevKitAdv 主要包括兩部分,一是GCC++編譯器,二是 GBA庫.

GCC++編譯器功能和我們常用的VC差不多,只不過少了個編輯源代碼的文本編輯器(至少我沒發現,我用的是EditPlus,UltraEdit也可以),還有就是--不支持類(class),真是讓人頭痛,只能用struct來替代.它的作用是把我們寫的代碼編譯成二進制的可執行文件,當然這個可執行文件是相對GBA和GBA模擬器而言的.就象Windows里的EXE文件無法在Mac機上使用是一樣的道理;

GBA庫提供了圖像,控制及聲音一系列的函數,和GCC++配合使用.

下載地址: http://occultforces.mine.nu/~darkfader/gba/files/devkitadv.zip

二. DevKitAdv 的安裝

沒啥好說的,解壓後就可以直接使用,編譯時設置DevKitAdv的路徑就可以了,建議做一個批處理文件,比如 go.bat

set PATH=d:\devkitadv\bin;%PATH%

cmd (win98是command)

三. 最簡單的 GBA 程序 (t1)

// main.c
// 一些基本數據類型
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
#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 15bits/單緩沖區
#define MODE_4 0x04 // 240*160 8bits/雙緩沖區
#define MODE_5 0x05 // 160*128 15bits/雙緩沖區
#define BG2_ENABLE 0x0400 // BG_2
#define SetMode(Mode) REG_DISPCNT=(Mode) // 設置顯示模式的宏定義

// ----------- 主程序 ------------
int main()
{
//設置屏幕模式,這里使用MODE_4
SetMode (MODE_4 | BG2_ENABLE);
}

1.MODE_5和MODE_3都是16bits,但MODE_3隻有單緩沖,製作動畫效果肯定沒雙緩沖好,因此排除MODE_3;

2.MODE_4是8bits,理論上256色對於掌機夠用了,雖然16bits真彩的誘惑沒有人想抗拒,可MODE_5隻有160*128咧,在實際應用中建議還是使用MODE_4.

很簡單吧--的確是的,現在要用GCC編譯它:

gcc -lm -o main.elf main.c

obj -v -O binary main.elf main.bin

你會看目錄下多了個"main.bin",這個就是能在GBA模擬器上執行的二進制文件!
教程中t1-t10目錄為源程序目錄,裡面有個make.bat,修改代碼後直接執行它就可以編譯,但要注意我的devkitadv是裝在D:,你要是裝在別的盤就得改一下make.bat的path參數.

四. 在MODE_4背景層畫圖的 GBA 程序 (t2)

在GBA的MODE_4里畫一幅圖要經過3個步驟:

1. 把原始256色圖像文件轉換成 *.h / *.c 的數據文件,我們用的是 < BMP2GBA > ,這里以"image.bmp"為例,轉換後我們就得到了一個"image.h"文件;

2. 在程序開頭#include "image.h",這樣就能在程序中使用"image.h"定義的調色板和圖像數據;

3. 在程序中把"image.h"定義的調色板和圖像數據寫入MODE_4背景層的調色板和圖像緩沖區.

另外,GBA還有專為精靈設置的物體層,它的用法和背景層一樣,只是功能有點不一樣,地址是0x06000000.有關用這里就不詳細說了,大家可以把精靈數據直接輸出到物體緩沖區就可以了.

下面是源程序:

... ...

// 包含圖像調色板和數據的頭文件
#include "gfx/image.h"

// ----------- 全局變數 --------
// 系統調色板
u16* palette_mem=(u16*)PALETTE;
// 圖像緩沖區
u16* video_buffer=(u16*)VRAM;

// ----------- 函數定義 ---------
// MODE_4繪圖函數
void Draw(u16* src_palette,u16* src_data,u16* dst_palette,u16* dst_data);

// ----------- 主程序 ------------
int main()
{

// 設置屏幕模式,這里使用MODE_4
SetMode (MODE_4 | BG2_ENABLE);

// 在背景層畫圖,Palette和Data是在"image.h"定義的調色板和圖像數據數組名
Draw(Palette,Data,palette_mem,video_buffer);
}

// MODE_4繪圖函數
void Draw(u16* src_palette,u16* src_data,u16* dst_palette,u16* dst_data)
{
int loop,x,y;

// 寫入目的調色板
for(loop = 0; loop < 256; loop++)
dst_palette[loop] = src_palette[loop];

// 寫入圖像緩沖區
for(x = 0; x < 120; x++)
{
for(y = 0; y < 160; y++)
{
dst_data[(y) *120 + (x)]=src_data[(y) *120 + (x)];
}
}
}

編譯後得到main.bin,然後在GBA模擬器里運行,就可以得到這樣的結果:
五. 在MODE_5畫圖的 GBA 程序 (t3)

在GBA的MODE_5里畫一幅圖也要經過相似3個步驟,只不過不需要調色板數據:

1. 把原始真彩圖像文件轉換成 *.h / *.c 的數據文件,我們用的是 < Targa2GBA > ,這里以"image.bmp"(240*160)為例,DOS窗口下進Targa2GBA目錄,輸入"t2g mode5 image.bmp image.h",轉換後我們就得到了一個"image.h"文件;

2. 在程序開頭#include "image.h",這樣就能在程序中使用"image.h"定義的圖像數據;

3. 在程序中把"image.h"定義的圖像數據寫入圖像緩沖區.

下面就是源程序:

// 包含圖像數據的頭文件
#include "gfx/image.h"

// ----------- 全局變數 --------
// 圖像緩沖區
u16* video_buffer=(u16*)VRAM;

// ----------- 函數定義 ---------
// MODE_5繪圖函數
void Draw(int x,int y,int w,int h,u16 *src_data,u16 *dst_data);

// ----------- 主程序 ------------
int main()
{
// 設置屏幕模式,這里使用MODE_5
SetMode (MODE_5 | BG2_ENABLE);

// 在背景層畫圖,image是在"image.h"定義的圖像數據數組名
Draw(0,0,240,160,image,video_buffer);
}

// MODE_5繪圖函數
void Draw(int x,int y,int w,int h,u16 *src_data,u16 *dst_data)
{
int i,o,idst;

// 把源圖像數據復制到圖像緩沖區的指定地方
idst =(y*160)+x;
for (i=0;i<h;i++)
{
for (o=0;o<w;o++)
{
if (*src_data != 0)
{
dst_data[idst] = *src_data;
}
idst++;
src_data++;
}
idst += (160-w);
}
}

編譯後運行結果:
六. 全屏顯示的 MODE_5 GBA 程序 (t4)

由於GBA不支持線性的圖像變換,因此得到的結果會產生一些馬賽克的現象,現在還是附上這個變換函數和最終結果,其實質量還是可以接受的,大家可以試試使用這個新的MODE_5.

// 切換到新MODE_5全屏模式,page為緩沖區,原理是把顯示寄存器數據X,Y交換,得到128*160的顯示,GBA就會全屏顯示.
void SetFlipMode(int page)
{
u16 *ioreg=(u16*)0x4000000;

*ioreg=5+((page&1)>>4)+(1>>10);
ioreg[0x10]=0;
ioreg[0x11]=256;
ioreg[0x12]=128;
ioreg[0x13]=0;
}

int main()
{
// 設置屏幕模式,這里使用MODE_5
SetMode (MODE_5 | BG2_ENABLE);

// 切換模式
SetFlipMode(0);

// 在背景層畫圖,image是在"image.h"定義的圖像數據數組名
Draw(0,0,240,160,image,video_buffer);

r七. GBA的雙緩沖顯示(t5)

大家在做上面MODEL_5的程序時一定會發現圖像在閃動(第六節的240*160的MM象被破了相...),而MODEL_4下卻比較穩定--這是因為MODEL_5下要處理16bits(實質上是15bits)的圖像,數據量比MODEL_4下的8bits大很多,在沒使用雙緩沖的情況下,圖像填充時就會造成閃爍,這就是為什麼我們拋棄了MODEL_3的原因...

原理也很簡單,圖像在背緩沖區里填充好之後再直接輸出到前緩沖區顯示,程序里就是一個 "等待同步-> 交換緩沖" 的過程:

... ...
// ----------- 全局變數 --------
// 圖像緩沖區
u16* video_buffer=(u16*)M5_VRAM;

// ----------- 函數定義 ---------
... ...

// 等待緩沖區數據同步
void WaitSync ();
// 交換緩沖區內容
void SwapScreen ();

// ----------- 主程序 ------------
int main()
{

// 設置屏幕模式,這里使用MODE_5
SetMode (MODE_5 | BG2_ENABLE);

while(1)
{
// 在背景層畫圖,image是在"image.h"定義的圖像數據數組名
Draw(0,0,240,160,image,video_buffer);
WaitSync();
SwapScreen();
}
}

// 等待緩沖區數據同步
void WaitSync ()
{
while (*(volatile u16*)0x4000006<160) {};
}

// 交換緩沖區
void SwapScreen ()
{
if (REG_DISPCNT & BACKBUFFER)
{
REG_DISPCNT &= ~BACKBUFFER;
video_buffer = (u16*) M5_VRAM;
}
else
{
REG_DISPCNT |= BACKBUFFER;
video_buffer = (u16*) VRAM;
}
}

八. GBA 的按鍵輸入(t6)

講了老半天的圖像,雖說是對著MM,但大家一定也有點煩了,我們現在就換個方向,來看看GBA的控制.

... ...
// 按鍵控制
#define KEY_A 1
#define KEY_B 2
#define KEY_SELECT 4
#define KEY_START 8
#define KEY_RIGHT 16
#define KEY_LEFT 32
#define KEY_UP 64
#define KEY_DOWN 128
#define KEY_R 256
#define KEY_L 512
volatile u32* KEYS = (volatile u32*)0x04000130;

// 包含圖像調色板和數據的頭文件
#include "gfx/image.h"

// ----------- 全局變數 --------
// 圖像緩沖區
u16* video_buffer=(u16*)M5_VRAM;
// 圖像顯示坐標
int img_x,img_y;

// ----------- 函數定義 ---------
// 按鍵控制
void KeyAction();
... ...
// ----------- 主程序 ------------
int main()
{

// 設置屏幕模式,這里使用MODE_5
SetMode (MODE_5 | BG2_ENABLE);

while(1)
{
// 處理按鍵事件
KeyAction();
// 在背景層畫圖,image是在"image.h"定義的圖像數據數組名
Draw(img_x,img_y,96,64,image,video_buffer);

WaitSync();
SwapScreen();
}
}

// 處理按鍵事件
void KeyAction()
{
// 上方向鍵
if(! ( (*KEYS) & KEY_UP) )
{
img_y+=5;
}

// 下方向鍵
if(! ( (*KEYS) & KEY_DOWN) )
{
img_y-=5;
}
}
eturn(0);
九. 簡單聲音輸出(t7)

Simple is the Best(簡潔至上),這里我們使用一個現成的聲音模塊(Troff Player,by Vova & Serge).這里還要用到一個轉換工具< MOD2GBA >,用來把MOD音樂文件轉換成GBA的 *.c / *.h 聲音數據文件.MOD和MIDI差不多,但支持更多更強的效果.MOD可以由konvertor這個強大的軟體轉換而來.

// MOD數據文件
#include "song_data.h"
// MOD播放函數文件
#include "modplayer.h"

// ----------- 主程序 ------------
int main()
{
//設置屏幕模式,這里使用MODE_4
SetMode (MODE_4 | BG2_ENABLE);

// 初始化聲音(聲道數,音量)
InitSound(2, 7);
// 初始化音樂(節拍,循環)
InitSong(20000, 0);

while(1)
{
// 更新音樂播放狀態
UpdateSong();
}
}

OK,就這么EZ.

十. 用圖塊建立可滾動/縮放/旋轉的背景(t8)

這一節主要是源程序中注釋為主,這里就不詳細說明了."gba.h"包含基本宏定義,"maths.h"是sin/cos乘256後的值數組,"main.h"包括了我們定義背景結構及操作背景的函數.

程序中的地圖背景是由不同的圖塊所構成,而這些圖塊統一緊挨著放在一個圖像文件,這樣每個圖塊就會有一個索引號;地圖信息只要記錄這張地圖里共有多少個 單位(圖塊)以及每個單位對應的圖塊索引號就OK了,在例子中"gfx/tiles.h"就是圖塊大本營,而"gfx/level1.h"則是圖塊索引排列表.地圖工具為"map editor beta 4".

背景的滾動/縮放/旋轉是通過一系列的簡單數學計算,修改GBA系統提供的一些背景屬性來完成,因為是由硬體來完成背景的操作(MODE_1),所以速度很快,我還有個MODE_5下直接修改像素點位置來完成旋轉的常式,待會兒大家可以比較一下.

F. c璇璦涓鐨勬ā鏉跨被鐨勫畾涔夋槸浠涔堟剰鎬濓紵

榪欐槸寤虹珛妯℃澘鐨勫滻瀹氬艦寮忥紝template鍗蟲ā鏉匡紝class鎸囩被鍒錛孴鏄綾誨埆鐨勭粺縐幫紝鍙浠ヤ嬌鐢ㄧ殑鏁版嵁綾誨瀷鏈塱nt銆乧har錛宖loat錛宒ouble絳夌瓑銆

涓句釜渚嬪瓙錛

template < typename T >
T min( T a, T b )
{
return a > b ? b : a;
}
榪欎釜 max 鍑芥暟灝辨槸涓涓妯℃澘鍑芥暟錛屽畠鍙浠ヤ紶鍏ヤ竴涓 鈥滅被鍨嬧濈殑鍙傛暟錛屼互渚垮疄鐜頒換鎰忕被鍨嬫眰鏈灝忓肩殑鏁堟灉銆

鎵╁睍璧勬枡錛

鍑芥暟妯℃澘鐨勫畾涔夛細

鍑芥暟妯℃澘鐨勫0鏄庢槸鍦ㄥ叧閿瀛 template 鍚庤窡闅忎竴涓鎴栧氫釜妯℃澘鍦ㄥ皷鎷寮у唴鐨勫弬鏁板拰鍘熷瀷銆備笌鏅閫氬嚱鏁扮浉瀵癸紝瀹冮氬父鏄鍦ㄤ竴涓杞鎹㈠崟鍏冮噷澹版槑錛岃屽湪鍙︿竴涓鍗曞厓涓瀹氫箟錛屽彲浠ュ湪鏌愪釜澶存枃浠朵腑瀹氫箟妯℃澘銆備緥濡傦細

// file max.h

#ifndef MAX_INCLUDED

#define MAX_INCLUDED

template <class T>

T max(T t1, T t2)

{

return (t1 > t2) ? t1 : t2;

}

#endif

瀹氫箟 T 浣滀負妯℃澘鍙傛暟錛屾垨鑰呮槸鍗犱綅絎︼紝褰撳疄渚嬪寲 max()鏃訛紝瀹冨皢鏇誇唬鍏蜂綋鐨勬暟鎹綾誨瀷銆俶ax 鏄鍑芥暟鍚嶏紝t1鍜宼2鏄鍏跺弬鏁幫紝榪斿洖鍊肩殑綾誨瀷涓 T銆傚彲浠ュ儚浣跨敤鏅閫氱殑鍑芥暟閭f牱浣跨敤榪欎釜 max()銆傜紪璇戝櫒鎸夌収鎵浣跨敤鐨勬暟鎹綾誨瀷鑷鍔ㄤ駭鐢熺浉搴旂殑妯℃澘鐗瑰寲錛屾垨鑰呰存槸瀹炰緥錛

int n=10,m=16;

int highest = max(n,m); // 浜х敓 int 鐗堟湰

std::complex c1, c2;

//.. 緇 c1,c2 璧嬪

std::complex higher=max(c1,c2); // complex 鐗堟湰

鍙傝冭祫鏂欐潵婧愶細鐧懼害鐧劇戔斿嚱鏁版ā鏉

G. 什麼是PSOS

pSOS系統結構
pSOS是一個由標准軟組件組成的,可剪裁的實時操作系統。其系統結構如圖2.1所示

,它分為內核層、系統服務層、用戶層。
1. 內核層
pSOS內核負責任務的管理與調度、任務間通信、內存管理、實時時鍾管理、中斷服

務;可以動態生成或刪除任務、內存區、消息隊列、信號燈等系統對象;實現了基於優

先級的、選擇可搶占的任務調度演算法,並提供了可選的時間片輪轉調度。pSOS Kernel還

提供了任務建間通信機制及同步、互斥手段,如消息、信號燈、事件、非同步信號等。
pSOS操作系統在Kernel層中將與具體硬體有關的操作放在一個模塊中,對系統服務層

以上屏蔽了具體的硬體特性,從而使得pSOS很方便地從支持Intel 80x86系列轉到支持MC

68XXX系列,並且在系統服務層上對不同應用系統不同用戶提供標準的軟組件如PNA+、
PHILE+等。
2. 系統服務層
pSOS系統服務層包括PNA+、PRPC+、PHILE+等組件。PNA+實現了完整的基於流的TCP

/IP協議集,並具有良好的實時性能,網路組件內中斷屏蔽時間不大於內核模塊中斷屏蔽時

間。PRPC+提供了遠程調用庫,支持用戶建立一個分布式應用系統。PHILE+提供了文件系

統管理和對塊存儲設備的管理。PREPC+提供了標準的C、C++庫,支持用戶使用C、C++語言

編寫應用程序。
由於pSOS內核屏蔽了具體的硬體特性,因此,pSOS系統服務層的軟組件是標準的、與

硬體無關的。這意味著pSOS各種版本,無論是對80X86系列還是MC68XXX系列,其系統服務

層各組件是標準的、同一的,這減少了軟體維護工作,增強了軟體可移植性。
每個軟組件都包含一系列的系統調用。對用戶而言,這些系統調用就象一個個可重入

的C函數,然而它們卻是用戶進入pSOS內核的唯一手段。
3. 用戶層
用戶指的是用戶編寫的應用程序,它們是以任務的形式出現的。任務通過發系統調

用而進入pSOS內核,並為pSOS內核所管理和調度。
pSOS為用戶還提供了一個集成式的開發環境(IDE)。pSOS_IDE可駐留於UNIX或DOS

環境下,它包括C和C++優化編譯器、CPU和pSOS模擬模擬和DEBUG功能。
pSOS內核機制
§3.1 幾個基本概念
3.1.1 任務
在實時操作系統中,任務是參與資源競爭(如CPU、Memory、I/O devices等)
的基本單位。pSOS為每個任務構造了一個虛擬的、隔離的環境,從而在概念上,一個任務

與另一個任務之間可以相互並行、獨立地執行。任務與任務之間的切換、任務之間的通

信都是通過發系統調用(在有些情況下是通過ISR)進入pSOS Kernel,由pSOS Kernel完

成的。
pSOS系統中任務包括系統任務和用戶任務兩類。關於用戶任務的劃分並沒有一個固

定的法則,但很明顯,劃分太多將導致任務間的切換過於頻繁,系統開銷太大,劃分太少又

會導致實時性和並行性下降,從而影響系統的效率。一般說來,功能模塊A與功能模塊B是

分開為兩個任務還是合為一個任務可以從是否具有時間相關性、優先性、邏輯特性和功

能耦合等幾個方面考慮。
3.1.2 優先順序
每個任務都有一個優先順序。pSOS系統支持0~255級優先順序,0級最低,255級最高。0級

專為IDLE任務所有,240~255級為系統所用。在運行時,任務(包括系統任務)的優先順序

可以通過t_setpri系統調用改變。
3.1.3 任務狀態
pSOS下任務具有三種可能狀態並處於這三個狀態之一。只有通過任務本身或其他任

務、ISR對pSOS內核所作的系統調用才能改變任務狀態。從宏觀角度看,一個多任務應用

通過一系列到pSOS的系統調用迫使pSOS內核改變受影響任務而從運行一個任務到運行另

一任務向前發展的。
對於pSOS kernel,任務在創建前或被刪除後是不存在的。被創建的任務在能夠運行

前必須被啟動。一旦啟動後,一個任務通常處於下面三個狀態之一:
①Executing (Ready)就緒
②Running運行
③Blocked阻塞
就緒任務是未被阻塞可運行的,只等待高優先順序任務釋放CPU的任務。由於一個任務

只能由正運行的任務通過調用來被啟動,而且任何時刻只能有一個正在運行的任務,所

以新任務總是從就緒態開始。
運行態任務是正在使用CPU的就緒任務, 系統只能有一個running任務。一般runni

ng任務是所有就緒任務中優先順序最高的,但也有例外。
任務是由自身特定活動而變為阻塞的,通常是系統調用引起調用任務進入等待狀態

的。所以任務不可能從ready態到blocked態,因為只有運行任務才能執行系統調用。
3.1.4 任務控制塊
任務控制塊TCB是pSOS內核建立並維護的一個系統數據結構,它包含了pSOS Kernel調

度與管理任務所需的一切信息,如任務名、優先順序、剩餘時間片數、當前寄存器狀態等。

在有的RTOS中,任務的狀態與任務TCB所處的隊列是等同的。pSOS操作系統將二者分

為兩個概念,例如任務處於阻塞狀態,但它的TCB卻處於消息等待隊列、信號燈等待隊列、

內存等待隊列、超時隊列之一。
pSOS啟動時,將根據Configuration Table中的參數kc_ntask建立一個包含kc_ntask

個TCB塊的TCB池,它表示最大並行任務數。在創建一個任務時,分配一個TCB給該任務,在

撤銷一個任務時,該TCB將被收回。
3.1.5 對象、對象名及ID號
pSOS Kernel是一個面向對象的操作系統內核,pSOS系統中對象包括任務、memory
regions、memory partitions、消息隊列和信號燈。
對象名由用戶定義(4位ASCII字元),並且在該對象創建時作為系統調用obj_CREAT
E
的一個人口參數傳給pSOS Kernel。pSOS Kernel反過來賦予該對象一個唯一的32位ID號

。除obj_CREATE和obj_IDENT外,所有涉及對象的系統調用都要用到對象ID號。
創建對象的任務通過obj_CREATE就已經知道了該對象的ID號,其餘任務可通過obj_
IDENT或通過全局變數(如果已經為該任務的ID號建立了一個全局變數的話)獲取該對象

的ID號。對象ID號隱含了該對象控制塊(如TCB、QCB)的位置信息,這一位置信息被pSO
S
Kernel用於對該對象的管理和操作,如掛起/解掛一個任務、刪除一個消息隊列等。
3.1.6 任務模式字Mode word.
每個任務帶有一個mode word,用來改變調度決策或執行環境。主要有以下四個參


Preemption Enabled/Disabled.
Roundrobin Enabled/Disabled
Interupts Enabled/Disabled.
ASR Enabled/Disabled: 每個任務有一個通過as-catoh建立起來的非同步信號服務例

程ASR。非同步信號類似於軟體中斷。當ASR位為1時as-catch所指向的任務將會被改變執行

路徑,先執行ASR,再返回原執行點。
§3.2 任務調度
3.2.1 影響動態調度效果的兩個因素
pSOS採用優先順序+時間片的調度方式。有兩個因素將影響動態調度的效果:一是優先

級可變(通過t_setpri系統調用改變任務的優先順序);二是任務模式字中的preemption

bit位和roundrobin bit位。preemption bit位決定不同優先順序的任務是否可搶占,並和

roundrobin bit位一起決定任務的時間片輪轉是否有效。
3.2.2 引起任務調度的原因及結果
pSOS系統中引起調度的原因有兩條:
1. 在輪轉方式下時間片到
2. pSOS系統調用引發任務調度。該系統調用可能是ISR發出的,也可能是某個任務發出的

pSOS任務調度的結果有兩種:
1. 引起運行任務切換,這指的是
2. 不引起運行任務切換,這指的是
不論任務調度是否引發運行任務切換,都有可能引起一個或多個任務狀態變遷。
3.2.3 運行任務的切換
一、何時切換
下面三種情況將引發運行任務切換:
1. 在時間片輪轉方式下(此時任務模式字的roundrobin bit與preemption bit均為
enable),運行任務Task A的時間片用完,且Ready隊列中有相同優先順序的其它任務,則

Task A退出運行。
2. 在運行任務Task A的Mode word的preemption bit位為enable的前提下,若Task A發出

的某條相同調用引發一個優先順序高於Task A的任務Task B從Block狀態進入Reary狀態,則

將Task B投入運行。
3. ISR使用I_RETURN系統調用,則ISR退出運行,pSOS Kernel選擇Ready隊列中優先順序最高

的任務投入運行(這一任務並不一定是被ISR打斷的前運行任務)。
二、如何切換
上述三類運行任務的切換,其具體的pSOS Kernel運作過程並非完全一樣,但彼此之間

差別不大。為了簡單起見,我們以
為例對切換過程作一簡單敘述。這一過程可細分為4個步驟:
1. 任務A運行信息保存(_t_save proc far)
這一過程主要完成修改系統工作標志,保存切換點地址及運行信息、任務A棧調


指針保存、棧切換、參數及返址入棧等一系列工作。
2.任務A入就緒隊列(void t_in_chain)
這一過程將任務A的TCB塊按優先順序順序插入就緒隊列。
3.選擇一個高優先順序任務B(void t_choice( ))
按一定演算法從就緒隊列中選出最高優先順序任務B的TCB塊,並使運行指針指向它。

4.將任務B投入運行(_t_run proc far)
從系統棧切換到任務B棧,用任務B的TCB塊中保存的信息恢復上次運行被打斷的

,恢
復任務運行環境,於是任務B開始繼續運行。
圖3.1反映了典型任務切換過程中CPU控制權的轉移、各堆棧活動生命期、任務活動

生命期等信息。圖中
t1,t4為切換點 t2,t3為開/關中斷
Tsch=t4-t1 // Tsch為任務切換時間
Tforbid=t3-t2 // Tforbid為中斷禁止時間
它們是實時操作系統最重要的兩個性能指標。

熱點內容
sql資料庫pdf 發布:2025-01-07 10:24:08 瀏覽:405
指紋忘記密碼怎麼辦 發布:2025-01-07 10:15:37 瀏覽:638
流量熱點如何取消密碼 發布:2025-01-07 10:02:43 瀏覽:5
安卓手機的天氣預報在哪裡 發布:2025-01-07 10:01:17 瀏覽:743
linux配置文件路徑 發布:2025-01-07 09:58:47 瀏覽:917
手機解鎖密碼什麼改 發布:2025-01-07 09:55:52 瀏覽:315
阿里少兒編程大賽 發布:2025-01-07 09:55:49 瀏覽:440
安卓版美易剪輯形狀在哪裡 發布:2025-01-07 09:54:25 瀏覽:201
奇偶排序演算法 發布:2025-01-07 09:53:37 瀏覽:933
cmd命令如何解壓zip 發布:2025-01-07 09:53:36 瀏覽:80