/// <summary> /// Initializes a new instance of the <see cref="Warcraft.MPQ.MPQ"/> class. /// </summary> /// <param name="mpqStream">An open stream to data containing an MPQ archive.</param> public MPQ([NotNull] Stream mpqStream) { _archiveReader = new BinaryReader(mpqStream); Header = new MPQHeader(_archiveReader.ReadBytes((int)PeekHeaderSize())); // Seek to the hash table and load it _archiveReader.BaseStream.Position = (long)Header.GetHashTableOffset(); var encryptedHashTable = _archiveReader.ReadBytes((int)Header.GetHashTableSize()); var hashTableData = MPQCrypt.DecryptData(encryptedHashTable, HashTable.TableKey); ArchiveHashTable = new HashTable(hashTableData); // Seek to the block table and load it _archiveReader.BaseStream.Position = (long)Header.GetBlockTableOffset(); var encryptedBlockTable = _archiveReader.ReadBytes((int)Header.GetBlockTableSize()); var blockTableData = MPQCrypt.DecryptData(encryptedBlockTable, BlockTable.TableKey); ArchiveBlockTable = new BlockTable(blockTableData); if (Header.GetFormat() != MPQFormat.ExtendedV1) { return; } // Seek to the extended block table and load it, if necessary if (Header.GetExtendedBlockTableOffset() <= 0) { return; } _archiveReader.BaseStream.Position = (long)Header.GetExtendedBlockTableOffset(); var extendedTable = new List <ushort>(); for (var i = 0; i < Header.GetBlockTableEntryCount(); ++i) { extendedTable.Add(_archiveReader.ReadUInt16()); } ExtendedBlockTable = extendedTable; }
/// <summary> /// Initializes a new instance of the <see cref="Warcraft.MPQ.MPQ"/> class. /// </summary> /// <param name="mpqStream">An open stream to data containing an MPQ archive.</param> public MPQ(Stream mpqStream) { ArchiveReader = new BinaryReader(mpqStream); Header = new MPQHeader(ArchiveReader.ReadBytes((int)PeekHeaderSize())); // Seek to the hash table and load it ArchiveReader.BaseStream.Position = (long)Header.GetHashTableOffset(); byte[] hashTableData; if (Header.IsHashTableCompressed()) { byte[] encryptedData = ArchiveReader.ReadBytes((int)Header.GetCompressedHashTableSize()); byte[] decryptedData = MPQCrypt.DecryptData(encryptedData, HashTable.TableKey); BlockFlags tableFlags = BlockFlags.IsCompressedMultiple; hashTableData = Compression.DecompressSector(decryptedData, tableFlags); } else { byte[] encryptedData = ArchiveReader.ReadBytes((int)Header.GetHashTableSize()); hashTableData = MPQCrypt.DecryptData(encryptedData, HashTable.TableKey); } ArchiveHashTable = new HashTable(hashTableData); // Seek to the block table and load it ArchiveReader.BaseStream.Position = (long)Header.GetBlockTableOffset(); byte[] blockTableData; if (Header.IsBlockTableCompressed()) { byte[] encryptedData = ArchiveReader.ReadBytes((int)Header.GetCompressedBlockTableSize()); byte[] decryptedData = MPQCrypt.DecryptData(encryptedData, BlockTable.TableKey); BlockFlags tableFlags = BlockFlags.IsCompressedMultiple; blockTableData = Compression.DecompressSector(decryptedData, tableFlags); } else { byte[] encryptedData = ArchiveReader.ReadBytes((int)Header.GetBlockTableSize()); blockTableData = MPQCrypt.DecryptData(encryptedData, BlockTable.TableKey); } ArchiveBlockTable = new BlockTable(blockTableData); // TODO: Seek to the extended hash table and load it // TODO: Seek to the extended block table and load it if (Header.GetFormat() >= MPQFormat.ExtendedV1) { // Seek to the extended block table and load it, if neccesary if (Header.GetExtendedBlockTableOffset() <= 0) { return; } ArchiveReader.BaseStream.Position = (long)Header.GetExtendedBlockTableOffset(); for (int i = 0; i < Header.GetBlockTableEntryCount(); ++i) { ExtendedBlockTable.Add(ArchiveReader.ReadUInt16()); } } }