public void Deserialize(Stream input, Endian endian, IStringTable stringTable)
        {
            var nameIndex = input.ReadValueU32(endian);

            this.Name = stringTable.Get(nameIndex);

            uint fileCount      = input.ReadValueU32(endian);
            uint directoryCount = input.ReadValueU32(endian);
            uint unknown        = input.ReadValueU32(endian);

            if (unknown != 0)
            {
                throw new InvalidOperationException();
            }

            this.Directories.Clear();
            for (uint i = 0; i < directoryCount; i++)
            {
                var dir = new DirectoryEntry(this);
                dir.Deserialize(input, endian, stringTable);
                this.Directories.Add(dir);
            }

            this.Files.Clear();
            for (uint i = 0; i < fileCount; i++)
            {
                var file = new FileEntry(this);
                file.Deserialize(input, endian, stringTable);
                this.Files.Add(file);
            }
        }
        private void Deserialize(Stream input, Endian endian)
        {
            var version = input.ReadValueU16(endian);

            if (IsValidVersion(version) == false)
            {
                throw new FormatException("invalid or unsupported wad version");
            }
            this.Version = version;

            if (version == 0x101 || version >= 0x200)
            {
                this.Flags = input.ReadValueEnum <Wad.ArchiveFlags>(endian);
            }
            else
            {
                this.Flags = Wad.ArchiveFlags.None;
            }

            if (version >= 0x202)
            {
                var headerXmlLength = input.ReadValueU32(endian);
                this.HeaderXml = input.ReadBytes(headerXmlLength);
            }

            var stringTableSize = input.ReadValueU32(endian);

            using (var stringTableData = new MemoryStream())
            {
                if (version >= 0x200)
                {
                    stringTableData.WriteFromStream(input, stringTableSize);
                    stringTableData.Position = 0;
                }

                this.DataTypes.Clear();
                if ((this.Flags & Wad.ArchiveFlags.HasDataTypes) == Wad.ArchiveFlags.HasDataTypes)
                {
                    uint count = input.ReadValueU32(endian);
                    for (uint i = 0; i < count; i++)
                    {
                        var item = new Wad.DataType();
                        item.Index    = input.ReadValueU32(endian);
                        item.Unknown2 = input.ReadValueU32(endian);
                        this.DataTypes.Add(item);
                    }
                }

                var totalFileCount      = input.ReadValueU32(endian);
                var totalDirectoryCount = input.ReadValueU32(endian);

                this.DataOffsets.Clear();
                if (version >= 0x200)
                {
                    uint count = input.ReadValueU32(endian);
                    for (uint i = 0; i < count; i++)
                    {
                        this.DataOffsets.Add(input.ReadValueU32(endian));
                    }
                }
                else
                {
                    // don't know how to handle this situation
                    throw new InvalidOperationException();
                }

                if (version == 0x100)
                {
                    stringTableData.WriteFromStream(input, stringTableSize);
                    stringTableData.Position = 0;
                }

                var stringTableReader = new StringTableReader(stringTableData);

                using (var fileTableData = input.ReadToMemoryStream((totalDirectoryCount + totalFileCount) * 16))
                {
                    while (fileTableData.Position < fileTableData.Length)
                    {
                        var dir = new Wad.DirectoryEntry(null);
                        dir.Deserialize(fileTableData, endian, stringTableReader);
                        this.Directories.Add(dir);
                    }

                    if (this.TotalFileCount != totalFileCount ||
                        this.TotalDirectoryCount != totalDirectoryCount)
                    {
                        throw new InvalidOperationException();
                    }

                    if (fileTableData.Position != fileTableData.Length)
                    {
                        throw new InvalidOperationException();
                    }
                }
            }
        }