2012-08-05 69 views
3

我正在嘗試開發由無限引擎(Baldur's gate,planescape Torment等)創建的遊戲的修改工具。我知道無限引擎文件中有什麼樣的數據結構,我正在從byte []內容映射某個對象。然而它缺乏一些表現,我對此並不滿意。閱讀使用正確編碼的固定字符陣列

我在託管世界上的映射對象是結構,我知道它們表示多少字節。因此我決定在不安全的代碼中進行映射過程。我對Uint沒有任何問題,但是像字符串類型那樣,我喜歡使用值類型化值,但我對char []編碼問題有困難。

爲例,你可以看到結構GAM文件的標題在C#中,

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 Signature的結果我有;

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

這些字符是真的不合理的。我想這是由編碼引起的。有誰知道這個解決方案?或者我必須自己用Encoding.ASCII.GetString讀取char數組嗎?如果我用這種方法讀取特定大小的字節[],我會得到真正的結果。

還有這些結構的不同版本。在上面的示例中,有一個V.2.0版本的Baldur's Gate 2 Gam文件。但是,在博德之門1中,版本變爲v.1.0,這不適用於我的方法。我想閱讀這些不同的方法,並將它們映射到模型中,然後將它們發送回UI層。你有什麼建議閱讀不同種類的版本?

在此先感謝。

回答

2

我解決了我的問題。

我問過的人說過;

「使用.NET字符爲2個字節長。如果你直接投你不能做到這一點。要做到這一點,你可以用馬歇爾類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)); 

就像一個魅力:)

問候。