ゲームなどのアプリケーションを配布するとき
悩みの種となるのがファイルデータの取り扱いです
ディレクトリにそのままファイルを放り込んだままですと
ユーザーが全員良心的な人であればいいのですが、コピーされ悪用されかねませんし、
ゲームのデータに借り物のデータなどがある場合は著作権上大きな問題になります
これは配布する側がユーザーに簡単に生のファイルデータを取らせない工夫が必要になります
そこでディレクトリファイルをまとめてパッケージ化(あるいはリソース化)する必要が出てくるわけです
かと言ってzipなどの誰でも解凍できる既知のファイルフォーマットでは意味がないので
既知でないフォーマットで作成するのが一番だと思います
今回使うパッケージファイルのフォーマットは次のようになっています
(オリジナルフォーマットと言い張るつもりはありません、誰でも考えつきそうだし・・・)
○ヘッダー部 ・ ファイルのフォーマットを表す文字 ・ 格納されているファイルの個数 ○データ部 ・ 各ファイルのファイル名 ・ 各ファイルのファイルサイズ ・ 各ファイルのデータ ・ 各ファイルのデータ末尾
指定のディレクトリ内の全てのファイルをパッケージファイルに変換し、
そのファイルからバイナリデータを取得します
なお、階層情報を保ったままの相対パスをファイル名としています
今回の全ファイル
zip:package.zip
具体的な実装に関しては
・package.h
・package.cpp
を見てもらいたいと思います
使い方は次のようになります
main.cpp
#include "package.h" int main(){ Package package; // 指定のディレクトリをパッケージ化する package.CreatePackage(_T("media"),_T("media.pak")); // パッケージ化したファイルを開く package.OpenPackage(_T("media.pak")); // パッケージファイルの中のファイルデータを取得する FileData fd; // 階層構造の情報もパッケージ化したときの状態なので辿る package.GetFileData(_T("media/txt/test.txt"),&fd); // 先頭データへのポインタ取得 byte* data = fd.Ptr; printf("%s\n",data); return 0; }
実行するとmediaディレクトリのファイルをまとめたmedia.pakファイルができるはずです
作成後、パッケージファイルの読み取りにはファイルマッピングという方法を取っています
ファイルマッピングはファイルをページングする(ファイルデータに仮想アドレスを割り当てること)により
ファイルデータを(仮想的に)連続メモリとしてポインタで読み書きできる方法です
つまり、ファイルポインタを使わずに直接ポインタでファイルデータにアクセスできます
今回のように複数のファイルをまとめたパッケージファイルの中から
指定のファイルデータの生データをポインタで取り出せるのでデータの読み取りをしやすいと思います
ファイルマッピングの実装は
・memorymappedfile.h
・memorymappedfile.cpp
にあります
特にDirectXの関数では画像データ等のバイナリのデータの先頭ポインタから
テクスチャ等のリソースを確保できる関数が用意されているため、この方法は重宝するはずです
実行結果は次のようになります
テキストファイルの生データを取得し、表示しているだけです
最近ではバイナリデータを分解するようなツールも出てきてるみたいなので
本来ならば、さらにパッケージファイルの圧縮や暗号化をする必要があるでしょう
ただそのレベルまでやる必要があるのは商用レベルのゲームだと思うので今回は割愛します