乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      怎么制作游戲修改器

       昵稱10587962 2012-08-25
      游戲修改器制作-黑客入門 
      
      
      工具:SoftICE、金山游俠2002、VC++7.0、PE查看器、SPY++ 
      測試平臺:Window2000 Professional SP2 
      
      
      首先我介紹一下將會用到的工具: 
      1、 SoftICE(不用多說了吧,我想你應(yīng)該會用) 
      2、 金山游俠2002(這個你也應(yīng)該會用) 
      3、 VC++7.0(不要求你一定會用,但至少應(yīng)該會一種編程工具) 
      4、 PE查看器(你可以隨意找一個,沒有也沒關(guān)系,我會教你用SoftICE查看) 
      5、 SPY++(VC里的一個查看程序信息的工具,你可以和別的,比如Delphi和C++Builder的WinSight32) 
      
      
      然后就是你應(yīng)該會的知識: 
      1、 匯編基礎(chǔ) 
      2、 一些編程基礎(chǔ),至少應(yīng)該看懂我介紹的幾個API函數(shù) 
      3、 PE文件結(jié)構(gòu)的基礎(chǔ),不會也沒關(guān)系,我會解釋給你 
      
      
      以上幾點(diǎn)你都具備了的話我們就可以開始了。 
      
      
      我來介紹一下我要教給你的東西。想必大家都玩過PC游吧,那么也一定用過一些專用的游戲修改器吧,比如暗黑,紅警,大富翁這些經(jīng)典的游戲都有它們專用的修改器,注意,我說的不是FPE之類的通用修改工具。 
      你試沒試過用金山游俠修改紅警二的金錢?如果有的話你應(yīng)該知道每玩一次就要改一次,因?yàn)檫@個游戲是動態(tài)分配內(nèi)存的,每次重新開始都會改變。所以你會選擇到網(wǎng)上去下載一個專用的修改器,那么你有沒有想過自己做一上呢?想過?那你為什么不做?什么不會?那就好辦了,看了這篇教程你就會了:D費(fèi)話少說,我來講一下原理。 
      有一些經(jīng)常修改游的朋友一定會知道,不論游戲中“物品”的內(nèi)存地址是否是動態(tài)的,物品與物品之間相隔的距離都是不變的,我拿“楚留香新傳”為例,我先用金山游俠查找內(nèi)力值的內(nèi)存地址,找到的結(jié)果是:79F695C,再查找物品“金創(chuàng)藥”的地址是:328D1DC,現(xiàn)在我用79F695C減去328D1DC,得到:4769780,這個數(shù)就是內(nèi)力值與金創(chuàng)藥的偏移值,沒看懂?接著看呀,我還沒說完呢,現(xiàn)在重新再運(yùn)行游戲,查找內(nèi)力值的地址,得到:798695C再查找金創(chuàng)藥得到的地址是:321D1DC,兩個值的內(nèi)存地址都改變了,但是用你內(nèi)力值的地址減去金創(chuàng)藥的地址得到的結(jié)果是什么?沒錯,還是4769780,也就是說,無論這兩個值的內(nèi)存地址變成多少,它們之間的距離是永遠(yuǎn)不變的,不光是這個游戲,一般的游戲都是,至少我沒見過不是的:D 
      上面講的東西總結(jié)出一個結(jié)論,那就是我們只要得到這兩個地址中的任何一個,就可以得到另外一個,只要你知道它們之間的偏移量是多少。 
      我們第一步要做的就是得到這個地址,但是內(nèi)存中的地址是動態(tài)改變的,得到也沒有用,這里我就教你把它變成靜態(tài)的,叫它永遠(yuǎn)都不變!我繼續(xù)拿“楚留香新傳”為例,如果你有這個游的話就跟我一起做,沒有的也沒關(guān)系,只要看懂這幾個步驟就行了。開工! 
      首先進(jìn)入游戲,查找內(nèi)值的地址,得到的是:798695C(不知道為什么這上游并不是每次重起都改變內(nèi)存地址),按Ctrl+D打開SoftICE,下命令:BPM 798695C W(寫這個地址時(shí)則中斷),回到游戲中,打開人物屬性面板,游戲中斷了,在SofitICE中你會看到這條指令: 
      
      
      0047EB17 MOV EAX [EDX+000003F4] 下命令:D EDX+3F4將看到內(nèi)力值 
      0047EB1D PUSH EAX 
      ……………………………… 
      ……………………………… 
      從上面可看出0047EB17處的指令是將內(nèi)力值的指針?biāo)偷紼AX寄存器中,這是一個典型的尋址方式,設(shè)想一下,我們是到了EDX中的基址,那么無論什么時(shí)候只要用EDX+3F4就可以輕松的得到內(nèi)力值的地址,因?yàn)?00003F4是一個常量,它是不會改變的,改變的只是EDX中的地址,所以只要有辦法得到EDX中的值就什么都好辦了,你明白了沒有?如果還是不懂,那么請?jiān)倏匆槐椤,F(xiàn)在要做的就是如何得到這個值,下面我教給你如何做: 
      我的辦法就是設(shè)計(jì)一段代碼,把EDX中的值存放到一個地址中,然后運(yùn)行這段代碼,再返回游戲的原有指令繼續(xù)執(zhí)行,什么?補(bǔ)丁技術(shù)?SMC?隨你怎么說啦,只要運(yùn)行正常就一切OK啦:D 
      實(shí)際操作: 
      首先在程序中找一段空白處來存放我們設(shè)計(jì)的代碼,很簡單,只要懂得一些PE文件結(jié)構(gòu)的朋友都會知道,一般在EXE文件的數(shù)據(jù)段(.data段)的結(jié)尾都會有一段緩沖區(qū),我們可以在這段區(qū)域中寫任何東西,當(dāng)然你也可以用“90大法”找一段空白區(qū),但我還是推薦你用我教給你的方法。上同我提到,如果你沒有PE文件查看工具我可以教你用SoftICE查看,而且很簡單,只要一個命令:MAP32 “模塊名”,看一下我是怎么做的你就知道了。 
      Ctrl+D呼收出SoftICE,然后下命令:MAP32 CrhChs,這時(shí)你應(yīng)該看到EXE各個段的信息,我們要注意的只是.data段,既然要找的是數(shù)據(jù)段的結(jié)尾,那么我們就從下一個段開始向上找,如下: 
      .data 004FB000 
      .rsrc 00507000 
      .data的下一個段是.rsrc段,它是從00507000開始的,也就是說以00507000為基礎(chǔ)向上一個字節(jié)就是數(shù)據(jù)段的結(jié)尾,我所擇從00506950處開始寫代碼,說了這么半天那么我們的代碼到底是什么樣子呢?修改后的指令又是什么樣的呢?別急,請看下面: 
      修改0047EB17后代碼: 
      0047EB17 JMP 00506950 //跳到我們的代碼中去執(zhí)行 
      0047EB1C NOP //由于這條指令原來的長度是6字節(jié),而修改后的長度是5個字節(jié),所以用一個空指令補(bǔ)上 
      0047EB1D PUSH EAX 
      
      
      //我們的代碼: 
      00506950 MOV DWORD PTR EAX,[EDX+00003F4] //恢復(fù)我們破壞的指令 
      00506956 MOV DWORD PTR [00506961],EDX //把EDX保存以00506961中去 
      0050695C JMP 0047EB1D //返回原來的指令去執(zhí)行 
      
      
      把上面的代碼用SoftICE的A命令寫入,OK! 
      現(xiàn)在我們試一下運(yùn)行的效果,你現(xiàn)在用金山游俠搜索一下內(nèi)力址的地址,什么又變了?那就地啦,它要是不變我們還用費(fèi)這么大勁兒嗎?記下這個地址返回到游戲中去,Ctrl+D呼出SoftICE,下命令 D *[00506961]+000003F4,在數(shù)據(jù)窗口看到什么了?呵呵,沒錯,看到了你剛才記住的那個地址,里面的數(shù)值正是內(nèi)力的值,試著改一下,回到游戲中,呵呵,內(nèi)力值變了吧:D 
      講到這里,我們的工作已經(jīng)完成了%90,但別高興的太早,后面的%10要遠(yuǎn)比前的%90花的時(shí)間長,因?yàn)槲覀円镁幊虒?shí)現(xiàn)這一切,因?yàn)槟悴荒苊看味枷駝偛拍菢幼鲆淮伟桑?
      現(xiàn)在我來說一下編程的步驟: 
      首先用FindWindow函數(shù)得到窗口句柄,然后用GetWindowThreadID函數(shù)從窗口句柄得到這個進(jìn)程的ID,接著用OpenProcess得到進(jìn)程的讀寫權(quán)限,最后用WriteProcessMemory和ReadProcessMemory讀寫內(nèi)存,然后。。。。呵呵,你的修改器就做成啦:D 
      下面是我抄寫以前寫的修改器源程序片斷,第一部分是動態(tài)寫入剛才的代碼,第二部分是讀取并修改內(nèi)力值,由于我沒有時(shí)間整理和測試,所以不能保證沒有錯誤,如果大家發(fā)現(xiàn)有遺漏的話,可以在QQ上給我留言或?qū)懶沤o我,代碼如下: 
      有幾點(diǎn)請大家注意: 
      1、 寫機(jī)器碼時(shí)要一個字節(jié)一個字節(jié)的寫 
      2、 注意要先寫入自己的代碼,然后再修改游中的指令(下面的代碼沒有這樣做,因?yàn)椴挥绊?,但是你?yīng)該注意這個問題) 
      
      
      #define MY_CODE5 0x00 
      #define MY_CODE6 0x90 
      //00506950 
      #define MY2_CODE1 0x8B 
      #define MY2_CODE2 0x82 //這部分是要寫入的機(jī)器碼的常量定義 
      #define MY2_CODE3 0xF4 
      #define MY2_CODE4 0x03 
      #define MY2_CODE5 0x00 
      #define MY2_CODE6 0x00 
      
      
      #define MY3_CODE1 0x89 
      #define MY3_CODE2 0x15 
      #define MY3_CODE3 0x61 
      #define MY3_CODE4 0x69 
      #define MY3_CODE5 0x50 
      #define MY3_CODE6 0x00 
      
      
      #define MY4_CODE1 0xE9 
      #define MY4_CODE2 0xBC 
      #define MY4_CODE3 0x81 
      #define MY4_CODE4 0xF7 
      #define MY4_CODE5 0xFF 
      //-----------------------------------------------------------------------------// 
      DWORD A1 =MY_CODE1; 
      DWORD A2 =MY_CODE2; 
      DWORD A3 =MY_CODE3; 
      DWORD A4 =MY_CODE4; 
      DWORD A5 =MY_CODE5; 
      DWORD A6 =MY_CODE6; 
      
      
      DWORD B1 =MY2_CODE1; 
      DWORD B2 =MY2_CODE2; 
      DWORD B3 =MY2_CODE3; //這部分是變量的定義 
      DWORD B4 =MY2_CODE4; 
      DWORD B5 =MY2_CODE5; 
      DWORD B6 =MY2_CODE6; 
      
      
      DWORD C1 =MY3_CODE1; 
      DWORD C2 =MY3_CODE2; 
      DWORD C3 =MY3_CODE3; 
      DWORD C4 =MY3_CODE4; 
      DWORD C5 =MY3_CODE5; 
      DWORD C6 =MY3_CODE6; 
      
      
      DWORD D1 =MY4_CODE1; 
      DWORD D2 =MY4_CODE2; 
      DWORD D3 =MY4_CODE3; 
      DWORD D4 =MY4_CODE4; 
      DWORD D5 =MY4_CODE5; 
      //--------------------------------------------------------------------------// 
      HWND hWnd =::FindWindow("CRHClass",NULL); //得到窗口句柄 
      if(hWnd ==FALSE) 
      MessageBox("游戲沒有運(yùn)行!"); 
      else 
      { 
      GetWindowThreadProcessId(hWnd,&hProcId); // 從窗口句柄得到進(jìn)程ID 
      HANDLE nOK =OpenProcess(PROCESS_ALL_ACCESS|PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ| 
      PROCESS_VM_WRITE,FALSE,hProcId); //打開進(jìn)程并得到讀與權(quán)限 
      if(nOK ==NULL) 
      MessageBox("打開進(jìn)程時(shí)出錯"); 
      else 
      { 
      //0047EB17 
      WriteProcessMemory(nOK,(LPVOID)0x0047EB17,&A1,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x0047EB18,&A2,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x0047EB19,&A3,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x0047EB1A,&A4,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x0047EB1B,&A5,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x0047EB1C,&A6,1,NULL); 
      //00506950 
      WriteProcessMemory(nOK,(LPVOID)0x00506950,&B1,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x00506951,&B2,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x00506952,&B3,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x00506953,&B4,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x00506954,&B5,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x00506955,&B6,1,NULL); 
      //第二句 
      WriteProcessMemory(nOK,(LPVOID)0x00506956,&C1,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x00506957,&C2,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x00506958,&C3,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x00506959,&C4,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x0050695A,&C5,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x0050695B,&C6,1,NULL); 
      //最后一句 
      WriteProcessMemory(nOK,(LPVOID)0x0050695C,&D1,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x0050695D,&D2,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x0050695E,&D3,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x0050695F,&D4,1,NULL); 
      WriteProcessMemory(nOK,(LPVOID)0x00506960,&D5,1,NULL); 
      
      
      CloseHandle(nOK); //關(guān)閉進(jìn)程句柄 
      } 
      } 
      } 
      ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
      //讀取并修改內(nèi)力值 
      DWORD hProcId; 
      HWND hWnd =::FindWindow("CRHClass",NULL); 
      if(hWnd ==FALSE) 
      MessageBox("No"); 
      else 
      { 
      GetWindowThreadProcessId(hWnd,&hProcId); 
      HANDLE nOK =OpenProcess(PROCESS_ALL_ACCESS|PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ| 
      PROCESS_VM_WRITE,FALSE,hProcId); 
      if(nOK ==NULL) 
      MessageBox("ProcNo!"); 
      else 
      { 
      DWORD buf1; 
      DWORD write; 
      BOOL OK=ReadProcessMemory(nOK,(LPCVOID)0x00506961,(LPVOID)&buf1,4,NULL); //讀取我們保存EDX中的基礎(chǔ) 
      if(OK ==TRUE) 
      { 
      write =buf1+0x000003F4; //得到內(nèi)力值的地址 
      DWORD Writeed =0x00; //要修改的數(shù)值 
      BOOL B =WriteProcessMemory(nOK,(LPVOID)write,&Writeed,1,NULL); 
      if(B==FALSE) 
      MessageBox("WriteNo"); 
      } 
      } 
      CloseHandle(nOK); 
      } 
      
      啊,寫的我手都麻啦,今天就到這里了,才疏學(xué)淺難免會有遺漏,請大家指教,如果我不會或不喜歡用VC的話,你可以在QQ上與我交流,我可以教你如何用Delphi、C++Builder、Win32Asm或VC實(shí)同上面的功能。 
      (如轉(zhuǎn)載本篇文章請不要改動內(nèi)容及作者!) 
      作者:CrackYY 
      Email:CoolYY@msn.com 
      OICQ:20651482 
      
      
      2001年,從云風(fēng)那兒得知了IDA這種好東東,看到他在解愷撒的游戲資源,覺得好玩,也開始自己解一些東東,當(dāng)時(shí)一口氣解了一些游戲的資源,當(dāng)然,都不是很復(fù)雜的,主要是臺灣和日本的 
      后來在主頁上放過一段時(shí)間,記得感興趣的朋友還挺多的,一直沒時(shí)間說,現(xiàn)在大概聊一下做法吧:) 
      工具當(dāng)然是IDA+SoftIce,要自己寫解壓程序的話,還要有習(xí)慣的編輯器,我當(dāng)然是用VC 
      其實(shí),資源破解,并不是很復(fù)雜,方法大致有3種 
      
      
      1,硬性破解 
      通過觀察目標(biāo)文件和反匯編代碼,分析出資源壓縮或者加密的格式,寫程序讀取改文件,并轉(zhuǎn)換成一種自己可以識別的格式就OK了 
      這是自己動手解資源時(shí)最容易想到的做法 
      具體來說,也就是通過一些特定函數(shù),譬如 fopen、createFile這樣的文件相關(guān)函數(shù),確定游戲的解資源函數(shù),然后就拼命的分析匯編代碼就OK了 
      我前期大部分資源都是這樣破解的,最好先用UEDIT分析一下實(shí)際的文件,有些格式太簡單了,通過文件大小,用看的就可以了 
      這種方法,我解過的最復(fù)雜的就是神奇?zhèn)髡f系列,當(dāng)時(shí)就感覺和GIF比較像,但又不太一樣,因?yàn)閷嚎s算法沒研究,所以就沒深究了,不過后來從網(wǎng)上看到文章說,那是一個很通用的壓縮算法,一些解壓工具就可以可以解開的,◎#¥%……真是不爽(不過還好,我只花了幾個小時(shí)就解開那個游戲而已 
      
      
      2,Dump 
      等圖片載入后,直接從內(nèi)存中導(dǎo)出 
      這種做法也很容易想到的,主要難點(diǎn)在于內(nèi)存中資源的格式問題,可能對3D游戲來說,這種解法比較容易一些,畢竟紋理渲染這些,是顯卡完成的,不是軟件實(shí)現(xiàn)的 
      我了解到的有些人解魔獸的資源就是這樣解開的,hook OpenGL的一些函數(shù) 
      我這樣解過一些游戲的文本(漢化用的文字),賽車游戲的,為了獲取所有游戲文本,特地將那款游戲通關(guān)的說 
      
      
      3,直接調(diào)用游戲的解碼函數(shù)解碼 
      和第2種做法類似,但是主動調(diào)用函數(shù),基本上可以一次將所有資源全部解開,不需要游戲通關(guān) 
      當(dāng)然,不是讓你調(diào)用游戲的解包模塊,畢竟很多游戲都不是dll形式的 
      只能侵入到游戲進(jìn)程內(nèi)部,找一個合適的時(shí)機(jī)(一般是載入其他文件的時(shí)候,中斷跳轉(zhuǎn)一下,先把我們的事做完),調(diào)用內(nèi)部函數(shù),解開所有的資源 
      我解過一款游戲就是用這種方法,說起來,那款游戲的資源壓縮率和rar差不多 
      
      
      0. 需求文檔 
      LZW壓縮算法是一種新穎的壓縮方法,由Lemple-Ziv-Welch 三人共同創(chuàng)造,用他們的名字命名。它采用了一種先進(jìn)的串表壓縮,將每個第一次出現(xiàn)的串放在一個串表中,用一個數(shù)字來表示串,壓縮文件只存貯數(shù)字,則不存貯串,從而使文件的壓縮效率得到較大的提高。奇妙的是,不管是在壓縮還是在解壓縮的過程中都能正確的建立這個串表,壓縮或解壓縮完成后,這個串表又被丟棄。 
      
      
      1. 基本原理 
      首先建立一個字符串表,把每一個第一次出現(xiàn)的字符串放入串表中,并用一個數(shù)字來表示,這個數(shù)字與此字符串在串表中的位置有關(guān),并將這個數(shù)字存入壓縮文件中,如果這個字符串再次出現(xiàn)時(shí),即可用表示它的數(shù)字來代替,并將這個數(shù)字存入文件中。壓縮完成后將串表丟棄。如"print" 字符串,如果在壓縮時(shí)用266表示,只要再次出現(xiàn),均用266表示,并將"print"字符串存入串表中,在解碼時(shí)遇到數(shù)字266,即可從串表中查出266所代表的字符串"print",在解壓縮時(shí),串表可以根據(jù)壓縮數(shù)據(jù)重新生成。 
      
      
      2. 實(shí)現(xiàn)方法 
      A. 初始化串表 
      在壓縮信息時(shí),首先要建立一個字符串表,用以記錄每個第一次出現(xiàn)的字符串。一個字符串表最少由兩個字符數(shù)組構(gòu)成,一個稱為當(dāng)前數(shù)組,一個稱為前綴數(shù)組,因?yàn)樵谖募忻總€基本字符串的長度通常為2(但它表示的實(shí)際字符串長度可達(dá)幾百甚至上千),一個基本字符串由當(dāng)前字符和它前面的字符(也稱前綴)構(gòu)成。前綴數(shù)組中存入字符串中的首字符,當(dāng)前數(shù)組存放字符串中的尾字符,其存入位置相同,因此只要確定一個下標(biāo),就可確定它所存貯的基本字符串,所以在數(shù)據(jù)壓縮時(shí),用下標(biāo)代替基本字符串。一般串表大小為4096個字節(jié)(即2 的12次方),這意味著一個串表中最多能存貯4096個基本字符串,在初始化時(shí)根據(jù)文件中字符數(shù)目多少,將串表中起始位置的字節(jié)均賦以數(shù)字,通常當(dāng)前數(shù)組中的內(nèi)容為該元素的序號(即下標(biāo)),如第一個元素為0,第二個元素為1,第15個元素為14 ,直到下標(biāo)為字符數(shù)目加2的元素為止。如果字符數(shù)為256,則要初始化到第258個字節(jié),該字節(jié)中的數(shù)值為257。其中數(shù)字256表示清除碼,數(shù)字257 為文件結(jié)束碼。后面的字節(jié)存放文件中每一個第一次出現(xiàn)的串。同樣也要音樂會 前綴數(shù)組初始化,其中各元素的值為任意數(shù),但一般均將其各位置1,即將開始位置的各元素初始化為0XFF,初始化的元素?cái)?shù)目與當(dāng)前數(shù)組相同,其后的元素則要存入每一個第一次出現(xiàn)的字符串了。如果加大串表的長度可進(jìn)一步提高壓縮效率,但會降低解碼速度。 
      
      
      B. 壓縮方法 
      了解壓縮方法時(shí),先要了解幾個名詞,一是字符流,二是代碼流,三是當(dāng)前碼,四是當(dāng)前前綴。字符流是源文件文件中未經(jīng)壓縮的文件數(shù)據(jù);代碼流是壓縮后寫入文件的壓縮文件數(shù)據(jù);當(dāng)前碼是從字符流中剛剛讀入的字符;當(dāng)前前綴是剛讀入字符前面的字符。 
      文件在壓縮時(shí),不論文件字符位數(shù)是多少,均要將顏色值按字節(jié)的單位放入代碼流中,每個字節(jié)均表示一種顏色。雖然在源文件文件中用一個字節(jié)表示16色、4色、2色時(shí)會出現(xiàn)4位或更多位的浪費(fèi)(因?yàn)橛靡粋€字節(jié)中的4位就可以表示16色),但用LZW 壓縮法時(shí)可回收字節(jié)中的空閑位。在壓縮時(shí),先從字符流中讀取第一個字符作為當(dāng)前前綴,再取第二個字符作為當(dāng)前碼,當(dāng)前前綴與當(dāng)前碼構(gòu)成第一個基本字符串(如當(dāng)前前綴為A,當(dāng)前碼為B則此字符串即為AB),查串表,此時(shí)肯定不會找到同樣字符串,則將此字符串寫入串表,當(dāng)前前綴寫入前綴數(shù)組,當(dāng)前碼寫入當(dāng)前數(shù)組,并將當(dāng)前前綴送入代碼流,當(dāng)前碼放入當(dāng)前前綴,接著讀取下一個字符,該字符即為當(dāng)前碼了,此時(shí)又形成了一個新的基本字符串 (若當(dāng)前碼為C,則此基本字符串為BC),查串表,若有此串,則丟棄當(dāng)前前綴中的值,用該串在串表中的位置代碼(即下標(biāo))作為當(dāng)前前綴,再讀取下一個字符作為當(dāng)前碼,形成新的基本字符串,直到整個文件壓縮完成。由此可看出,在壓縮時(shí),前綴數(shù)組中的值就是代碼流中的字符,大于字符數(shù)目的代碼肯定表示一個字符串,而小于或等于字符數(shù)目的代碼即為字符本身。 
      
      
      C. 清除碼 
      事實(shí)上壓縮一個文件時(shí),常常要對串表進(jìn)行多次初始化,往往文件中出現(xiàn)的第一次出現(xiàn)的基本字符串個數(shù)會超過4096個,在壓縮過程中只要字符串的長度超過了4096,就要將當(dāng)前前綴和當(dāng)前碼輸入代碼流,并向代碼流中加入一個清除碼,初始化串表,繼續(xù)按上述方法進(jìn)行壓縮。 
      
      
      D. 結(jié)束碼 
      當(dāng)所有壓縮完成后,就向代碼流中輸出一個文件結(jié)束碼,其值為字符數(shù)加1,在256色文件中,結(jié)束碼為257。 
      
      
      E. 字節(jié)空間回收 
      在文件輸出的代碼流中的數(shù)據(jù),除了以數(shù)據(jù)包的形式存放之外,所有的代碼均按單位存貯,樣就有效的節(jié)省了存貯空間。這如同4位彩色(16色)的文件,按字節(jié)存放時(shí),只能利用其中的4位,另外的4位就浪費(fèi)了,可按位存貯時(shí),每個字節(jié)就可以存放兩個顏色代碼了。事實(shí)上在 文件中,使用了一種可變數(shù)的存貯方法,由壓縮過程可看出,串表前綴數(shù)組中各元素的值頒是有規(guī)律的,以256色的文件中,第258-511元素中值的范圍是0-510 ,正好可用9位的二進(jìn)制數(shù)表示,第512-1023元素中值的范圍是0-1022,正好可用10位的二進(jìn)制數(shù)表示,第1024-2047 元素中值的范圍是0-2046,正好用11位的二進(jìn)制數(shù)表示,第2048-4095元素中值的范圍是0-4094,正好用12位的二進(jìn)制數(shù)表示。用可變位數(shù)存貯代碼時(shí),基礎(chǔ)位數(shù)為文件字符位數(shù)加1,隨著代碼數(shù)的增加,位數(shù)也在加大,直到位數(shù)超過為12(此時(shí)字符串表中的字符串個數(shù)正好為2 的12次方,即4096個)。 其基本方法是:每向代碼流加入一個字符,就要判別此字符所在串在串表中的位置(即下標(biāo))是否超過2的當(dāng)前位數(shù)次方,一旦超過,位數(shù)加1。如在4位文件中,對于剛開始的代碼按5位存貯,第一個字節(jié)的低5位放第一個代碼,高三位為第二個代碼的低3位,第二個字節(jié)的低2位放第二個代碼的高兩位,依次類推。對于8位(256色)的文件,其基礎(chǔ)位數(shù)就為9,一個代碼最小要放在兩個字節(jié)。 
      
      
      F. 壓縮范圍 
      以下為文件編碼實(shí)例,如果留心您會發(fā)現(xiàn)這是一種奇妙的編碼方法,同時(shí)為什么在壓縮完成后不再需要串表,而且還在解碼時(shí)根據(jù)代碼流信息能重新創(chuàng)建串表。 
      字 符 串: 1,2,1,1,1,1,2,3,4,1,2,3,4,5,9,… 
      當(dāng) 前 碼: 2,1,1,1,1,2,3,4,1,2,3,4,5,9,… 
      當(dāng)前前綴: 1,2,1,1,260,1,258,3,4,1,258,262,4,5,… 
      當(dāng)前數(shù)組: 2,1,1, 1, 3,4,1, 4,5,9,… 
      數(shù)組下標(biāo): 258,259,260,261,262,263,264,265,266,267,… 
      代 碼 流: 1,2,1,260,258,3,4,262,4,5,… 
      
      
      3. 測試文檔 
      
      說明: 
      當(dāng)選擇時(shí)請選擇1-3的數(shù)據(jù),如果選了其他的數(shù)據(jù)就出錯了。 
      4. 使用文檔 
      在進(jìn)入程序后,通過選擇是壓縮、解壓縮還是退出程序。 
      壓縮文件: 
      1)提示:“Input file name?” 輸入:D:\cc\test.txt 
      2)提示:“Compressed file name?” 輸入:test.lzw 
      3)顯示:“Compressing………” 及 “*”表示文件壓縮的進(jìn)度。 
      說明:如果輸入的文件不存在,將會重復(fù)提示,直到輸入正確文件位置和文件名。生成的test.lzw將會存放在程序所在的根目錄下。 
      如:程序放在D:\cc\下,則生成文件也在D:\cc\. 
      解壓縮: 
      1)提示:“Input file name?” 輸入:test.lzw 
      2)提示:“Compressed file name?” 輸入:test.txt 
      3)顯示:“Expand………” 及 “*”表示文件解壓縮的進(jìn)度。 
      說明:如果輸入的文件不存在,將會重復(fù)提示,直到輸入正確文件位置和文件名。生成的test.lzw將會存放在程序所在的根目錄下。 
      
      
      ANI(APPlicedon Startins Hour Glass)文件是 MS-Windows的動畫光標(biāo)文件,其文件擴(kuò)展名為“.ani”。它一般由四部分構(gòu)成:文字說明區(qū)、信息區(qū)、時(shí)間控制區(qū)和數(shù)據(jù)區(qū),即 ACONLIST塊。anih塊、rate塊和 LIST塊。 
      以下就是作為例子的文件內(nèi)容(數(shù)據(jù)E)及ANI文件標(biāo)準(zhǔn)結(jié)構(gòu)圖(圖): 
      
      
      1. 從(0000-006D)是 Wnd0WS 95& NT ANI文件的文字說明區(qū)部分 
      如你想對你開發(fā)的ANI文件提供一點(diǎn)文字說明,并加入你的版權(quán)信息,且同時(shí)它們又要被ANI文件播放軟件承認(rèn)時(shí),這是你唯一的選擇。要是你覺得這樣做很麻煩,或者沒什么好寫時(shí),那你完全可以去掉本塊中的全部內(nèi)容,并將塊的大小置為0。切記,“塊識別碼 
      ‘ ACONLIST’”和標(biāo)識“塊的大小”這兩部分,共計(jì) 12字節(jié),絕對不能被更改、移動及刪除,否則后果自負(fù)。 
      可能為了讓文字說明信息系統(tǒng)化,在ACONLIST塊內(nèi)部包容了若干子塊,本例中用到的兩個分別是:INFOINAM塊(提供本文件的解釋說明)和IART塊(用于插入版本信息)。說實(shí)在,諸位可以運(yùn)用在 AVI文件中插入自定義塊的方法,加入自己的自定義塊,其結(jié)果只是ANI播放軟件把它當(dāng)作一個“JUNK”罷了。 
      0000-0003:多媒體文件識別碼:RIFF 
      0004-0007;文件大?。?2052h字節(jié))-8字節(jié) 
      0008- 000F: ACONLIST塊識別碼,它是文字說明區(qū)開始的標(biāo)志 
      0010-0013:ACONLIST塊的大?。?Ah字節(jié)) 
      0014-001B:INFOINAM塊識別碼,標(biāo)志文件說明信息子塊的開始 
      001C- 001F: INFOINAM塊的大?。?20h字節(jié)) 
      0020-003F :文件說明信息子塊的內(nèi)容“Application startingHour Glass” 
      0040-0043:IART塊識別碼,標(biāo)志版權(quán)說明信息于決的開始 
      0044-0047:IART塊的大?。?6h字節(jié)) 
      0048- 006D:版權(quán)說明信息于塊的內(nèi)容“Microsoft Corporation,Copyright 1995” 
      2.從(006E-0099)?

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多