LoginSignup
0
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-04-15

はじめに

この記事は、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ファイルを読み取ってみる
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2