最近,我在“大眾軟件”上看到一則關(guān)于軟件“變速齒輪”的報道。我很少上網(wǎng),所以對這方面了解比較少,不知道它在網(wǎng)上已經(jīng)流行好幾個(gè)月了。當時(shí)的感覺(jué)就是太驚奇了,很佩服王榮先生是怎么做到如此神奇的事,尤其是他如何保證各種游戲的兼容,他如何知道不同游戲對時(shí)間的處理。我立刻上網(wǎng)DOWN了個(gè)0.22b版,在試用的過(guò)程中,我發(fā)現“變速齒輪”不但可以加速游戲,實(shí)際上,它可以加速任何windows程序(從某種程度上),我逐漸認識到它的工作原理,不一定對,僅是猜測而已。先聲明一點(diǎn),我是使用UNIX的,并不是很了解windows編程,所以只能給出概念上大體的認識,而無(wú)法說(shuō)出具體的實(shí)現辦法。
首先,先看看計算機是如何有時(shí)間概念的。在主板上有一個(gè)時(shí)鐘晶振,依靠電池供電,本質(zhì)上就是一塊電子表。計算機軟件中所有的時(shí)間概念,歸根結底都來(lái)自著(zhù)個(gè)“硬件時(shí)間”,換句話(huà)說(shuō),如果這個(gè)時(shí)間不對,則任何運行在該主板上的程序對時(shí)間的處理都不可能正確。(包擴各種操作系統)
那么,操作系統是如何知道這個(gè)時(shí)間的呢?這是因為這個(gè)時(shí)鐘每過(guò)一定時(shí)間都會(huì )產(chǎn)生一個(gè)硬件中斷(INT)操作系統可以截取這個(gè)中斷并做相應的處理,從而獲得時(shí)間的概念。好象是20ms產(chǎn)生一次中斷,一秒鐘50次。具體的中斷號我忘了,就稱(chēng)為 INT A 吧。對Dos而言,它在啟動(dòng)時(shí)就準備好了對INT A的中斷處理程序(Dos核心的一部分),當我們使用DOs的時(shí)候,在提示符狀態(tài)下,即使不做任何操作,Dos內部在一秒鐘時(shí)間內,也會(huì )接受50次INT A,執行50次中斷處理程序。只是這一過(guò)程在幕后完成,我們無(wú)法感受到。Dos的中斷處理程序所做的,就是讓Dos能夠了解當前的時(shí)間。(如保留當前日期,時(shí)間在內部變量中等操作)。但很重要的一點(diǎn),在INT A中斷處理程序的末尾,又調用INT B。
INT B是Dos為用戶(hù)保留的軟中斷,在缺省情況下,Dos的INT B中斷處理程序立即返回,不做任何事。而
用戶(hù)可以編寫(xiě)自己的INT B中斷處理程序定時(shí)處理自己的操作,然后把它替換Dos原來(lái)的空INT B中斷程序。比如我有一個(gè)程序需要在12:00運行,一種方法是寫(xiě)如下代碼:
for(;;){
if(時(shí)間是12:00) break;
sleep(5); /*休息5秒鐘,這句在Dos中沒(méi)有,意為讓程序不做任何事,只是等待一段時(shí)間*/
}
{具體的處理程序}
然后在提示符狀態(tài)下運行。因為Dos沒(méi)有多用戶(hù)的概念,在程序12:00退出以前,無(wú)法在使用這臺機器。另一種方法是,把要運行的程序寫(xiě)成TSR(長(cháng)駐內存程序),運行后執行代碼長(cháng)駐在內存中,程序本身返回提示符,供用戶(hù)使用。那么該執行碼如何保證在12:00被執行呢,就要靠INT B,在長(cháng)駐該程序時(shí),也要編寫(xiě)新的INT B中斷處理程序,內容大概是:
{屏蔽INT B中斷} /*這一步是因為Dos的大部分中斷是不可重入的,
即在中斷還未處理完時(shí),再次*/
/*被中斷,這一般會(huì )讓Dos死掉*/
{執行舊的INT B中斷處理程序} /*這一步的目的是防止自己的TSR影響其他TSR程序*/
if(時(shí)間是12:00){
把處理轉向TSR程序的入口;
} else {
{恢復被屏蔽的中斷}
退出;
}
綜合上面講到的,Dos下的時(shí)間處理大概是:
機器時(shí)間------->INT A(操作系統用)-------->INT B(用戶(hù)用)-------->TSR程序
當然,由于Dos對運行級別幾乎沒(méi)有控制,用戶(hù)也可以繞過(guò)INT A,INT B直接訪(fǎng)問(wèn)硬件。這時(shí)我們即使改變操作系統的時(shí)間,用戶(hù)程序也能得到正確的時(shí)間。
在windows中,情況也很類(lèi)似。但程序不會(huì )直接訪(fǎng)問(wèn)硬件,而是通過(guò)叫VxD的虛擬設備驅動(dòng)程序來(lái)工作。由VxD來(lái)和硬件打交道,而應用程序只和VxD交流信息。對時(shí)鐘中斷的處理也是一樣,windows有專(zhuān)門(mén)的時(shí)鐘虛擬設備驅動(dòng)來(lái)捕獲來(lái)自晶振的硬件中斷,并為windows提供時(shí)間和定時(shí)的功能。這與Dos下的INT A功能基本是一致的,但更強大,功能更廣。
我們在來(lái)看應用程序需要怎樣的時(shí)間處理機制。一個(gè)典型的游戲,如射擊游戲,如果沒(méi)有時(shí)間控制,敵人的飛機如果要連開(kāi)10槍?zhuān)绦驊撌牵?br>for(i=0;i<10;i++){
開(kāi)槍?zhuān)?br>}
但是有一個(gè)問(wèn)題,機器的速度可能太快,以至于只需要0.1秒十槍就完成了,另外在不同的機器上,這段程會(huì )有不同的運行時(shí)間。為了解決這個(gè)問(wèn)題,我們改進(jìn)這段程序:
for(i=0;i<10;i++){
開(kāi)槍?zhuān)?br>sleep(1); /*休息1秒,不做任何事*/
}
這樣我們至少保證一秒只開(kāi)一槍。但還有一個(gè)問(wèn)題,就是可能屏幕上有多個(gè)敵人,不可能在一個(gè)敵人開(kāi)10槍的過(guò)程中其他敵人不動(dòng)(而且自己也不動(dòng))。所以我認為,一般的游戲程序都是用定時(shí)器來(lái)實(shí)現主要功能的。即先為每一種動(dòng)作編寫(xiě)相應的處理程序,如開(kāi)槍?zhuān)苿?dòng)等,在為每個(gè)對象申請一個(gè)定時(shí)器,一旦定時(shí)器的時(shí)間到,就激活該對象相應動(dòng)作的程序代碼。如屏幕上的十個(gè)敵人對應十個(gè)定時(shí)器,定時(shí)器互不干涉,哪個(gè)時(shí)間到轉向哪個(gè)處理程序,控制他是否該移動(dòng)或射擊。至于定時(shí)器的創(chuàng )建,由應用程序向系統申請。
|--->用戶(hù)定時(shí)器1------->用戶(hù)程序1
|--->用戶(hù)定時(shí)器2------->用戶(hù)程序2
機器時(shí)間------>windows的時(shí)鐘VxD---|--->用戶(hù)定時(shí)器3------->用戶(hù)程序3
|--->系統接口------->系統應用
這種機制可以保證星際爭霸中的小狗在P100上和在PIII上奔跑的速度一樣快,前提是這兩臺機器的硬件時(shí)間是一樣準的,但是,如果有一臺機器的時(shí)鐘快或慢了,那問(wèn)題就有變化了。(注意,這里的快或慢,并不是指兩臺機器的時(shí)間不一樣,而是指在相同的現實(shí)時(shí)間下,他們產(chǎn)生硬件中斷的次數不一樣)
那么,說(shuō)了這么多,我認為“變速齒輪”的工作原理,就是修改用戶(hù)申請的windows定時(shí)器中的等待時(shí)間。我不太了解windows編程,不好說(shuō)這種修改是如何實(shí)現的。他沒(méi)有修改VxD因為windows系統的時(shí)間并沒(méi)有因為啟動(dòng)“變速齒輪”而跑快或跑慢,某些應用,如雙擊桌面圖標時(shí)的間隔時(shí)間上的設定(即兩次擊鼠標的間隔時(shí)間多長(cháng)以?xún)炔潘闶恰半p擊”)也沒(méi)有變。通俗的描述是:在啟動(dòng)“變速齒輪”后,當應用程序(特別是游戲)向windows申請定時(shí)器時(shí),“變速齒輪”修改了申請的等待時(shí)間參數,因次改變了程序正常的定時(shí),才使程序有了不正長(cháng)的
速度(這個(gè)結論只是猜的)。只所以這樣猜,是因為對已經(jīng)啟動(dòng)的程序,他并不能改變速度,而只能先啟動(dòng)“變速齒輪”,再運行程序。另外,某些系統接口,也是無(wú)法修改的。
所以,一旦啟動(dòng)“變速齒輪”,所有應用程序(申請了定時(shí)器,并要依靠定時(shí)器來(lái)做一些操作的程序)都會(huì )受到他的影響。在Word中,等待輸入的光標會(huì )因為調成了加速而更快的閃動(dòng),各種提示信息的出現時(shí)間會(huì )變快(或變慢)很多,最夸張的是,當把速度調成最慢時(shí),在同一位置,間隔十秒鐘擊一次鼠標會(huì )被系統認為是雙擊(發(fā)生在應用程序內,而不是桌面上)
我很佩服王榮先生的想象力和編程能力?!白兯冽X輪”的出現,證明在虛擬的世界里:沒(méi)有做不到的,只有想不到的。
聯(lián)系客服