Пример #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MpqHeroesArchive"/> class.
        /// </summary>
        /// <param name="stream">The stream containing the archive to be read.</param>
        /// <exception cref="ArgumentNullException" />
        internal MpqHeroesArchive(Stream stream)
        {
            _archiveStream = stream ?? throw new ArgumentNullException(nameof(stream));

            Span <byte> headerBuffer = stackalloc byte[2048]; // guess how much the header will be

            stream.Read(headerBuffer);

            BitReader bitReader = new BitReader(headerBuffer, EndianType.LittleEndian);

            _mpqHeader = new MpqHeader(ref bitReader);

            if (_mpqHeader.HashTableOffsetHigh != 0 || _mpqHeader.ExtendedBlockTableOffset != 0 || _mpqHeader.BlockTableOffsetHigh != 0)
            {
                throw new MpqHeroesToolException("MPQ format version 1 features are not supported");
            }

            _blockSize = 0x200 << _mpqHeader.BlockSize;

            // LoadHashTable
            Span <byte> hashBuffer = stackalloc byte[(int)(_mpqHeader.HashTableSize * MpqHash.Size)]; // get the hash table buffer

            stream.Position = (int)_mpqHeader.HashTablePos;
            stream.Read(hashBuffer);

            DecryptTable(hashBuffer, "(hash table)");

            _mpqHashes = new MpqHash[_mpqHeader.HashTableSize];

            BitReader mpqHashesBitReader = new BitReader(hashBuffer, EndianType.LittleEndian);

            for (int i = 0; i < _mpqHeader.HashTableSize; i++)
            {
                _mpqHashes[i] = new MpqHash(ref mpqHashesBitReader);
            }

            // LoadEntryTable;
            Span <byte> entryBuffer = stackalloc byte[(int)(_mpqHeader.BlockTableSize * MpqHeroesArchiveEntry.Size)]; // get the entry table buffer

            stream.Position = (int)_mpqHeader.BlockTablePos;
            stream.Read(entryBuffer);

            DecryptTable(entryBuffer, "(block table)");

            _mpqArchiveEntries = new MpqHeroesArchiveEntry[_mpqHeader.BlockTableSize];
            BitReader mpqArchivesEntryBitReader = new BitReader(entryBuffer, EndianType.LittleEndian);

            for (int i = 0; i < _mpqHeader.BlockTableSize; i++)
            {
                _mpqArchiveEntries[i] = new MpqHeroesArchiveEntry(ref mpqArchivesEntryBitReader, (uint)_mpqHeader.HeaderOffset);
            }
        }
Пример #2
0
        private void ParseReplayServerBattlelobby(StormReplay stormReplay, ArrayPool <byte> pool)
        {
            MpqHeroesArchiveEntry entry = _stormMpqArchive.GetEntry(ReplayServerBattlelobby.FileName);
            int size = (int)entry.FileSize;

            byte[]      poolBuffer = pool.Rent(size);
            Span <byte> buffer     = new Span <byte>(poolBuffer).Slice(0, size);

            _stormMpqArchive.DecompressEntry(entry, buffer);
            ReplayServerBattlelobby.Parse(stormReplay, buffer);

            pool.Return(poolBuffer);
        }
Пример #3
0
        public MpqHeroesArchiveEntry GetEntry(string fileName)
        {
            if (!TryGetHashEntry(fileName, out MpqHash hash))
            {
                throw new FileNotFoundException("File not found: " + fileName);
            }

            MpqHeroesArchiveEntry entry = _mpqArchiveEntries[hash.BlockIndex];

            if (entry.FileName == null)
            {
                entry.FileName = fileName;
            }

            return(entry);
        }
Пример #4
0
        public bool AddListfileFileNames()
        {
            if (!AddFileName("(listfile)"))
            {
                return(false);
            }

            MpqHeroesArchiveEntry entry = GetEntry("(listfile)");

            Span <byte> buffer = stackalloc byte[(int)entry.FileSize];

            DecompressEntry(entry, buffer);

            AddFileNames(buffer);

            return(true);
        }
Пример #5
0
        public ReadOnlySpan <byte> OpenFile(string filename)
        {
            if (!TryGetHashEntry(filename, out MpqHash hash))
            {
                throw new FileNotFoundException("File not found: " + filename);
            }

            MpqHeroesArchiveEntry entry = _mpqArchiveEntries[hash.BlockIndex];

            if (entry.FileName == null)
            {
                entry.FileName = filename;
            }

            Span <byte> buffer = new byte[(int)entry.FileSize];

            DecompressEntry(entry, buffer);

            return(buffer);
        }