private void ReadDirEntries(byte[] buffer, BlockInfo block, RDAMemoryResidentHelper mrm) { MemoryStream memoryStream = new MemoryStream(buffer); BinaryReader reader = new BinaryReader(memoryStream); for (uint fileId = 0; fileId < block.fileCount; ++fileId) { byte[] fileNameBytes = reader.ReadBytes((int)DirEntry.GetFilenameSize()); string fileNameString = Encoding.Unicode.GetString(fileNameBytes).Replace("\0", ""); DirEntry dirEntry = new DirEntry { filename = fileNameString, offset = ReadUIntVersionAware(reader), compressed = ReadUIntVersionAware(reader), filesize = ReadUIntVersionAware(reader), timestamp = ReadUIntVersionAware(reader), unknown = ReadUIntVersionAware(reader), }; RDAFile rdaFile = RDAFile.FromUnmanaged(fileHeader.version, dirEntry, block, read, mrm); rdaFileEntries.Add(rdaFile); } }
private ulong ReadBlock(ulong Offset, ulong beginningOfDataSection) { UpdateOutput("----- Reading Block at " + Offset); read.BaseStream.Position = (long)Offset; BlockInfo blockInfo = new BlockInfo { flags = read.ReadUInt32(), fileCount = read.ReadUInt32(), directorySize = ReadUIntVersionAware(read), decompressedSize = ReadUIntVersionAware(read), nextBlock = ReadUIntVersionAware(read), }; if ((blockInfo.flags & 8) != 8) { bool isMemoryResident = false; bool isEncrypted = false; bool isCompressed = false; if ((blockInfo.flags & 4) == 4) { UpdateOutput("MemoryResident"); isMemoryResident = true; } if ((blockInfo.flags & 2) == 2) { UpdateOutput("Encrypted"); isEncrypted = true; } if ((blockInfo.flags & 1) == 1) { UpdateOutput("Compressed"); isCompressed = true; } if (blockInfo.flags == 0) { UpdateOutput("No Flags"); } int decryptionSeed = 0; if (isEncrypted) { try { decryptionSeed = BinaryExtension.GetDecryptionSeed(fileHeader.version); } catch (ArgumentException e) { UpdateOutput("Skipping (" + blockInfo.fileCount + " files) -- " + e.Message); skippedDataSections.Add(new RDASkippedDataSection() { blockInfo = blockInfo, offset = beginningOfDataSection, size = (Offset - beginningOfDataSection), }); return(blockInfo.nextBlock); } } read.BaseStream.Position = (long)(Offset - blockInfo.directorySize); if (isMemoryResident) { read.BaseStream.Position -= GetUIntSizeVersionAware() * 2; } byte[] numArray2 = read.ReadBytes((int)blockInfo.directorySize); if (isEncrypted) { numArray2 = BinaryExtension.Decrypt(numArray2, decryptionSeed); } if (isCompressed) { numArray2 = ZLib.ZLib.Uncompress(numArray2, (int)blockInfo.decompressedSize); } RDAMemoryResidentHelper mrm = null; if (isMemoryResident) { ulong beginningOfHeader = (ulong)read.BaseStream.Position; ulong compressedSize = ReadUIntVersionAware(read); ulong uncompressedSize = ReadUIntVersionAware(read); mrm = new RDAMemoryResidentHelper(beginningOfHeader - blockInfo.directorySize - compressedSize, uncompressedSize, compressedSize, read.BaseStream, blockInfo, fileHeader.version); } uint dirEntrySize = DirEntry.GetSize(fileHeader.version); if (blockInfo.fileCount * dirEntrySize != blockInfo.decompressedSize) { throw new Exception("Unexpected directory entry size or count"); } ++rdaReadBlocks; UpdateOutput("-- DirEntries:"); ReadDirEntries(numArray2, blockInfo, mrm); } return(blockInfo.nextBlock); }
public static RDAFile FromUnmanaged(FileHeader.Version version, DirEntry dir, BlockInfo block, BinaryReader reader, RDAMemoryResidentHelper mrm) { RDAFile rdaFile = new RDAFile(); rdaFile.FileName = dir.filename; rdaFile.Version = version; if ((block.flags & 4) != 4) { if ((block.flags & 1) == 1) { rdaFile.Flags |= Flag.Compressed; } if ((block.flags & 2) == 2) { rdaFile.Flags |= Flag.Encrypted; } } if ((block.flags & 4) == 4) { rdaFile.Flags |= Flag.MemoryResident; } if ((block.flags & 8) == 8) { rdaFile.Flags |= Flag.Deleted; } rdaFile.Offset = dir.offset; rdaFile.UncompressedSize = dir.filesize; rdaFile.CompressedSize = dir.compressed; rdaFile.TimeStamp = DateTimeExtension.FromTimeStamp(dir.timestamp); rdaFile.BinaryFile = mrm == null ? reader : new BinaryReader(mrm.Data); return(rdaFile); }