Пример #1
0
        private static readonly byte[] magic = { 0x45, 0x58, 0x48, 0x46 }; // EXHF

        public Exh(string name)
        {
            using (var steam = new MemoryStream(File.ReadAllBytes(name)))
            {
                using (var reader = new BinaryReaderBigEndian(steam))
                {
                    byte[] magicBytes = reader.ReadBytes(4);
                    Debug.Assert(magicBytes.SequenceEqual(magic));

                    ushort version = reader.ReadUInt16Be();
                    Debug.Assert(version == 3);

                    DataSize  = reader.ReadUInt16Be();
                    Columns   = new Column[reader.ReadUInt16Be()];
                    Pages     = new Page[reader.ReadUInt16Be()];
                    Languages = new ExdLanguage[reader.ReadUInt16Be()];
                    reader.ReadUInt16Be();
                    reader.ReadUInt32Be();
                    Entries = reader.ReadUInt32Be();
                    reader.Skip(8); // padding

                    for (uint i = 0u; i < Columns.Length; i++)
                    {
                        Columns[i] = new Column
                        {
                            Type   = (ExdDataType)reader.ReadUInt16Be(),
                            Offset = reader.ReadUInt16Be()
                        };
                    }

                    //Columns = Columns.OrderBy(c => c.Offset).ToArray();

                    for (uint i = 0u; i < Pages.Length; i++)
                    {
                        Pages[i] = new Page
                        {
                            Id      = reader.ReadUInt32Be(),
                            Entries = reader.ReadUInt32Be()
                        };
                    }

                    for (uint i = 0u; i < Languages.Length; i++)
                    {
                        Languages[i] = (ExdLanguage)reader.ReadUInt16();
                    }
                }
            }
        }
Пример #2
0
        private static readonly byte[] magic = { 0x45, 0x58, 0x44, 0x46 }; // EXDF

        public void Load <T>(string name, Exh header, uint pageIndex) where T : Entry, new()
        {
            using (var steam = new MemoryStream(File.ReadAllBytes(name)))
            {
                using (var reader = new BinaryReaderBigEndian(steam))
                {
                    byte[] magicBytes = reader.ReadBytes(4);
                    Debug.Assert(magicBytes.SequenceEqual(magic));

                    ushort version = reader.ReadUInt16Be();
                    Debug.Assert(version == 2);

                    reader.ReadUInt16Be();

                    uint offsetSize = reader.ReadUInt32Be();
                    //Debug.Assert(offsetSize == header.Pages[pageIndex].Entries * 8);

                    uint dataSize = reader.ReadUInt32Be();
                    reader.Skip(16); // padding

                    // this the correct way to handle this??
                    uint entries = header.Pages[pageIndex].Entries;
                    if (header.Pages.Length == 1 && header.Pages[0].Entries > header.Entries)
                    {
                        entries = header.Entries;
                    }

                    Entries = new Entry[entries];
                    for (uint i = 0u; i < entries; i++)
                    {
                        Entries[i] = new T
                        {
                            Index  = reader.ReadUInt32Be(),
                            Offset = reader.ReadUInt32Be(),
                            Data   = new object[header.Columns.Length]
                        };
                    }

                    foreach (Entry entry in Entries)
                    {
                        reader.BaseStream.Position = entry.Offset;

                        reader.ReadUInt32Be(); // size
                        reader.ReadUInt16Be();

                        long dataTable = reader.BaseStream.Position;
                        for (uint i = 0u; i < header.Columns.Length; i++)
                        {
                            reader.BaseStream.Position = dataTable + header.Columns[i].Offset;
                            if ((uint)header.Columns[i].Type >= 0x19u)
                            {
                                int bitOffset = (int)header.Columns[i].Type - 0x19;
                                entry.Data[i] = (reader.ReadByte() & (1 << bitOffset)) != 0;
                            }
                            else
                            {
                                switch (header.Columns[i].Type)
                                {
                                case ExdDataType.String:
                                    entry.Data[i] = reader.ReadUInt32Be();
                                    break;

                                case ExdDataType.Bool:
                                    entry.Data[i] = reader.ReadBoolean();
                                    break;

                                case ExdDataType.SByte:
                                    entry.Data[i] = reader.ReadSByte();
                                    break;

                                case ExdDataType.Byte:
                                    entry.Data[i] = reader.ReadByte();
                                    break;

                                case ExdDataType.Short:
                                    entry.Data[i] = reader.ReadInt16();
                                    break;

                                case ExdDataType.UShort:
                                    entry.Data[i] = reader.ReadUInt16Be();
                                    break;

                                case ExdDataType.Int:
                                    entry.Data[i] = reader.ReadInt32Be();
                                    break;

                                case ExdDataType.UInt:
                                    entry.Data[i] = reader.ReadUInt32Be();
                                    break;

                                case ExdDataType.ULong:
                                    entry.Data[i] = reader.ReadUInt64Be();
                                    break;

                                default:
                                    Debug.Assert(false, $"Unhandled EXD data type {header.Columns[i].Type}");
                                    break;
                                }
                            }
                        }

                        long stringTable = dataTable + header.DataSize;
                        for (uint i = 0u; i < header.Columns.Length; i++)
                        {
                            if (header.Columns[i].Type != ExdDataType.String)
                            {
                                continue;
                            }

                            reader.BaseStream.Position = stringTable + (uint)entry.Data[i];
                            entry.Data[i] = reader.ReadExdString();
                        }

                        entry.Initialise();
                    }
                }
            }
        }