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); }