public FileStructureExtraData(Stream stream, CustomBinaryReader reader, int extra_length) { var end = stream.Position + extra_length; _UnknownID = reader.ReadInt16(); StructureSizeAfterHeader = reader.ReadInt16(); UncompressedFileLength = reader.ReadInt32(); _UnknownD = reader.ReadInt32(); CompressedFileLength = reader.ReadInt32(); _UnknownF = reader.ReadInt32(); var data_offset_ldword = (Int64)reader.ReadUInt32(); var data_offset_hdword = (Int64)reader.ReadUInt32(); DataOffset = data_offset_ldword + (data_offset_hdword << 32); _UnknownG = reader.ReadInt32(); _Timestamp_Maybe_But_Not_Sure = reader.ReadInt32(); // here be demons and lots of padding // make sure we read this to ensure the stream position is correct var padding_length = end - stream.Position; var data = reader.ReadBytes((int)padding_length); if (stream.Position % 0x1000 != 0) { throw new Exception("File Data Section Alignment Error (End Extra Read)"); } FileDataOffset = stream.Position; }
void PopulateDirectory(FileStream stream, CustomBinaryReader reader, CentralDirectoryLocator central_directory_locator) { long central_directory_base_offset = central_directory_locator.ContentDirectoryOffset; stream.Position = central_directory_base_offset; byte[] central_directory_data = reader.ReadBytes(central_directory_locator.ContentDictionarySize); using (MemoryStream central_directory_stream = new MemoryStream(central_directory_data)) using (CustomBinaryReader central_directory_reader = new CustomBinaryReader(central_directory_stream)) { // rebase current offset to 0 because we've copied data to a relative stream long central_directory_current_offset = 0; content_dictionary_count = central_directory_locator.DontentDictionaryCount; for (int i = 0; i < central_directory_locator.DontentDictionaryCount; i++) { var central_directory = ReadPK(central_directory_stream, central_directory_reader, central_directory_current_offset) as CentralDirectory; central_directory_current_offset = central_directory_stream.Position; //TODO async query //var file_structure = ReadPK(stream, reader, central_directory.extra.data_offset) as FileStructure; Files[central_directory.Filename] = new P4KFile(this, central_directory); //var file_data = ReadDataFromFileSection(stream, reader, file_offset.extra.file_data_offset, file_offset.extra.file_data_length); /*if(PopulateDirectoryCallbackFunc != null) * { * PopulateDirectoryCallbackFunc(i, central_directory_locator.content_dictionary_count); * }*/ current_index = i; } } }
public static byte[] ReadDataFromFileSection(FileStream stream, CustomBinaryReader reader, Int64 offset, int size) { stream.Position = offset; if (offset % 0x1000 != 0) { throw new Exception("File data alignment error"); } return(reader.ReadBytes(size)); }
static long FindEndCentralDirectoryOffset(FileStream stream, CustomBinaryReader reader) { // last PK must be within 0x1000 alignment, worst case scenario long length = Math.Min(stream.Length, 0x2000L); stream.Position = stream.Length - length; byte[] data = reader.ReadBytes((int)length); byte[] end_central_directory_magic = { 0x50, 0x4B, 0x05, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; long current_offset = length - end_central_directory_magic.LongLength; bool found = true; for (; current_offset > 0; current_offset--) { found = true; for (long magic_index = 0; magic_index < end_central_directory_magic.LongLength; magic_index++) { if (data[current_offset + magic_index] != end_central_directory_magic[magic_index]) { found = false; break; } } if (found) { break; } } if (!found) { throw new Exception("Couldn't find CentralDirectoryEnd"); } long offset_from_eof = length - current_offset; stream.Position = stream.Length - offset_from_eof; return(stream.Position); }