2012-08-05 37 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)); 

就像一个魅力:)

问候。