バイナリー中間ファイル

概要

バイナリー中間ファイルは、高速に読み書きするために一部データをバイナリー化した中間ファイルです。 実機で扱うランタイム用のバイナリーファイルとは別のファイルです。 バイナリー中間ファイルは拡張子の最後の文字が a(テキスト形式)でなく b(バイナリー形式)になっています。

バイナリー中間ファイルの構造

バイナリー中間ファイルは、テキスト形式で記述された前半部と、バイナリーデータが埋め込まれた後半部に分かれています。 中間ファイル入出力において多くの時間を占める <stream_array> を、バイナリー形式で読み書きすることによって高速なファイル入出力を実現しています。

テキスト形式の前半部

バイナリー中間ファイルの前半部は、<stream_array> 以下の要素が削除されている点以外は通常の テキスト中間ファイル と同一です。

前半部に関しては、テキストエディタで内容を確認することができます。
ただし、テキストエディタで内容を編集して保存すると、後半部のバイナリーデータが壊れます。

前半部の終了 (</nw4f_3dif>\r\n) から後半部の先頭までは、1~32byte のゼロパディングを挿入して、32byte アライメントをとります。 最初に見つかった 0 値のアドレス + 1 を、32byte 境界に繰り上げると、後半部の先頭アドレスになります。

ただし、<stream_array> が存在しない場合は前半部のみとなり、テキスト中間ファイル と完全に同じ内容になります。

バイナリー形式の後半部

バイナリー形式の後半部はデータブロックであるチャンク単位で分割しています。 チャンクの先頭はファイル先頭からの 32byte アライメントに配置し、チャンク自体のサイズも 32byte 単位です。

エンディアンはリトルエンディアンです。

<stream_array> をバイナリー化したバイナリーデータであるため、対応したストリーム配列チャンクと複数のストリームチャンクを持ちます。

ストリーム配列チャンク

後半部の先頭にはストリーム配列チャンクがあります。

オフセット サイズ 内容
0 8 チャンクヘッダ "g3dstrma" (0x616D727473643367) です。
8 4 ストリームチャンク数です。
以降はストリームチャンクの情報が、チャンク数分並びます。
12 + 8 *
index
4 バイナリー形式の後半部先頭から、ストリームチャンク先頭までのオフセットです。
index はストリームチャンクのインデックスです。
16 + 8 *
index
4 ストリームチャンクのサイズです。
index はストリームチャンクのインデックスです。
? ? % 32 アライメントをとるためのゼロパディングです。

ストリームチャンク

ストリーム配列チャンクで指定されたストリームチャンクが複数並びます。

オフセット サイズ 内容
0 8 チャンクヘッダ "stream□□" (0x20206D6165727473) です。
□は半角スペースです。
8 4 ストリームのデータ型です。
0: float、1: int、2: byte、3: string、4: wstring です。
12 4 ストリームの持つデータ数です。
データ型が string、wstring の場合は、常に 1 です。
16 4 テキスト中間ファイルで利用するカラムです。
テキスト中間ファイルに変換する際に、 <stream> column に指定します。
データ型が string、wstring の場合は、常に 0 です。
20 4 データサイズ(データ列の byte 数)です。
データ型が string、wstring の場合は、終端文字を含んだ byte 数です。
24 8 アライメントをとるためのゼロパディングです。
32 データ
サイズ
データ型の値が、データ数の個数分並んでいるデータ列です。
string は ASCII で、wstring は UTF-16 LE で格納します。
string、wstring の改行コードは LF です。
? ? % 32 アライメントをとるためのゼロパディングです。

最後のストリームチャンク終端が、ファイルの終端です。

バイナリー中間ファイルの全体イメージ

<?xml version="1.0" encoding="utf-8"?>
<nw4f_3dif>
 ...
 <stream_array> 削除
 ...
</nw4f_3dif>\r\n
1~32byte のゼロパディング

ストリーム配列チャンク
{
 "g3dstrma"
 ストリームチャンク数

 {
  ストリーム配列チャンク先頭から各ストリームチャンク先頭へのオフセット
  各ストリームチャンクのサイズ
 } * ストリームチャンク数

 0~31byte のゼロパディング
}

ストリームチャンク
{
 "stream  "
 ストリームデータ型
 データ数
 カラム数
 データサイズ
 8byte のゼロパディング

 データ列

 0~31byte のゼロパディング
} * ストリームチャンク数

バイナリー中間ファイルの構造体イメージ

struct ChunkOffset
{
    u32 offset;
    u32 size;
};

struct StreamChunk
{
    u64 header;
    StreamType type;
    s32 count;
    s32 column;
    s32 size;

    u64 padding;

    void* data;
};

struct StreamArray
{
    u64 header;
    u32 chunkCount;
    std::vector<ChunkOffset> chunkOffset;

    // StreamChunk が 32byte アライメントになるように padding

    std::vector<StreamChunk> streamChunk;
};