我正打算做一个使用Quickbmsqu去解那些没有解包器的文档的教程。6 ?- s/ g/ B8 }, a$ `
起步会很简单,然后越来越难,直到你学会并且编写你自己的脚本。
我们需要如下的四个工具:
1、16进制编辑器,比如HxD。(我用WINHEX)
2、Quick BMS  http://aluigi.org/papers/quickbms.zip(老外真废话,不用这个还写什么教程啊?)
3、文本编辑器比如wordpad(我猜老外用的都是免费软件,我用EditPlus)
4、支持16进制的计算机,比如WINDOWS自带的! d% G- z* K, _2 {. z( b/ J8 J
我们从一个叫做FEZ(Fantasy Earth Zero)的游戏开始$ f1 l% h- ?" ~
这对某些人学习bms脚本来说是一个很大的文档格式。
附上一些例子:
网站 http://tw.fez.gamania.com/  1 S' q, J, j* l+ [+ D* k$ q1 ^* c
安装 http://tw.dl.gamania.com/fez/FEZ_1103.exe  
这个游戏在主要思路上用不正常的文件头材质和一些TGA以及一些.MDL格式。
好了,你可以从这里下载到完整的安装或者一些样本片段文件。% v* J& E8 p9 d+ h0 P* I4 z. L
http://www.MegaShare.com/1029061
用16进制编辑器打开文件,你就能看到如下所示:6 a" s% c, `0 w9 K8 H. F- O$ }
QUICKBMS 中文指南-编程知识网 
8 m' c3 N' B' @5 T7 U
可以看到右面有一些可辨认的文字; N! P  l. g" f3 @: y
Etc\\aura.tex , Etc\\cursor.tex , Etc\\mahoujin.tex , Etc\\env2.tex , and Etc\\kaze.tex .  
所以往下看我们就能知道在这个BIN文件里至少包含5个文件,如果把他们解包,则会被解包到一个叫做Etc的文件夹中。
我们还是看看这个文件的文件头中的其他部分吧,从前面4个字节开始。/ q9 J, R" {: ^. W
QUICKBMS 中文指南-编程知识网 

