MPQ Storm库 源代码分析 一个
MPQ什么?
? ? ? ??MPQ維基上說的非常明確。
簡而言之,它是暴雪公司用于游戲數據打包的工具。星際爭霸,魔獸爭霸游戲中都有使用。該工具內含游戲資源加密和壓縮等功能。
? ? ? ? git下載地址:https://github.com/stormlib/StormLib
? ? ? ??MPQ文件總共同擁有四種格式:
? ? ? ? ? ? ?第一種:FLAT格式。線性存儲。
? ? ? ? ? ? ?另外一種:Partial格式,分包的存儲。
? ? ? ? ? ? ?第三種:MPQE格式,加密存儲。
? ? ? ? ? ? ?第四種:BLOCK格式。模塊存儲。
? ? ? ??
FLAT格式最簡單。只是該格式也支持對單個文件的加密和壓縮。
本文主要分析FLAT格式,主要包括下面五點:
? ? ? ??一、創建一個MPQ文件。
? ? ? ??二、加入資源文件。
? ? ? ??三、封裝MPQ文件。
? ? ? ??四、讀取MPQ文件。
? ? ? ??五、讀取資源文件。
? ? ? ??圖一、圖二、圖三為FLAT格式的內部格式。
圖一
? ? ? ??一、創建一個MPQ文件。
? ? ? ? ? ? ?主要過程是。調用SFileCreateArchive接口創建MPQ文件。創建成功之后,該接口會返回成功與否。同一時候將MPQ文件的句柄賦值給傳進來的變量。
? ? ? ? ? ? ?創建MPQ文件具體流程是:
? ? ? ? ? ? ?1》在內存中初始化一個加密塊StormBuffer;
? ? ? ? ? ? ?2》嘗試打開一個同名的MPQ文件。假如已經存在的同名文件不是MPQ文件,MPQ工具就會嘗試用MPQ文件的格式讀取該文件。為了避免同名的錯誤。在StormLib的樣例中,有先刪除同一文件夾想的同名文件,再創建MPQ文件的邏輯。
? ? ? ? ? ? ?3》創建一個空的MPQ文件。
? ? ? ? ? ? ?4》重置文件大小。
? ? ? ? ? ? ?5》寫入一個假的MPQ文件頭部,即圖一的A指向的區域。
MPQ的頭部有四種不同的格式。分別擁有不同的長度,只是默認有一個最大長度是208字節。寫這個假的MPQ文件頭部,最基本的目的是占位,保證第一個數據文件的寫入位置是在正確的。
? ? ? ? ? ? ?6》假設是大文件,則創建大文件的索引表HetTable。
? ? ? ? ? ? ?7》創建HashTabl,用來索引文件的。
? ? ? ? ? ? ?以上七個過程。主要實現了兩個結果,1、創建了MPQ文件,2、在內存中生成須要用到的MPQ數據。
? ? ? ??二、加入資源文件。
? ? ? ? ? ? ?主要過程是,調用SFileCreateFile接口。在MPQ文件里創建一個新的文件句柄。通過SFileWriteFile接口寫入數據。
調用SFileCloseFile釋放內存資源。
? ? ? ? ? ? ?具體流程:
? ? ? ? ? ? ?1》檢查是不是內部文件。MPQ主要有兩個內部文件,一個是listfile。另外一個attributes。假設不是內部文件,則向MPQ文件里加入新的文件。
? ? ? ? ? ? ?2》找到MPQ文件里能夠寫入的位置。假設是第一次寫入。則此時是圖一B指向的區域。
但此時還沒有寫入。
? ? ? ? ? ? ?3》通過HashString方法,將資源文件名稱轉化為hash索引值。以新的hash索引值從當前的HashTable中取一個TMPQHash數據結構。
? ? ? ? ? ? ?4》假如不是第一次建立新文件。則此時,通過TMPQHash的dwBlockIndex值。在FileTable做dwBlockIndex偏移。獲取新文件的入口TFileEntry。假如是第一次建立新文件。則會先到FileTable里面取出一個空暇的位置,分配一個TFileEntry。默認是取FileTable位置做dwFileTableSize偏移,而此時dwFileTableSize值是0,所以就是FileTable表中第一個位置。即圖一B指向的區域。
同一時候分配一個TMPQHash(hash索引的取值與文件名稱有關),分配完之后。與FileEntry關聯。在FileEntry里通過dwHashIndex索引到hash表中的位置,TMPQHash通過dwBlockIndex索引到FileEntry。
? ? ? ? ? ? ?5》拿到了FileEntry以后,在SFileAddFile_Init函數中初始化FileEntry的其它值。
經過這些邏輯。就能夠拿到一個TMPQFile文件指針,用來寫入數據。
? ? ? ? ? ? ?6》通過SFileWriteFile接口寫入文件數據,能夠將資源文件分批寫到MPQ文件里。也能夠將資源文件一次寫入MPQ文件里,兩種都不會有問題。
圖二
? ? ? ? ? ? ?7》在將要寫文件的前,會先寫入一個扇區,默認有8字節,扇區與將要寫入的數據的加密有關聯。然后寫入
數據,數據有選項,能夠選擇是否加密,是否壓縮,是否選擇數據作為單元文件存儲。
寫入完成之后,會再次寫入當
前扇區,詳細為什么要兩次寫入扇區,下一篇會繼續分析。圖二中。L指向的是真正的資源文件數據,K、M各自是扇
區。資源文件可選擇加密和壓縮。
圖三
? ? ? ??三、封裝MPQ文件。
? ? ? ? 封裝挺重要的,封裝時會將新生成的文件相關的數據更新到MPQ文件頭部。覆蓋原先的假頭部。
封裝的主要過程是。將與文件相關的HET表和BET表,以及HASH表,文件FileTable。按順序寫到最后一個資源文件的結尾位置。
封裝邏輯運行完之后。新的MPQ文件內部結構如圖三。
? ? ? ??詳細流程是: ? ? ? ? ? ? ? ?
? ? ? ? ? ? ?1》確定是否要寫入listfile、attributes等文件,假設要,則會在MPQ文件里創建,并寫入。
? ? ? ? ? ? ?2》調用SFileCloseArchive,找到能夠寫入HET、BET、HASH、FILETABLE表的位置,然后將這些表的數據寫入到新的MPQ文件里。寫入后MPQ文件內部如圖三。表的數據會寫在第N個數據文件之后。最后,回到頭部更新MPQ文件頭部。
? ? ? ? ? ? ?3》釋放內存中的資源。
? ? ? ??四、讀取MPQ文件。
? ? ? ??主要流程是。打開MPQ文件,先讀取頭部。在讀取正確之后,解析各個表的位置。獲取數據文件位置。而且隨意一個環節出錯。都會退出。
? ? ? ??詳細流程:
? ? ? ? ? ? ?1》初始化一個StormBuff(與數據加密有關)。然后用208字節的長度,從MPQ文件頭部0位置開始讀取,一次讀取208字節。
讀取完之后強制轉化為TMPQHeader數據結構。
若TMPQHeader內部的數據是正確的,則開始讀取文件,為了推斷文件是否正確,MPQ會有很多檢測。只是MPQ文件頭部默認有四種格式。
每一種格式的長度都不一樣。在確定頭部之后。會調用memset。將超出的部分置0,確保新生成的MPQHeader數據正確。
? ? ? ? ? ? ?2》通過新獲得的頭部數據結構。讀取HASH表。Hash表通過TMPQHeader的dwHashTablePos屬性。找到其在文件里的位置,并讀取出。接著將文件里的數據,讀取到內存里面,完畢Hash表數據的讀取。
? ? ? ? ? ? ?3》建立文件數據表。通過讀取Hash表,初始化文件數據表FileTable。有了FileTable就能夠得到FileEntry,有了文件入口。就能讀取數據了。
? ? ? ? ? ? ?4》加載listfile和attributes文件。
眼下我沒用到這兩個選項。
? ? ? ? ? ? ?5》返回MPQ文件句柄。
? ? ? ??五、讀取資源文件。
? ? ? ? 有兩種讀取方式。
第一種是取出當中某一個特定的文件,另外一種遍歷MPQ文件內部全部的數據文件。
? ? ? ??第一種取出一個文件是比較簡單的。
? ? ? ??詳細流程是:
? ? ? ? ? ? ?1》調用SFileOpenFileEx接口(Ex即外部文件的意思)。傳入文件名稱給該接口,接口內部會將文件名稱轉化為hash數據。通過hash數據的dwBlockIndex屬性,算出FileEntry數據,有了FileEntry,就能夠獲得要讀取的文件的數據的位置。而且獲取該數據文件的句柄。也能夠先調用SFileHasFile推斷是否有該文件。
? ? ? ? ? ? ?2》調用SFileGetFileSize獲取文件大小,申請內存空間。調用SFileGetFileInfo獲取文件信息,不是數據。
? ? ? ? ? ? ?3》調用SFileReadFile獲取MPQ文件里特定資源文件的數據。
? ? ? ? ? ? ?4》調用SFileCloseFile釋放申請的內存。
? ? ? ??另外一種略微復雜一些。
? ? ? ??詳細流程是:
? ? ? ? ? ? ?1》調用SFileFindFirstFile,匹配符為*,則會所有匹配。返回一個hFind值。
? ? ? ? ? ? ?2》運行讀取一個文件的流程,上面已經說明,此處不再贅述。
? ? ? ? ? ? ?3》調用SFileFindNextFile獲取下一個文件的入口。
? ? ? ? ? ? ?4》循環運行1==>3流程。直至沒有文件能夠讀取。
版權聲明:本文博客原創文章,博客,未經同意,不得轉載。
總結
以上是生活随笔為你收集整理的MPQ Storm库 源代码分析 一个的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 5G NR空口物理层主要参数解读
- 下一篇: win10开机优化