淺談LZSS與遊戲圖片破解

 業餘遊戲製作者最頭疼的就是沒有美工的支持了。很多業餘遊戲製作所使用的圖片都是來自於網上的很有限的一些圖片資源,然而這些圖片並不能完整配套,所以業餘遊戲的畫面往往顯得單調或者搭配不協調(使用多個不屬於一系列的圖片資源)。基於此,也有不少業餘遊戲採用“竊取”商業遊戲圖片於己用的方式(反正業餘遊戲一般都不用於商業目的),這種方法使用的就是一系列完整、配套的圖片,畫面就會顯得專業、協調得多,但是,前提是能夠破解商業遊戲的圖片格式。多數商業遊戲並不會將圖片資源以可以直接打開的常用格式存放,而是會做一定的壓縮處理,這樣做有兩個好處:其一,圖片不易被用戶直接修改或用於其他用途;其二,減小遊戲圖片資源所佔用的磁盤空間。

  最近,我爲了獲取圖片資源,研究了一些遊戲的圖片壓縮格式,發現有不少遊戲採用了LZSS壓縮,例如《天使音樂會》、《神奇傳說系列》(只針對《時空道標》和《遠征奧德賽》兩作,因爲沒有其他的在手邊)。於是,我在網上查閱了一些關於LZSS壓縮的資料,實現了這些遊戲的圖片資源破解。

  LZSS壓縮是LZ77壓縮的改進方式,相對於LZ77減少了冗餘度。LZSS在壓縮比率上相對其它壓縮並沒有太大優勢,然而它的壓縮/解壓縮速度卻非常快,因此往往用在速度優先的場合(當然,遊戲圖片解壓縮就是速度優先的)。基於這個優勢,LZSS被大量採用,例如微軟以前常使用的compress.exe/expand.exe就是採用LZSS實現的(這裏順便提一下,《神奇傳說時空道標》的圖片壓縮完全就是用compress.exe的方式壓縮的,連文件頭都完整存在,因此可以直接用expand.exe來解壓縮,就不用自己忙活了^_^)。

  在文章的末尾我給出了一個用LZSS壓縮/解壓縮的源程序,是Haruhiko Okumura在1989年所寫,後來被廣泛使用。但是由於其源代碼相當晦澀,所以我在這裏先把LZSS壓縮的原理大致介紹一下:

  LZSS採用了一個大小爲N的滑動窗口用於在文件中滑動,其中後F大小作爲一個前向緩衝,在窗口中前N-F字節內容是已處理部分,而後F字節也就是前向緩衝是待處理部分。如下圖示:



  壓縮過程就是用前向緩衝中的F字節長的串和前面的N-F個長F的串作比較,例如當F如上圖爲10的時候,將前向緩衝的qrstabcdfk串分別和前面的zqrstabcdf、yzqrstabcd、xyzqrstabc、wxyzqrstab……總共N-10個串進行比較,尋找最長匹配。在上例中,qrstabcdfk的最長匹配出現在qrstuvwxyz時(即箭頭所指位置N-F-10),匹配長度爲4即qrst。然後記錄下二元組〈匹配位置,匹配長度〉(在上例中是〈N-20, 4〉),放入到輸出緩衝區;如果匹配長度少於等於2個字節(例如上例中匹配f時,匹配長度爲1),這時用上述二元組記錄,反而會造成浪費,因此,直接把原字符放入輸出緩衝區。當放入輸出緩衝區以後,應該將滑動窗口向後滑動,後F字節中處理過了的字節滑入N-F字節區中,同時從文件中補充相應字節數至後F字節,重複上述處理,直至文件結束。解壓縮的過程與此類似,在此不再贅述。

上面只是一個大概的LZSS實現原理,下面我針對所附的源代碼中的部分問題做一個解釋:

1. 大家知道,作字符串比較是比較耗時的,爲了提高效率,程序中使用了256棵查找二叉樹,每一棵表示一個字節值開頭的串,以快速查找到所需要比較的串的所在地。

2. 程序中將滑動窗口做成了一個環狀緩衝,以免造成滑動的不便。

3. 程序的輸出格式如下:用一位表示一個單元的類型,該位爲1表示字符未經處理直接輸出(一個字節)、爲0表示經過了處理,輸出上面所說的〈匹配位置,匹配長度〉二元組(兩個字節),把這樣的8位合在一起(一個字節)表示後面輸出的八組元素的類型,其後就是經過處理或未經處理的八組數據,每組一或二個字節,當八組數據滿時,將輸出緩衝區中的數據輸出到文件。二元組的兩個字節是這樣安排的:第一個字節表示匹配位置的低八位,第二個字節的高四位表示匹配位置的高四位,第二個字節的第四位表示匹配長度(程序中定義N爲4096,因此位置值佔用12位,F值定義爲18,除去匹配長度爲1和2的兩種情況,共16種情況佔4位)。

4. 微軟的compress.exe/expand.exe採用的是N=4096、F=16的定義,因此這個程序只要修改F值就可以解壓縮compress.exe壓縮的文件(事先需去除文件頭)。


  有了這個程序,我們就可以解壓不少遊戲的圖片或其他資源,用於自己的業餘遊戲開發。如何判斷一個文件是否採用LZSS壓縮呢?其實很簡單,上面我們也說到,在匹配長度小於等於2的時候,LZSS是原樣輸出的,以BMP文件爲例,其文件頭前幾個字節ASCII爲“BM6>[1]”由於BM6等幾個字符匹配長度爲1,因此在壓縮的文件中也肯定是明文出現的,如果其後有類似F3 F0的字節值,就和上面介紹的二元組格式一致了,那麼多半就是LZSS壓縮的了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章