SkyrimのModをプログラムで生成する - 7 - ストリングテーブルを扱う

  • 0
    いいね
  • 0
    コメント

    はじめに

    この記事は、SkyrimというゲームソフトのModファイルのバリナリ解析とそれを利用してModを生成するC#のコードについて記載していくシリーズ物です。
    ファイルフォーマットについての詳しい情報は以下のサイトがあります。(以降UESP)
    Tes5Mod:Mod File Format - The Unofficial Elder Scrolls Pages (UESP)

    前回はModでも特に特別な構造となっているセル情報とワールド情報のクラスについて扱いました。今回はストリングテーブルについてです。

    Skyrimのストリングテーブルを扱うクラス

    Skyrim.esmなど、大本のファイルでは武器名などゲーム中に表示する固有の文字列は別ファイルで管理されています。(通常のModファイルではこれが普通の文字列として管理されています)
    このため、例えばSkyrim.esmから武器情報を抜き出した際に武器名称を知りたい場合、ストリングテーブルから文字情報を取得する必要があります。

    ストリングテーブルのファイルフォーマットについてUESPに詳細がありますので説明は省略します。
    http://en.uesp.net/wiki/Tes5Mod:String_Table_File_Format

    とりあえず今回はSTRINGSを扱うクラスのみです。

        public class TesTableStrings
        {
            private TesFileReader fr;
            private uint count;
            private uint dataSize;
            private Dictionary<uint, uint> de = new Dictionary<uint, uint>();
            private long pos;
            private Dictionary<uint, string> dic = new Dictionary<uint, string>();
    
            public TesTableStrings(string path)
            {
                fr = new TesFileReader(path);
                count = fr.GetUInt32();
                dataSize = fr.GetUInt32();
                for (int i = 0; i < count; i++)
                {
                    de.Add(fr.GetUInt32(), fr.GetUInt32());
                }
                pos = fr.Position;
            }
    
            public string this[uint id]
            {
                get
                {
                    if (!de.ContainsKey(id))
                        return "";
    
                    if (!dic.ContainsKey(id))
                    {
                        dic.Add(id, fr.GetNullTerminatedString(pos + de[id]));
                    }
                    string result = dic[id];
                    return result;
                }
            }
    
            public Dictionary<uint, uint> DicStringID
            {
                get
                {
                    return de;
                }
            }
        }
    

    必要な文字列にのみアクセスできる仕組みとなっていますので、折角ですからすべて読み取るのではなく、インデクサーで指定されたidの文字列を読み取る形としています。
    一応一度読み取ったものはディクショナリーに登録してそこから読むようにはしてみました。
    指定したidが無い場合、とりあえず、例外とせずに空文字を返すようにしていますが、今後検討が必要です。

    単純な構造ですから特に説明する事はないかと思いますが、最初にidと文字列があるオフセットのディクショナリーを作成し、後はidが指定されたら、そのディクショナリーからオフセット位置までシークして、NULL終端までの文字列を読み取るようにしています。

    以上

    前回 次回
    6 - セル情報とワールド情報を扱う 8 - 実際にModファイルを読み取ってみる