TOP MAP UP

エミュレータ的ZIPファイル対応

 エミュレータでZIPに対応したい・・・・というのはもうほとんど、圧縮されたROMを圧縮されたまま取り扱いたい場合だろう。更に条件をつけると、ZIPから直接メモリに展開したいはずだ。

 こういった場合、いろいろZIPを扱うライブラリのような物はあるが、今回はzlibを使って機能を実装してみた(ちなみに統合アーカイバプロジェクトのunzip32.dllは直接メモリに展開するファンクションがドキュメントに書いてあるのだが、何故か実際には存在しないようだ:02/05/22現在)

 もともとzlib自体は一般に流通しているZIPファイル、つまりPKZIPベースのファイル、の取り扱いをサポートしているわけではない。よって自前でZIPを扱う為には、このPKZIP部分の処理を自前で追加してやる必要がある。ちなみにZIPファイルの構造などは、PKWAREPKZIP Application Noteが詳しい。



まずエミュレータ自体のおおまかな処理の流れは
 ZIPファイルと、解凍先のメモリを取得する
 ZIPファイルをメモリに読み込む
 メモリ上のZIPファイルを捜査してdeflateのデータ位置を特定する
 Inflateしてメモリ上に解凍する
 インターリーブ処理等を行う
 ZIPファイルと、解凍先のメモリを開放する
といった具合だ。

この部分のサンプルコードはこれ(LOAD_ROM.CPP)
まぁ特に難しいわけではないので、解説は省く。



実際に問題になってくるのが、deflateのデータ位置の特定だ。
このあたりのサンプルコードはこれ(PKZIP.CPP,PKZIP.H)

 まず'PK',0x03,0x04というヘッダ(以下PK34)をZIPファイル先頭から探す(ちなみにこの部分をインプリメントしてるのがm_search_pkxxである)
 PK34自体はすぐに見つかるだろう(いちばん最初は)しかし、そのヘッダが目的のファイルとは限らないので、違った場合は、更にサーチする必要がある。ちなみにこのヘッダは別にアライメントにそろってる訳ではないので、ちゃんと1byteづつサーチしないと取りこぼす可能性がある。
 しかしまじめにその後も延々1byteごとにサーチするとアホほど時間を食うので、見つかったヘッダのcompress sizeを元に、次のヘッダの手前からサーチする(ファイル名などがあるので、単純にcompress sizeを足せば十分であろうと思われる)
 という処理を繰り返して、目的のファイルのヘッダを探す(ちなみにこの部分をインプリメントしてるのがm_search_nameである)

目的のヘッダが見つかったら、deflateの位置は
 ZIPファイルの先頭アドレス+
 目的のファイルヘッダのオフセット+
 定数ZNAM(つまりファイル名位置を指す)+
 目的のファイルヘッダから導くファイル名の長さ+
 目的のファイルヘッダから導くその他領域の長さ・・・・・である。

m_extractのパラメータは
 deflateの位置,compressサイズ,解凍メモリの位置,解凍後サイズ・・・・・となる

 実際にm_extractでは何をやってるかというと、まずは初期化を行う。この時に(詳しくはわからないが:汗)inflateInit2を使わないと、うまくinflate出来なかった。後はパラメータを突っ込んでinflateで完了である。

 本来はこのあたりで、サンプルソースのように、十分なメモリ量を期待できない場合もあるかと思うので、ZIPや解凍先のバッファが小さくても動作できるように処理を追加する方が良いと思うが、今回は割愛しておく(奥村晴彦先生のzlib入門を参照されたし)



 というわけで、エミュレータを作成する時に「ZIPの扱いめんどくせぇ〜」と思い、延々放置状態だった人等に参考にしていただければ幸いである。
 ちなみにサンプルのPKZIP.CPPはm_xxxxという名前のファンクションになっている。これはメモリでの処理の関数なのでこう名前を付けている。興味のある人は、この上に、ファイルレベルのラッパーを書いてみてはどうだろうか?