從問題到結果 ——EXE2SWF的開發手記
隨著Macromedia Flash 5的閃亮推出,Flash在網絡多媒體應用方面已經占據了不可動搖的地位,再加上中國閃客們的無私勞動,許多經典歌曲,比如“東北人”、“第一次” 等等都有了Flash版本的MTV,真是別有一番情趣。然而,網絡上許多Flash作品都是EXE形式的,雖然方便了沒有安裝Flash插件的朋友,但是EXE形式的Flash不能用於網頁制作,更不用說分析Action什麼的了。由於手邊沒有免費的EXE2SWF工具,於是決定自己DIY一個,一顯Programmer本色!
一、開發工具 我用到的開發工具有Delphi6,最好用的RAD工具; UltraEdit,強大的16進制編輯工具;ShowGood三國系列中的財神到.swf、桃源結義.swf、神啊救救我吧.exe、割須棄袍.exe;最後就是思考,最有力也是最根本的工具。^_^
二、基本思路 首先我設想了一個基本思路:EXE形式的Flash包含兩部分,Flash播放器和跟在播放器後面的Swf文件,因為BMP2EXE、MP32EXE等軟件都是這麼做的。是不是這樣呢?我們動手看一看吧!
用UltraEdit打開“財神到.swf”和“桃源結義.swf”分析文件頭,非常明顯,文件頭都包括相同的ASCII碼“FWS”,估計這是Flash文件的標識符。用UltraEdit打開“神啊救救我吧.exe”,文件全長1183046字節。按下Ctrl+F調出搜索對話框,在Find What後填入“FWS”並且勾上“Find ASCII”,搜索。果不其然,在5c000處找到了“FWS”,接著的部分也和“財神到.swf”中的非常相似,可見假設很有可能是正確的。順籐摸瓜,查看兩個.swf文件的文件尾,都是若干個00加上40 00 00 00的形式,然而“神啊救救我吧.exe”的文件尾卻是若干個00加上40 00 00 00再加上120d3e處的56 34 12 FA 3E 4D 0C 00。最後這八個字節會是什麼呢?再打開“割須棄袍.exe”,發覺它的最後八個字節是56 34 12 FA 82 F5 12 00。聰明的你一定猜到56 34 12 FA是EXE形式Flash文件的標識符了吧?經過檢查其他EXE形式的Flash,事實證明了這個猜測是正確的。至於3E 4D 0C 00是什麼呢?不妨把它當作一個32位整數,注意到低字節和高字節的逆序,3E 4D 0C 00就應該等於00 0C 4D 3E,也就是十進制的806206。OK!至此我們已經獲取了足夠多的信息,接著就看看有什麼巧合吧!顛來倒去,不難發現,把“神啊救救我吧.exe”中swf部分的結束地址120d3e減去起始地址5c000,不就正好得到806206?
接下來要辦的事情就簡單了,我們動手證實一下。還是利用UltraEdit,把5c000至120d3e之間的數據粘貼出來,保存為一個.swf文件,用IE打開一看,這不就是久違了的陳小春的歌嗎?呵呵,大功告成!
順便說一句,如果好奇的話,你還可以把0至5c000的數據直接保存成.exe文件看看,呵呵,驚奇吧,就是Flash 5中的Standalone Player!
三、編寫程序 在正式編寫程序之前,我想先花一些時間介紹Delphi 中的文件流操作。如果你已經對這個非常熟悉了,可以跳過去,直接閱讀後文的代碼。否則,請花一點時間看一看,這對於你閱讀下面的代碼非常有幫助。
在Delphi中,所有流對象的基類為TStream類,其中定義了所有流的共同屬性和方法。那什麼是流呢?簡單來說,流就是建立在面向對象基礎上的一種抽象的處理數據的工具。流中定義了一些處理數據的基本操作,如讀取數據、寫入數據等,程序員只是面對流進行所有操作的,不用關心流的另一頭數據的真正流向。我們程序中將要使用TFileStream,它是TStream最常用的派生類。使用 TFileStream操作文件要比Object Pascal基本文件操作方便得多。TFileStream的基本操作是這樣的:首先create一個實例,然後用try...finally TFileStream.free的格式操作,“...”部分可以用TFileStream的ReadBuffer、 Seek、
WriteBuffer、CopyFrom方法來操作文件流。此外,流不但可以處理文件,還可以處理動態內存、網絡數據等多種數據形式。編寫程序時善加利用流,將會大大提高編程的效率。
好了,現在讓我們正式開工。首先我們先設計窗體。打開Delphi,首先在窗體上添加兩個Button、兩個Edit、一個OpenDialog以及若干個Label工具,界面設計以及控件 Name屬性,其他的采用默認值。
btnOpen是用來打開硬盤上EXE形式的Flash文件的,雙擊之,添加如下的代碼:
procedure TForm1.btnOpenClick(Sender: TObject);
begin
// 通過OpenDialog讓用戶選擇EXE形式的Flash
if OpenDialog.Execute then
begin
edtSourceExe.Text := OpenDialog.FileName;
// 自動生成.swf格式的文件名,方便用戶
edtTargetSwf.Text := ChangeFileExt(edtSourceExe.Text, '.swf');
end;
end;
btnConvert是用來轉換文件格式的按鈕,雙擊之,添加如下代碼:
procedure TForm1.btnConvertClick(Sender: TObject);
var
// 分別處理EXE、SWF文件的文件