quake是id software公司推出一款風迷全球的fps遊戲.至今為止已經發展到了第三代,而且作為乙個優良的遊戲引擎,它也被大量的運用到其他公司開發的遊戲當中.例如我們所熟知的cs,它就是在quake2引擎上改良而來的.雖然裡面的程式碼實現並不完全相同,但是整體框架還是quake2的,只要是稍微接觸過quake引擎的人都很容易看得出來.(它是那麼的經典,以至於一直沿用到今天,個人認為它是遊戲領域大型結構化設計最好的乙個典範.現在很多遊戲已經改用物件導向的程式設計方法來編寫,但quake的影響卻是深遠的.包括前段時間洩露的cs2原始碼,它的架構仍然保留著些許多quake風格.)
很多人告述我id software 很早之前就已經公開了 quake 3全部原始碼.這裡我要告述大家,其實id公開的並不是所有的原始碼,而僅僅是邏輯層程式碼,你想想看哪個公司會笨到將自己的核心技術傾囊倒出,這些可是他們吃飯的本錢啊!邏輯層的程式碼只包括了ui,ai等實現.像影象渲染,網路傳輸部分均沒有給出.你看到的唯有函式的宣告部分.因此要徹底研究quake3就必須獲得這部分的原始碼,可上哪去找呢?令人興奮的是,早前已經有牛人通過逆向工程的方法將quake3核心程式碼整理出來,做了乙個仿quake3引擎(dusk3d).我下面的分析就是根據他的程式碼來寫的,雖然跟真實的quake3引擎比較也許會有些出入,但我相信那並不影響我們去理解quake3.
類如大多數win32應用程式,quake的win32部分也是從winmain函式進入的.邏輯層被分成了cgame,game,ui,q3_ui四個主要的模組.(這幾個模組被做成dll程式,由引擎負著載入它們)quake中dll與引擎之間的互動通過vmmain和dllentry這兩函式來完成.
vmmain作為引擎程式訪問邏輯層dll的介面,引擎使用vm_call函式呼叫邏輯層dll引出的vmmain,然後vmmain再根據引擎提供的要訪問函式的索引號查詢到相應的函式實現.
dllentry是邏輯層dll接收引擎系統函式的介面,邏輯層dll利用它呼叫引擎專門提供給他的系統函式.
sv_gamesystemcalls是引擎提供給game模組的系統函式呼叫介面.cl_cgamesystemcalls提供給cgame模組,而cl_uisystemcalls則是提供給ui模組使用.上述這幾個函式的實現方法與vmmain十分相似,它們都是通過乙個switch語句根據傳入的索引號跳轉到指定的函式處.
以下是dllentry函式的實現,可以看到它只有乙個引數,乙個函式指標,這個函式指標就是指向引擎提供給邏輯層模組的介面函式,例如sv_gamesystemcalls:
static int (cdecl *syscall)( int arg, ... ) = (int (cdecl *)( int, ...))-1;
void dllentry( int (cdecl *syscallptr)( int arg,... ) )
常見的trap打頭的函式實際上是呼叫了引擎程式碼的,具體如下:
void trap_printf( const char *fmt )
了解了呼叫規則後,我們就可以比較輕鬆地跟蹤除錯quake原始碼啦.
Quake原始碼分析 草稿 3
訊息處理 我把quake的訊息分為兩類,一種是常用輸入裝置產生的訊息,譬如keyboard,mouse,joystick等.另一種就是網路或本地傳輸資料報時引發的訊息.引擎中 eventloop 函式負責將抓獲到的訊息根據事件的型別分發給對應的處理函式,getevent 可以從 eventqueue...
Quake原始碼分析 草稿 3
訊息處理 我把quake的訊息分為兩類,一種是常用輸入裝置產生的訊息,譬如keyboard,mouse,joystick等.另一種就是網路或本地傳輸資料報時引發的訊息.引擎中com eventloop 函式負責將抓獲到的訊息根據事件的型別分發給對應的處理函式,com getevent 可以從com ...
Quake原始碼分析 草稿 4
quake網路部分總結 1 網路部分被分為接收和傳送兩個部分.2 傳送部份被分為本地資料報傳輸和異地資料報傳輸兩個部分.3 本地封包傳輸由net sendloopbackpacket 負責.4 異地封包傳輸由sys sendpacket 負責.5 資料報傳輸又可以分為單包傳輸和多包傳輸.6 net ...