public static MpqHeader FromReader(BinaryReader br) { uint num = br.ReadUInt32(); if (num != MpqId) { return(null); } MpqHeader header2 = new MpqHeader { ID = num, DataOffset = br.ReadUInt32(), ArchiveSize = br.ReadUInt32(), MpqVersion = br.ReadUInt16(), BlockSize = br.ReadUInt16(), HashTablePos = br.ReadUInt32(), BlockTablePos = br.ReadUInt32(), HashTableSize = br.ReadUInt32(), BlockTableSize = br.ReadUInt32() }; MpqHeader header = header2; if (header.MpqVersion == 1) { header.ExtendedBlockTableOffset = br.ReadInt64(); header.HashTableOffsetHigh = br.ReadInt16(); header.BlockTableOffsetHigh = br.ReadInt16(); } return(header); }
public static MpqHeader FromReader(BinaryReader br) { uint id = br.ReadUInt32(); if (id != MpqId) { return(null); } MpqHeader header = new MpqHeader { ID = id, DataOffset = br.ReadUInt32(), ArchiveSize = br.ReadUInt32(), MpqVersion = br.ReadUInt16(), BlockSize = br.ReadUInt16(), HashTablePos = br.ReadUInt32(), BlockTablePos = br.ReadUInt32(), HashTableSize = br.ReadUInt32(), BlockTableSize = br.ReadUInt32(), }; #if DEBUG if (header.MpqVersion == 0) { // Check validity if (Size != header.DataOffset) { throw new MpqParserException(string.Format("Invalid MPQ header field: DataOffset. Expected {0}, was {1}", Size, header.DataOffset)); } if (header.ArchiveSize != header.BlockTablePos + MpqEntry.Size * header.BlockTableSize) { throw new MpqParserException(string.Format("Invalid MPQ header field: ArchiveSize. Was {0}, expected {1}", header.ArchiveSize, header.BlockTablePos + MpqEntry.Size * header.BlockTableSize)); } if (header.HashTablePos != header.ArchiveSize - MpqHash.Size * header.HashTableSize - MpqEntry.Size * header.BlockTableSize) { throw new MpqParserException(string.Format("Invalid MPQ header field: HashTablePos. Was {0}, expected {1}", header.HashTablePos, header.ArchiveSize - MpqHash.Size * header.HashTableSize - MpqEntry.Size * header.BlockTableSize)); } if (header.BlockTablePos != header.HashTablePos + MpqHash.Size * header.HashTableSize) { throw new MpqParserException(string.Format("Invalid MPQ header field: BlockTablePos. Was {0}, expected {1}", header.BlockTablePos, header.HashTablePos + MpqHash.Size * header.HashTableSize)); } } #endif if (header.MpqVersion == 1) { header.ExtendedBlockTableOffset = br.ReadInt64(); header.HashTableOffsetHigh = br.ReadInt16(); header.BlockTableOffsetHigh = br.ReadInt16(); } return(header); }
private bool LocateMpqHeader() { BinaryReader br = new BinaryReader(this.BaseStream); for (long i = 0L; i < (this.BaseStream.Length - MpqHeader.Size); i += 0x200L) { this.BaseStream.Seek(i, SeekOrigin.Begin); this._mpqHeader = MpqHeader.FromReader(br); if (this._mpqHeader != null) { this._headerOffset = i; this._mpqHeader.SetHeaderOffset(this._headerOffset); return(true); } } return(false); }
private bool LocateMpqHeader() { BinaryReader br = new BinaryReader(BaseStream); // In .mpq files the header will be at the start of the file // In .exe files, it will be at a multiple of 0x200 for (long i = 0; i < BaseStream.Length - MpqHeader.Size; i += 0x200) { BaseStream.Seek(i, SeekOrigin.Begin); _mpqHeader = MpqHeader.FromReader(br); if (_mpqHeader != null) { _headerOffset = i; _mpqHeader.SetHeaderOffset(_headerOffset); return(true); } } return(false); }
private void Build(ICollection <MpqFile> mpqFiles, ushort?hashTableSize, ushort blockSize) { _blockSize = 0x200 << blockSize; var fileCount = (uint)mpqFiles.Count; _hashTable = new HashTable(Math.Max(hashTableSize ?? fileCount * 8, fileCount)); _blockTable = new BlockTable(fileCount); using (var writer = new BinaryWriter(BaseStream, new UTF8Encoding(false, true), true)) { // Skip the MPQ header, since its contents will be calculated afterwards. writer.Seek((int)MpqHeader.Size, SeekOrigin.Current); const bool archiveBeforeTables = true; uint hashTableEntries = 0; // Write Archive var fileIndex = (uint)0; var fileOffset = archiveBeforeTables ? MpqHeader.Size : throw new NotImplementedException(); var filePos = fileOffset; // TODO: add support for encryption of the archive files foreach (var mpqFile in mpqFiles) { uint locale = 0; mpqFile.AddToArchive((uint)_headerOffset, fileIndex, filePos, locale, _hashTable.Mask); if (archiveBeforeTables) { mpqFile.WriteToStream(writer); } hashTableEntries += _hashTable.Add(mpqFile.MpqHash, mpqFile.HashIndex, mpqFile.HashCollisions); _blockTable.Add(mpqFile.MpqEntry); filePos += mpqFile.MpqEntry.CompressedSize; fileIndex++; } // Match size of blocktable with amount of occupied entries in hashtable /* * for ( var i = blockTable.Size; i < hashTableEntries; i++ ) * { * var entry = MpqEntry.Dummy; * entry.SetPos( filePos ); * blockTable.Add( entry ); * } * blockTable.UpdateSize(); */ _hashTable.WriteToStream(writer); _blockTable.WriteToStream(writer); if (!archiveBeforeTables) { foreach (var mpqFile in mpqFiles) { mpqFile.WriteToStream(writer); } } writer.Seek((int)_headerOffset, SeekOrigin.Begin); _mpqHeader = new MpqHeader(filePos - fileOffset, _hashTable.Size, _blockTable.Size, blockSize, archiveBeforeTables); _mpqHeader.WriteToStream(writer); } }