3

Infinity Engine で作成されたゲーム (Baldur's gate、planescape Torment など) の modding ツールを開発しようとしています。Infinity Engine ファイル内のデータ構造の種類を知っており、byte[] コンテンツからオブジェクトをマッピングしています。ただし、パフォーマンスが不足しており、これには満足していません。

管理された世界にマップされたオブジェクトは構造体であり、それらが表現されるバイト数を知っています。したがって、アンセーフ コードでマッピング プロセスを作成することにしました。Uint、ushort のような値型の値には問題はありませんが、文字列型では char[] エンコーディングの問題に問題があります。

例として、C# で struct gam ファイルのヘッダーを確認できます。

http://iesdp.gibberlings3.net/file_formats/ie_formats/gam_v2.0.htm

[StructLayout(LayoutKind.Explicit, Size = 180,CharSet = CharSet.Ansi)]
public unsafe struct Header
{
    [FieldOffset(0)] 
    public fixed char Signature[4];

    [FieldOffset(0x0004)]
    public fixed char Version[4];

    [FieldOffset(0x0008)] public uint GameTime;

    [FieldOffset(0x000c)] public ushort SelectedFormation;

    [FieldOffset(0x000e)] public ushort FormationButton1;

    [FieldOffset(0x0010)] public ushort FormationButton2;

    [FieldOffset(0x0012)] public ushort FormationButton3;

    [FieldOffset(0x0014)] public ushort FormationButton4;

    [FieldOffset(0x0016)] public ushort FormationButton5;

    [FieldOffset(0x0018)] public uint PartyGold;

    [FieldOffset(0x001c)] public ushort NpcStructCountForPartyEx;

    [FieldOffset(0x001e)] public ushort WeatherBitfield;

    [FieldOffset(0x0020)] public uint NpcStructOffsetForParty;

    [FieldOffset(0x0024)] public uint NpcStructCountForPartyInc;

    [FieldOffset(0x0028)] public uint Unknown1;

    [FieldOffset(0x002c)] public uint Unknown2;

    [FieldOffset(0x0030)] public uint NpcStructOffsetForNonParty;

    [FieldOffset(0x0034)] public uint NpcStructCountForNonParty;

    [FieldOffset(0x0038)] public uint GlobalNamespaceVarOffset;

    [FieldOffset(0x003c)] public uint GlobalNamespaceVarCount;

    [FieldOffset(0x0040)] public fixed char MainArea[8];

    [FieldOffset(0x0048)] public uint FamilarExtraOffset;

    [FieldOffset(0x004c)] public uint JournalEntriesCount;

    [FieldOffset(0x0050)] public uint JournalEntriesOffset;

    [FieldOffset(0x0054)] public uint PartyReputation;

    [FieldOffset(0x0058)] public fixed char CurrentArea [8];

    [FieldOffset(0x0060)] public uint GuiFlags;

    [FieldOffset(0x0064)] public uint LoadingProgress;

    [FieldOffset(0x0068)] public uint FamilarInfoOffset;

    [FieldOffset(0x006c)] public uint StoredLocOffset;

    [FieldOffset(0x0070)] public uint StoredLocCount;

    [FieldOffset(0x0074)] public uint GameTimeSec;

    [FieldOffset(0x0078)] public uint PocketPlaneOffset;

    [FieldOffset(0x007c)] public uint PocketPlaneCount;

    [FieldOffset(0x0080)] public fixed byte Unknown3 [52];
}

これは、このオブジェクトをマップする方法です。

        string path = @"C:\Baldur.gam";

        byte[] content = IoHelper.ReadBinaryFile(path);

        unsafe
        {
            fixed (byte* pointContent = content)
            {
                Header* header = (Header*) pointContent; 
            }
        }

これは、私が持っている char 署名の結果です。

[0] = 21057 '剁' [1] = 13624 '㔸'

これらの文字は実際には合理的ではありません。これはエンコーディングが原因だと思います。誰もこれに対する解決策を知っていますか? または、自分で Encoding.ASCII.GetString を使用して char 配列を読み取る必要がありますか? このメソッドで特定のサイズの byte[] を読み取ると、真の結果が得られます。

また、これらの種類の構造にはさまざまなバージョンがあります。上記のサンプルの例として、V.2.0 バージョンの Baldur's Gate 2 Gam ファイルがあります。ただし、バルダーズ ゲート 1 ではバージョンが v.1.0 に変更され、私の方法では動作しません。これらのさまざまなメソッドを読み取り、それらをモデルにマップしてから、UI レイヤーに送り返したいと思います。異なる種類のバージョンを読むための提案はありますか?

前もって感謝します。

4

1 に答える 1

3

私は私の問題を解決します。

私が尋ねた人々は言った。

「.net char は 2 バイトの長さです。直接キャストする場合は実行できません。これを行うには、Marshall クラスの PtrToStructureMethod を使用できます」

固定バイト メンバーを文字列に置き換え、MarshalAs 属性を次のように使用します。

    [FieldOffset(0x0004), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
    public string Version;

そして、マッピングコードを ; に置き換えます。

        string path = @"G:\Games\BGOrg\BGII - SoA\save\000000001-Quick-Save\Baldur.gam";

        byte[] content = IoHelper.ReadBinaryFile(path);

        IntPtr unmanagedPointer = Marshal.AllocHGlobal(content.Length);
        Marshal.Copy(content, 0, unmanagedPointer, content.Length);

        Header header = (Header) Marshal.PtrToStructure(unmanagedPointer, typeof (Header));

魅力のように機能します:)

よろしく。

于 2012-08-06T18:42:50.637 に答える