这四个字节是 05 00 00 00  
我们处理的99%的游戏文档中,这个值是反向的。也就是说我们看到的05 00 00 00实际上应该是00 00 00 05或者说是5。6 k8 h( B8 O% h8 \& k
好了,如果我们还记得前面我们曾经看到过5个文件名,并且这个文件的前四个字节就等于5.那么我们就得出一个结论,那就是这里保存的是文档中的文件数。) {/ C/ [+ L7 p4 ~) i
数据的保存方式有长整型(Long)4字节,短整型(Short)2字节以及字节型(Bytes),于是我们得出了我们脚本的第一部分; A6 T# X. I3 }' F# \& G: |8 V
get FILES long  
这就告诉Quickbms读一个长整型值并且把它保存为变量FILES。  S. a3 z" B" @. o
接下来的4个字节74 00 00 00 对于quickbms解包没有用处,但是它表示的是文件头的长度。7 n2 b/ D% F) @3 b
QUICKBMS 中文指南-编程知识网
5 o6 O( ~  i; a6 Y  B7 Q+ f
于是我们可以写出下面一行quickbms脚本了! M5 r5 k8 m$ q' J( r$ u
get HEADERSZ long  
将文件头的大小保存到变量HEADERSZ 中: c6 V0 Z3 N4 H/ u( S7 U! j) P
现在,在文件名前面,我们又得到了两个字节,0C 00,我们知道这是短整型,但是00 0C代表什么呢?如果我们在16进制编辑器中把文件名部分选中,就能看到,它的长度正好是C。文件名长度可以写为:
get NSIZE short  
把表示文件名长度的两个字节保存到变量NSIZE中。
QUICKBMS 中文指南-编程知识网2 h7 m* _# H( s3 M
– O; B. y) ?9 }+ P0 f
在bms语言中,保存文件名应该写成下面的样子:
getdstring NAME NSIZE  
这就是说,保存一个长度为NSIZE的字符串到变量NAME中。
好了,现在我们在文件名之后又得到了另外4个字节:7C 00 00 00
我们已经知道了文件名,现在要解包这个文件,那么我们需要知道文件的大小以及保存的路径。
很显然,作为文件的大小来说,7C不是一个很大的数字。那么让我们看看偏移量7C的地方是什么。7 e1 W5 \9 r8 q, K( M) Q
在HXD中按下Ctrl+E,然后在开始偏移量和结束偏移量的地方都输入7C,再按OK键。
QUICKBMS 中文指南-编程知识网 
' u& B6 z+ T/ q7 ?
我们就能看到下面的图/ N- }& b' e" B" S# p
QUICKBMS 中文指南-编程知识网
这里好像是一个文件的文件头IMG0,于是我们写下这行表示这是文件的开头:
get OFFSET long  $ s2 |4 z  M( ?' p9 O2 K" E: }
将4个字节保存到变量OFFSET中。1 G3 l) G0 G4 l/ E& k  F0 S
接下来的4个字节70 10 00 00看上去比较大,所以让我们看看这里是不是文件的长度。先翻译成00 00 10 70或者说是1070,从刚才的偏移量7C加上长度1070– q% t2 x  j# a; x! L- J
QUICKBMS 中文指南-编程知识网9 p. G$ x4 D9 B0 u' ~: A3 |8 s
哦,我看到了TRUEVISION-XFILE,这是一个典型的TGA文件结尾。而且我们还看到了这个文件是以IMG0开头的。0 N4 m# `4 z) X7 Z$ }0 c+ ~/ [9 u6 k
QUICKBMS 中文指南-编程知识网" i7 t4 K6 B4 S- G9 a& _
这意味着我们找到了文件的长度。记下:
get SIZE long  
把4个字节保存到变量SIZE中。4 Q0 J+ z7 t' e' _3 [1 q0 v: N3 s
好了,现在我们下一个文件的两个字节,它们看上去挺相似的。: [$ F% r% R2 v2 ~
把0E 00翻译成00 0E或者E
文件名前的两个字节就是文件名的长度,让我们看看是不是。" |5 ^7 `( J! ]1 {# P' s
QUICKBMS 中文指南-编程知识网– K) h( L, S; D" B: ]* e& t. B
的确,文件名的长度是E
这意味着我们发现了文件头重复的部分,我们已经把需要解包的部分都识别出来了。现在我们就可以完成脚本生成我们的解包器了。
对于重复的部分,我们设定一个循环,让它一直运行到没有剩余的文件为止。简单的写出来就是:& F; V# \2 d3 O
for i = 0 < FILES  
意思就是运行下面的命令从i = 0 直到i< FILES(这里的翻译和原文不同,我是按照语句的意思翻译的,原文没看明白)# X# c6 K+ |" B! q$ m! D2 K; [
我们把它放到NSIZE变量前面,因为它是循环部分的开始。
要把它保存到文件中并且记录日志命令要用下面的格式:' H& a+ x0 W& o
log NAME OFFSET SIZE  ( c6 C: {! ~$ M/ {
意思是把偏移量OFFSET开始,长度为SIZE的数据填写到文件里并保存。
现在,重复这些操作,直到没有剩余的文件,我们还得加一句:4 y! R- ~3 A9 Z; Y" d% R
next i  $ F! L( U+ b! z8 }% h( G
在循环之后,这样循环就可以进行了。! ?" v/ T2 x% ~/ I8 M& R' _$ n; e* u
好了,保存脚本文件并且命名为extract.bms,把Etc.pac、extract.bms 和quickbms.exe放到一个文件夹中。在这个例子中,我们假设是C:\\Temp! u- X' o# m" G( r, E/ B
现在在命令行模式下,进到刚才那个目录中并且输入:
quickbms.exe -l extract.bms Etc.pac .  
将会列出文件的信息和大小。如果脚本不正确将给出错误信息。
耶,它运行了:
QUICKBMS 中文指南-编程知识网  ' ^; _& W; c8 w5 W- i- E' f+ ~
现在让我们试着把它们解包到extracted  目录中,输入
quickbms.exe extract.bms Etc.pac extracted  – y5 i; j, m! S/ w% i0 |
好,正确运行并且解包了。
QUICKBMS 中文指南-编程知识网
脚本代码:  
get FILES long  
get HEADERSZ long  
for i = 0 < FILES  8 ~0 I8 _2 n1 T' d+ X
get NSIZE short  
getdstring NAME NSIZE  
get OFFSET long  
get SIZE long  
– s2 O3 d4 Y. u3 F0 |$ k! {
log NAME OFFSET SIZE  3 j& O  r# @( J6 y+ h0 ~2 Y: S5 v
next i