Ejemplo n.º 1
0
        public void Deserialize(Stream input)
        {
            var basePosition = input.Position;

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

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

            // Mafia II  = 13
            // Mafia III = 14
            var vers = input.ReadValueU32(Endian.Big);

            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
            }

            // Mafia II  = 19
            // Mafia III = 20
            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;
                //using (var data = blockStream.ReadToMemoryStreamSafe(26, endian))
                using (var data = blockStream.ReadToMemoryStreamSafe(34, endian)) // M3
                {
                    resourceHeader = Archive.ResourceHeader.Read(data, endian);
                }

                //if (resourceHeader.Size < 30)
                if (resourceHeader.Size < 38) // + XmlOffset
                {
                    throw new FormatException();
                }

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

            string xml = null;

            if (fileHeader.XmlOffset > 0)
            {
                input.Position = basePosition + fileHeader.XmlOffset;
                xml            = input.ReadString((int)(input.Length - input.Position), Encoding.ASCII);
            }

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

            _Endian            = endian;
            _Platform          = platform;
            _SlotRamRequired   = fileHeader.SlotRamRequired;
            _SlotVramRequired  = fileHeader.SlotVramRequired;
            _OtherRamRequired  = fileHeader.OtherRamRequired;
            _OtherVramRequired = fileHeader.OtherVramRequired;
            _Unknown20         = (byte[])fileHeader.Unknown20.Clone();
            _ResourceTypes.AddRange(resourceTypes);
            _ResourceInfoXml = xml;
            _ResourceEntries.AddRange(resources);
        }
        public const uint Signature = 0x6C7A4555; // 'zlEU'

        public static BlockReaderStream FromStream(Stream baseStream, Endian endian)
        {
            var instance = new BlockReaderStream(baseStream);

            var magic     = baseStream.ReadValueU32(endian);
            var alignment = baseStream.ReadValueU32(endian); // III = 0x00010000
            var flags     = baseStream.ReadValueU8();

            if (magic != Signature || /*alignment != 0x4000 ||*/ flags != 4)
            {
                throw new InvalidOperationException();
            }

            long virtualOffset = 0;

            while (true)
            {
                uint size         = baseStream.ReadValueU32(endian);
                bool isCompressed = baseStream.ReadValueU8() != 0;

                if (size == 0)
                {
                    break;
                }

                if (isCompressed == true)
                {
                    var compressedBlockHeader = CompressedBlockHeader.Read(baseStream, endian);

                    /*if (compressedBlockHeader.Unknown04 != 32 ||
                     *  compressedBlockHeader.Unknown08 != 81920 ||
                     *  compressedBlockHeader.Unknown0C != 135200769 ||
                     *  compressedBlockHeader.Unknown14 != 0 ||
                     *  compressedBlockHeader.Unknown18 != 0 ||
                     *  compressedBlockHeader.Unknown1C != 0)
                     * {
                     *  throw new InvalidOperationException();
                     * }*/

                    // 32        == 0x00000020
                    // 65536     == 0x00010000
                    // 135200769 == 0x080f0001

                    if (compressedBlockHeader.Unknown04 != 32 ||
                        compressedBlockHeader.Unknown08 != 65536 && compressedBlockHeader.Unknown08 != compressedBlockHeader.UncompressedSize ||
                        compressedBlockHeader.Unknown0C != 135200769 ||
                        compressedBlockHeader.Unknown14 != 0 ||
                        compressedBlockHeader.Unknown18 != 0 ||
                        compressedBlockHeader.Unknown1C != 0)
                    {
                        throw new InvalidOperationException();
                    }


                    if (size - 32 != compressedBlockHeader.CompressedSize)
                    {
                        throw new InvalidOperationException();
                    }

                    instance.AddCompressedBlock(virtualOffset,
                                                compressedBlockHeader.UncompressedSize,
                                                baseStream.Position,
                                                compressedBlockHeader.CompressedSize);
                    baseStream.Seek(compressedBlockHeader.CompressedSize, SeekOrigin.Current);
                }
                else
                {
                    instance.AddUncompressedBlock(virtualOffset, size, baseStream.Position);
                    baseStream.Seek(size, SeekOrigin.Current);
                }

                virtualOffset += alignment;
            }

            return(instance);
        }