public void Deserialize(Stream input)
        {
            var basePosition = input.Position;

            var magic = input.ReadValueU32(Endian.Big);

            if (magic != Signature)
            {
                throw new FormatException("unsupported archive version");
            }

            input.Position += 4; // skip version
            var platform = (Archive.Platform)input.ReadValueU32(Endian.Big);

            if (platform != Archive.Platform.PC &&
                platform != Archive.Platform.Xbox360 &&
                platform != Archive.Platform.PS3)
            {
                throw new FormatException("unsupported archive platform");
            }

            var endian = platform == Archive.Platform.PC ? Endian.Little : Endian.Big;

            input.Position = basePosition;

            uint version;

            using (var data = input.ReadToMemoryStreamSafe(12, endian))
            {
                data.Position += 4; // skip magic
                version        = data.ReadValueU32(endian);
                data.Position += 4; // skip platform
            }

            if (version != 19)
            {
                throw new FormatException("unsupported archive version");
            }

            Archive.FileHeader fileHeader;
            using (var data = input.ReadToMemoryStreamSafe(52, endian))
            {
                fileHeader = Archive.FileHeader.Read(data, endian);
            }

            input.Position = basePosition + fileHeader.ResourceTypeTableOffset;
            var resourceTypeCount = input.ReadValueU32(endian);
            var resourceTypes     = new Archive.ResourceType[resourceTypeCount];

            for (uint i = 0; i < resourceTypeCount; i++)
            {
                resourceTypes[i] = Archive.ResourceType.Read(input, endian);
            }

            input.Position = basePosition + fileHeader.BlockTableOffset;
            var blockStream = BlockReaderStream.FromStream(input, endian);

            var resources = new Archive.ResourceEntry[fileHeader.ResourceCount];

            for (uint i = 0; i < fileHeader.ResourceCount; i++)
            {
                Archive.ResourceHeader resourceHeader;
                using (var data = blockStream.ReadToMemoryStreamSafe(26, endian))
                {
                    resourceHeader = Archive.ResourceHeader.Read(data, endian);
                }

                if (resourceHeader.Size < 30)
                {
                    throw new FormatException();
                }

                resources[i] = new Archive.ResourceEntry()
                {
                    TypeId            = (int)resourceHeader.TypeId,
                    Version           = resourceHeader.Version,
                    Data              = blockStream.ReadBytes((int)resourceHeader.Size - 30),
                    SlotRamRequired   = resourceHeader.SlotRamRequired,
                    SlotVramRequired  = resourceHeader.SlotVramRequired,
                    OtherRamRequired  = resourceHeader.OtherRamRequired,
                    OtherVramRequired = resourceHeader.OtherVramRequired,
                };
            }

            input.Position = basePosition + fileHeader.XmlOffset;
            var xml = input.ReadString((int)(input.Length - input.Position), Encoding.ASCII);

            this._ResourceTypes.Clear();
            this._ResourceEntries.Clear();

            this._Endian            = endian;
            this._Platform          = platform;
            this._SlotRamRequired   = fileHeader.SlotRamRequired;
            this._SlotVramRequired  = fileHeader.SlotVramRequired;
            this._OtherRamRequired  = fileHeader.OtherRamRequired;
            this._OtherVramRequired = fileHeader.OtherVramRequired;
            this._Unknown20         = (byte[])fileHeader.Unknown20.Clone();
            this._ResourceTypes.AddRange(resourceTypes);
            this._ResourceInfoXml = xml;
            this._ResourceEntries.AddRange(resources);
        }
        public void Deserialize(Stream input)
        {
            // Read Texture Names before we start.
            // They are from an external file, taken from MTL.
            ReadTextureNames();

            if (IsGameType(GamesEnumerator.MafiaI_DE))
            {
                if (!File.Exists("libs/oo2core_8_win64.dll"))
                {
                    MessageBox.Show(Language.GetString("$M1DE_OODLEERROR"), "Toolkit");
                    return;
                }
            }

            var basePosition = input.Position;

            // Check Magic, should be SDS.
            var magic = input.ReadValueU32(Endian.Big);

            if (magic != Signature)
            {
                string FormatError = string.Format("Unsupported Archive Signature: {0}", magic);
                throw new FormatException(FormatError);
            }

            input.Seek(8, SeekOrigin.Begin);
            // Check Platform. There may be values for XboxOne and PS4, but that is unknown.
            var platform = (Platform)input.ReadValueU32(Endian.Big);

            if (platform != Platform.PC && platform != Platform.Xbox360 && platform != Platform.PS3)
            {
                string FormatError = string.Format("Unsupported Archive Platform: {0}", platform);
                throw new FormatException(FormatError);
            }

            var endian = platform == Archive.Platform.PC ? Endian.Little : Endian.Big;

            input.Seek(4, SeekOrigin.Begin);
            // Check Version, should be 19 (Mafia: II) or 20 (Mafia III).
            var version = input.ReadValueU32(endian);

            if (version != 19 && version != 20)
            {
                string FormatError = string.Format("Unsupported Archive Version: {0}", version);
                throw new FormatException(FormatError);
            }

            input.Seek(12, SeekOrigin.Begin);
            input.Position = basePosition;

            using (var data = input.ReadToMemoryStreamSafe(12, endian))
            {
                data.Position += 4; // skip magic
                _Version       = data.ReadValueU32(endian);
                data.Position += 4; // skip platform
            }

            if (_Version != 19 && _Version != 20)
            {
                throw new FormatException("unsupported archive version");
            }

            Archive.FileHeader fileHeader;
            using (var data = input.ReadToMemoryStreamSafe(52, endian))
            {
                fileHeader = Archive.FileHeader.Read(data, endian);
            }

            input.Position = basePosition + fileHeader.ResourceTypeTableOffset;
            var resourceTypeCount = input.ReadValueU32(endian);
            var resourceTypes     = new Archive.ResourceType[resourceTypeCount];

            for (uint i = 0; i < resourceTypeCount; i++)
            {
                resourceTypes[i] = Archive.ResourceType.Read(input, endian);
            }

            input.Position = basePosition + fileHeader.BlockTableOffset;
            var blockStream = BlockReaderStream.FromStream(input, endian);

            var resources = new Archive.ResourceEntry[fileHeader.ResourceCount];

            for (uint i = 0; i < fileHeader.ResourceCount; i++)
            {
                Archive.ResourceHeader resourceHeader;
                var size = (_Version == 20 ? 34 : 26);
                using (var data = blockStream.ReadToMemoryStreamSafe(size, endian))
                {
                    resourceHeader = Archive.ResourceHeader.Read(data, endian, _Version);
                }

                if (resourceHeader.Size < 30)
                {
                    throw new FormatException();
                }

                resources[i] = new Archive.ResourceEntry()
                {
                    TypeId            = (int)resourceHeader.TypeId,
                    Version           = resourceHeader.Version,
                    Data              = blockStream.ReadBytes((int)resourceHeader.Size - (size + 4)),
                    FileHash          = resourceHeader.FileHash,
                    SlotRamRequired   = resourceHeader.SlotRamRequired,
                    SlotVramRequired  = resourceHeader.SlotVramRequired,
                    OtherRamRequired  = resourceHeader.OtherRamRequired,
                    OtherVramRequired = resourceHeader.OtherVramRequired,
                };
            }
            if (fileHeader.XmlOffset != 0)
            {
                input.Position = basePosition + fileHeader.XmlOffset;
                var xml = input.ReadString((int)(input.Length - input.Position), Encoding.ASCII);
                this._ResourceInfoXml = xml;
            }

            this._ResourceTypes.Clear();
            this._ResourceEntries.Clear();

            this._Endian            = endian;
            this._Platform          = platform;
            this._SlotRamRequired   = fileHeader.SlotRamRequired;
            this._SlotVramRequired  = fileHeader.SlotVramRequired;
            this._OtherRamRequired  = fileHeader.OtherRamRequired;
            this._OtherVramRequired = fileHeader.OtherVramRequired;
            this._Unknown20         = (byte[])fileHeader.Unknown20.Clone();
            this._ResourceTypes.AddRange(resourceTypes);
            this._ResourceEntries.AddRange(resources);
        }