Пример #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Warcraft.MPQ.MPQ"/> class.
        /// This constructor creates an empty archive.
        /// </summary>
        /// <param name="inFormat">In format.</param>
        public MPQ(MPQFormat inFormat)
        {
            if (inFormat > MPQFormat.ExtendedV1)
            {
                throw new NotImplementedException();
            }

            this.Header            = new MPQHeader(inFormat);
            this.ArchiveHashTable  = new HashTable();
            this.ArchiveBlockTable = new BlockTable();
        }
Пример #2
0
        /// <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;
        }
Пример #3
0
        /// <summary>
        /// Releases all resource used by the <see cref="Warcraft.MPQ.MPQ"/> object.
        /// </summary>
        /// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="Warcraft.MPQ.MPQ"/>. The <see cref="Dispose"/>
        /// method leaves the <see cref="Warcraft.MPQ.MPQ"/> in an unusable state. After calling <see cref="Dispose"/>, you must
        /// release all references to the <see cref="Warcraft.MPQ.MPQ"/> so the garbage collector can reclaim the memory that
        /// the <see cref="Warcraft.MPQ.MPQ"/> was occupying.</remarks>
        public void Dispose()
        {
            this.Header            = null;
            this.ArchiveHashTable  = null;
            this.ArchiveBlockTable = null;

            if (this.ExtendedBlockTable.Count > 0)
            {
                this.ExtendedBlockTable.Clear();
            }

            if (this.ExternalListfile.Count > 0)
            {
                this.ExternalListfile.Clear();
            }

            if (this.ArchiveReader != null)
            {
                this.ArchiveReader.Close();
                this.ArchiveReader.Dispose();
            }

            this.IsDisposed = true;
        }
Пример #4
0
        /// <inheritdoc />
        public void Dispose()
        {
            Header            = null;
            ArchiveHashTable  = null;
            ArchiveBlockTable = null;

            if (ExtendedBlockTable.Count > 0)
            {
                ExtendedBlockTable.Clear();
            }

            if (ExternalListfile.Count > 0)
            {
                ExternalListfile.Clear();
            }

            if (ArchiveReader != null)
            {
                ArchiveReader.Close();
                ArchiveReader.Dispose();
            }

            IsDisposed = true;
        }
Пример #5
0
        /// <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)
        {
            this.ArchiveReader = new BinaryReader(mpqStream);

            this.Header = new MPQHeader(this.ArchiveReader.ReadBytes((int)PeekHeaderSize()));

            // Seek to the hash table and load it
            this.ArchiveReader.BaseStream.Position = (long)this.Header.GetHashTableOffset();

            byte[] hashTableData;
            if (this.Header.IsHashTableCompressed())
            {
                byte[] encryptedData = this.ArchiveReader.ReadBytes((int)this.Header.GetCompressedHashTableSize());
                byte[] decryptedData = MPQCrypt.DecryptData(encryptedData, HashTable.TableKey);

                BlockFlags tableFlags = BlockFlags.IsCompressedMultiple;
                hashTableData = Compression.DecompressSector(decryptedData, tableFlags);
            }
            else
            {
                byte[] encryptedData = this.ArchiveReader.ReadBytes((int)this.Header.GetHashTableSize());
                hashTableData = MPQCrypt.DecryptData(encryptedData, HashTable.TableKey);
            }

            this.ArchiveHashTable = new HashTable(hashTableData);

            // Seek to the block table and load it
            this.ArchiveReader.BaseStream.Position = (long)this.Header.GetBlockTableOffset();

            byte[] blockTableData;
            if (this.Header.IsBlockTableCompressed())
            {
                byte[] encryptedData = this.ArchiveReader.ReadBytes((int)this.Header.GetCompressedBlockTableSize());
                byte[] decryptedData = MPQCrypt.DecryptData(encryptedData, BlockTable.TableKey);

                BlockFlags tableFlags = BlockFlags.IsCompressedMultiple;
                blockTableData = Compression.DecompressSector(decryptedData, tableFlags);
            }
            else
            {
                byte[] encryptedData = this.ArchiveReader.ReadBytes((int)this.Header.GetBlockTableSize());
                blockTableData = MPQCrypt.DecryptData(encryptedData, BlockTable.TableKey);
            }

            this.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 (this.Header.GetFormat() >= MPQFormat.ExtendedV1)
            {
                // Seek to the extended block table and load it, if neccesary
                if (this.Header.GetExtendedBlockTableOffset() > 0)
                {
                    this.ArchiveReader.BaseStream.Position = (long)this.Header.GetExtendedBlockTableOffset();

                    for (int i = 0; i < this.Header.GetBlockTableEntryCount(); ++i)
                    {
                        this.ExtendedBlockTable.Add(this.ArchiveReader.ReadUInt16());
                    }
                }
            }
        }