private void WriteChunkContent(BinaryWriter writer, GpkPackage package) { logger.Debug("WriteChunkBlocks"); for (int i = 0; i < package.Header.ChunkHeaders.Count; i++) { GpkCompressedChunkHeader chunk = package.Header.ChunkHeaders[i]; chunk.CompressedOffset = (int)writer.BaseStream.Length; writer.Write(chunk.writableChunkblock.signature); writer.Write(chunk.writableChunkblock.blocksize); writer.Write(chunk.writableChunkblock.compressedSize); writer.Write(chunk.writableChunkblock.uncompressedSize_chunkheader); foreach (var block in chunk.writableChunkblock.chunkBlocks) { writer.Write(block.compressedSize); writer.Write(block.uncompressedDataSize); } foreach (var block in chunk.writableChunkblock.chunkBlocks) { writer.Write(block.compressedData); } chunk.CompressedSize = (int)writer.BaseStream.Length - chunk.CompressedOffset; //????? logger.Debug("Chunk {0}: UncompressedOffset {1}, UncompressedSize {2}, UncompressedEnd {3}, CompressedOffset {4}, CompressedSize {5}, CompressedEnd {6}, Blocks {7}", i, chunk.UncompressedOffset, chunk.UncompressedSize, chunk.UncompressedOffset + chunk.UncompressedSize, chunk.CompressedOffset, chunk.CompressedSize, chunk.CompressedOffset + chunk.CompressedSize, chunk.writableChunkblock.chunkBlocks.Count); } logger.Debug("WriteChunkBlocks done"); }
private byte[] CheckAndDecompress(BinaryReader reader, GpkPackage package) { logger.Trace("checkAndDecompress start"); if (package.Header.ChunkHeaders.Count == 0) { return(null); } byte[] completeFile = new byte[package.UncompressedSize]; //should be the complete file size for (int i = 0; i < package.Header.ChunkHeaders.Count; i++) { GpkCompressedChunkHeader header = package.Header.ChunkHeaders[i]; reader.BaseStream.Seek(header.CompressedOffset, SeekOrigin.Begin); PackageChunkBlock chunk = new PackageChunkBlock(); chunk.signature = reader.ReadInt32(); chunk.blocksize = reader.ReadInt32(); chunk.compressedSize = reader.ReadInt32(); chunk.uncompressedSize_chunkheader = reader.ReadInt32(); int blockCount = Convert.ToInt32(Math.Ceiling(chunk.uncompressedSize_chunkheader / (double)chunk.blocksize)); byte[] uncompressedBytes = new byte[header.UncompressedSize]; chunk.Decompress(uncompressedBytes, blockCount, reader, package.Header.CompressionFlags); Array.ConstrainedCopy(uncompressedBytes, 0, completeFile, header.UncompressedOffset, header.UncompressedSize); logger.Trace("ChunkData {0}: BlockCount {1}, BlockSize {2}, compressedSize {3}, uncompressedSize_chunkheader {4}", i, blockCount, chunk.blocksize, chunk.compressedSize, chunk.uncompressedSize_chunkheader); } if (CoreSettings.Default.Debug) { //dump uncompressed file string path = String.Format("{0}\\decomp_{1}", Directory.GetCurrentDirectory(), package.Filename); //Task.Factory.StartNew(() => File.WriteAllBytes(path, completeFile)); } return(completeFile); }
private void ReadHeader(BinaryReader reader, GpkPackage package) { logger.Trace("Header start"); package.Header.Tag = reader.ReadInt32(); CheckSignature(package.Header.Tag); package.Header.FileVersion = reader.ReadInt16(); package.Header.LicenseVersion = reader.ReadInt16(); package.x64 = package.Header.FileVersion >= 0x381; package.Header.PackageFlags = reader.ReadInt32(); int len = reader.ReadInt32(); package.Header.PackageName = ReadString(reader, len); package.Header.Unk1 = reader.ReadInt16(); package.Header.Unk2 = reader.ReadInt16(); package.Header.NameCount = reader.ReadInt32(); package.Header.NameOffset = reader.ReadInt32(); if (!package.x64) { FixNameCount(package); } package.Header.ExportCount = reader.ReadInt32(); package.Header.ExportOffset = reader.ReadInt32(); package.Header.ImportCount = reader.ReadInt32(); package.Header.ImportOffset = reader.ReadInt32(); package.Header.DependsOffset = reader.ReadInt32(); logger.Debug("NameCount " + package.Header.NameCount); logger.Debug("NameOffset " + package.Header.NameOffset); logger.Debug("ExportCount " + package.Header.ExportCount); logger.Debug("ExportOffset " + package.Header.ExportOffset); logger.Debug("ImportCount " + package.Header.ImportCount); logger.Debug("ImportOffset " + package.Header.ImportOffset); logger.Debug("DependsOffset " + package.Header.DependsOffset); if (package.x64) { package.Header.Unk3 = reader.ReadBytes(16); } stat.totalobjects = package.Header.NameCount + package.Header.ImportCount + package.Header.ExportCount * 3; //Export, Export Linking, ExportData = *3 logger.Info("File Info: NameCount {0}, ImportCount {1}, ExportCount {2}", package.Header.NameCount, package.Header.ImportCount, package.Header.ExportCount); package.Header.FGUID = reader.ReadBytes(16); //logger.Info("FGUID " + package.Header.FGUID); int generation_count = reader.ReadInt32(); for (int i = 0; i < generation_count; i++) { GpkGeneration tmpgen = new GpkGeneration(); tmpgen.ExportCount = reader.ReadInt32(); tmpgen.NameCount = reader.ReadInt32(); tmpgen.NetObjectCount = reader.ReadInt32(); logger.Debug("Generation {0}, ExportCount {1}, NameCount {2}, NetObjectCount {3}", i, tmpgen.ExportCount, tmpgen.NameCount, tmpgen.NetObjectCount); package.Header.Generations.Add(tmpgen); } package.Header.EngineVersion = reader.ReadInt32(); package.Header.CookerVersion = reader.ReadInt32(); package.Header.CompressionFlags = reader.ReadInt32(); int chunkCount = reader.ReadInt32(); for (int i = 0; i < chunkCount; i++) { var chunk = new GpkCompressedChunkHeader(); chunk.UncompressedOffset = reader.ReadInt32(); chunk.UncompressedSize = reader.ReadInt32(); chunk.CompressedOffset = reader.ReadInt32(); chunk.CompressedSize = reader.ReadInt32(); package.Header.ChunkHeaders.Add(chunk); if (i == 0) { package.UncompressedSize = chunk.CompressedOffset + chunk.UncompressedSize; //header + chunk 1, assumption is that chunk 1 lays behind header } else { package.UncompressedSize += chunk.UncompressedSize; } } if (package.Header.EngineVersion == 0xC0FFEE) { logger.Info("Found a old brother ;)"); } logger.Debug("EngineVersion {0}, CookerVersion {1}, compressionFlags {2}, chunkCount {3}", package.Header.EngineVersion, package.Header.CookerVersion, package.Header.CompressionFlags, package.Header.ChunkHeaders.Count); logger.Debug("Compressed: {0}, FullyCompressed {1}, PackageFlags {2:X}", ((GpkPackageFlags)package.Header.PackageFlags & GpkPackageFlags.Compressed), ((GpkPackageFlags)package.Header.PackageFlags & GpkPackageFlags.FullyCompressed), package.Header.PackageFlags ); }
private void ReadHeader(BinaryReader reader, GpkPackage package) { logger.Trace("Header start"); if (reader.BaseStream.Length == 0) { throw new Exception("Not a valid GPK File."); } package.Header.Tag = reader.ReadInt32(); CheckSignature(package.Header.Tag); package.Header.FileVersion = reader.ReadInt16(); package.Header.LicenseVersion = reader.ReadInt16(); package.x64 = package.Header.FileVersion >= 0x381; package.Header.HeaderSize = reader.ReadInt32(); int len = reader.ReadInt32(); package.Header.PackageName = ReadString(reader, len); package.Header.PackageFlags = reader.ReadInt32(); package.Header.NameCount = reader.ReadInt32(); package.Header.NameOffset = reader.ReadInt32(); if (!package.x64) { FixNameCount(package); } package.Header.ExportCount = reader.ReadInt32(); package.Header.ExportOffset = reader.ReadInt32(); package.Header.ImportCount = reader.ReadInt32(); package.Header.ImportOffset = reader.ReadInt32(); package.Header.DependsOffset = reader.ReadInt32(); if (package.x64) { package.Header.HeaderSize = reader.ReadInt32(); //seralizedoffset } if (package.x64) { package.Header.Unk1 = reader.ReadBytes(12); } logger.Debug("NameCount " + package.Header.NameCount); logger.Debug("NameOffset " + package.Header.NameOffset); logger.Debug("ExportCount " + package.Header.ExportCount); logger.Debug("ExportOffset " + package.Header.ExportOffset); logger.Debug("ImportCount " + package.Header.ImportCount); logger.Debug("ImportOffset " + package.Header.ImportOffset); logger.Debug("DependsOffset " + package.Header.DependsOffset); logger.Debug("HeaderSize " + package.Header.HeaderSize); stat.totalobjects = package.Header.NameCount + package.Header.ImportCount + package.Header.ExportCount * 3; //Export, Export Linking, ExportData = *3 logger.Debug("File Info: NameCount {0}, ImportCount {1}, ExportCount {2}", package.Header.NameCount, package.Header.ImportCount, package.Header.ExportCount); package.Header.FGUID = reader.ReadBytes(16); int generation_count = reader.ReadInt32(); package.Header.Generations.Clear(); for (int i = 0; i < generation_count; i++) { GpkGeneration tmpgen = new GpkGeneration(); tmpgen.ExportCount = reader.ReadInt32(); tmpgen.NameCount = reader.ReadInt32(); tmpgen.NetObjectCount = reader.ReadInt32(); logger.Debug("Generation {0}, ExportCount {1}, NameCount {2}, NetObjectCount {3}", i, tmpgen.ExportCount, tmpgen.NameCount, tmpgen.NetObjectCount); package.Header.Generations.Add(tmpgen); } package.Header.EngineVersion = reader.ReadInt32(); package.Header.CookerVersion = reader.ReadInt32(); package.Header.CompressionFlags = reader.ReadInt32(); int chunkCount = reader.ReadInt32(); package.Header.ChunkHeaders.Clear(); for (int i = 0; i < chunkCount; i++) { var chunk = new GpkCompressedChunkHeader(); chunk.UncompressedOffset = reader.ReadInt32(); chunk.UncompressedSize = reader.ReadInt32(); chunk.CompressedOffset = reader.ReadInt32(); chunk.CompressedSize = reader.ReadInt32(); package.Header.ChunkHeaders.Add(chunk); if (i == 0) { package.UncompressedSize = chunk.CompressedOffset + chunk.UncompressedSize; //header + chunk 1, assumption is that chunk 1 lays behind header } else { package.UncompressedSize += chunk.UncompressedSize; } int endOfChunk = chunk.CompressedOffset + chunk.CompressedSize; if (endOfChunk > package.CompressedEndOffset) { package.CompressedEndOffset = endOfChunk; } logger.Debug("Chunk {0}: UncompressedOffset {1}, UncompressedSize {2}, CompressedOffset {3}, CompressedSize {4}, CompressedEnd {5}", i, chunk.UncompressedOffset, chunk.UncompressedSize, chunk.CompressedOffset, chunk.CompressedSize, endOfChunk); } logger.Debug("EngineVersion {0}, CookerVersion {1}, compressionFlags {2}, chunkCount {3}, PkgUncompressedSize {4}", package.Header.EngineVersion, package.Header.CookerVersion, package.Header.CompressionFlags, package.Header.ChunkHeaders.Count, package.UncompressedSize); logger.Debug("Compressed: {0}, FullyCompressed {1}, PackageFlags {2:X}", ((GpkPackageFlags)package.Header.PackageFlags & GpkPackageFlags.Compressed), ((GpkPackageFlags)package.Header.PackageFlags & GpkPackageFlags.FullyCompressed), package.Header.PackageFlags ); int paddingSize; if (chunkCount > 0) { // for compressed packages we can calcualte how much extra data there is paddingSize = package.Header.ChunkHeaders[0].CompressedOffset - (int)(reader.BaseStream.Position); } else { //uncompressed, save everythign to the namelist paddingSize = package.Header.NameOffset - (int)(reader.BaseStream.Position); } if (paddingSize > 0 && paddingSize < 1024) { //sanity check package.Header.HeaderPadding = reader.ReadBytes(paddingSize); } logger.Debug("End of Header at {0}, paddingSize {1}", reader.BaseStream.Position, package.Header.HeaderPadding.Length); }