Example #1
0
 public ExdTable(Exh header)
 {
     foreach (ExdLanguage language in header.Languages)
     {
         entries.Add(language, new Dictionary <uint, T>((int)header.Entries));
     }
 }
Example #2
0
        public static ExdTable <T> Load(string name)
        {
            var header   = new Exh(name);
            var exdTable = new ExdTable <T>(header);

            foreach (ExdLanguage language in header.Languages)
            {
                for (uint i = 0u; i < header.Pages.Length; i++)
                {
                    string exdPath = Path.Combine(Path.GetDirectoryName(name) ?? "", $"{Path.GetFileNameWithoutExtension(name)}_{header.Pages[i].Id}");
                    if (language != ExdLanguage.None)
                    {
                        exdPath += $"_{language.ToString().ToLower()}";
                    }

                    exdPath = Path.ChangeExtension(exdPath, ".exd");

                    // some EXH files contain language codes but don't have the associated EXD files
                    if (!File.Exists(exdPath))
                    {
                        continue;
                    }

                    var exd = new Exd();
                    exd.Load <T>(exdPath, header, i);
                    exdTable.Add(language, exd);
                }
            }

            return(exdTable);
        }
Example #3
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();
                    }
                }
            }
        }