public void Compress(string Folder, Action <int, int> processedEvent, bool is64 = false, int compression = 9) { string file_path; byte[] buffer_packed; byte[] buffer_unpacked; string[] files = Directory.EnumerateFiles(Folder, "*", SearchOption.AllDirectories).ToArray(); int FileCount = files.Count(); BPKG_FTE FileTableEntry = new BPKG_FTE(); MemoryStream mosTablems = new MemoryStream(); BinaryWriter mosTable = new BinaryWriter(mosTablems); MemoryStream mosFilesms = new MemoryStream(); BinaryWriter mosFiles = new BinaryWriter(mosFilesms); for (int i = 0; i < FileCount; i++) { file_path = files[i].Replace(Folder, "").TrimStart('\\'); FileTableEntry.FilePathLength = file_path.Length; if (is64) { mosTable.Write((long)FileTableEntry.FilePathLength); } else { mosTable.Write(FileTableEntry.FilePathLength); } FileTableEntry.FilePath = file_path; mosTable.Write(Encoding.Unicode.GetBytes(FileTableEntry.FilePath)); FileTableEntry.Unknown_001 = 2; mosTable.Write(FileTableEntry.Unknown_001); FileTableEntry.IsCompressed = true; mosTable.Write(FileTableEntry.IsCompressed); FileTableEntry.IsEncrypted = true; mosTable.Write(FileTableEntry.IsEncrypted); FileTableEntry.Unknown_002 = 0; mosTable.Write(FileTableEntry.Unknown_002); FileStream fis = new FileStream(files[i], FileMode.Open); MemoryStream tmp = new MemoryStream(); //stopWatch.Start(); //Console.Write("\rCompressing Files: {0}/{1}", (i + 1), FileCount); processedEvent((i + 1), FileCount); if (file_path.EndsWith(".xml") || file_path.EndsWith(".x16")) { // encode bxml BXML bxml = new BXML(XOR_KEY); Convert(fis, bxml.DetectType(fis), tmp, BXML_TYPE.BXML_BINARY); } else { // compress raw fis.CopyTo(tmp); } fis.Close(); fis = null; FileTableEntry.FileDataOffset = (int)mosFiles.BaseStream.Position; FileTableEntry.FileDataSizeUnpacked = (int)tmp.Length; if (is64) { mosTable.Write((long)FileTableEntry.FileDataSizeUnpacked); } else { mosTable.Write(FileTableEntry.FileDataSizeUnpacked); } buffer_unpacked = tmp.ToArray(); tmp.Close(); tmp = null; buffer_packed = Pack(buffer_unpacked, FileTableEntry.FileDataSizeUnpacked, out FileTableEntry.FileDataSizeSheared, out FileTableEntry.FileDataSizeStored, FileTableEntry.IsEncrypted, FileTableEntry.IsCompressed, compression); buffer_unpacked = null; mosFiles.Write(buffer_packed); buffer_packed = null; if (is64) { mosTable.Write((long)FileTableEntry.FileDataSizeSheared); } else { mosTable.Write(FileTableEntry.FileDataSizeSheared); } if (is64) { mosTable.Write((long)FileTableEntry.FileDataSizeStored); } else { mosTable.Write(FileTableEntry.FileDataSizeStored); } if (is64) { mosTable.Write((long)FileTableEntry.FileDataOffset); } else { mosTable.Write(FileTableEntry.FileDataOffset); } FileTableEntry.Padding = new byte[60]; mosTable.Write(FileTableEntry.Padding); } Console.Write("\r\nWriting File Entries...\n"); MemoryStream output = new MemoryStream(); BinaryWriter bw = new BinaryWriter(output); byte[] Signature = new byte[8] { (byte)'U', (byte)'O', (byte)'S', (byte)'E', (byte)'D', (byte)'A', (byte)'L', (byte)'B' }; bw.Write(Signature); int Version = 2; bw.Write(Version); byte[] Unknown_001 = new byte[5] { 0, 0, 0, 0, 0 }; bw.Write(Unknown_001); int FileDataSizePacked = (int)mosFiles.BaseStream.Length; if (is64) { bw.Write((long)FileDataSizePacked); bw.Write((long)FileCount); } else { bw.Write(FileDataSizePacked); bw.Write(FileCount); } bool IsCompressed = true; bw.Write(IsCompressed); bool IsEncrypted = true; bw.Write(IsEncrypted); byte[] Unknown_002 = new byte[62]; bw.Write(Unknown_002); int FileTableSizeUnpacked = (int)mosTable.BaseStream.Length; int FileTableSizeSheared = FileTableSizeUnpacked; int FileTableSizePacked = FileTableSizeUnpacked; buffer_unpacked = mosTablems.ToArray(); mosTable.Close(); mosTablems.Close(); mosTable = null; mosTablems = null; buffer_packed = Pack(buffer_unpacked, FileTableSizeUnpacked, out FileTableSizeSheared, out FileTableSizePacked, IsEncrypted, IsCompressed, compression); buffer_unpacked = null; if (is64) { bw.Write((long)FileTableSizePacked); } else { bw.Write(FileTableSizePacked); } if (is64) { bw.Write((long)FileTableSizeUnpacked); } else { bw.Write(FileTableSizeUnpacked); } bw.Write(buffer_packed); buffer_packed = null; int OffsetGlobal = (int)output.Position + (is64 ? 8 : 4); if (is64) { bw.Write((long)OffsetGlobal); } else { bw.Write(OffsetGlobal); } buffer_packed = mosFilesms.ToArray(); mosFiles.Close(); mosFilesms.Close(); mosFiles = null; mosFilesms = null; bw.Write(buffer_packed); buffer_packed = null; File.WriteAllBytes(Folder.Replace(".files", ""), output.ToArray()); bw.Close(); output.Close(); bw = null; output = null; Console.Write("\nDone!"); }
public void Extract(string FileName, Action <int, int> processedEvent, bool is64 = false) { FileStream fs = new FileStream(FileName, FileMode.Open); BinaryReader br = new BinaryReader(fs); string file_path; byte[] buffer_packed; byte[] buffer_unpacked; byte[] Signature = br.ReadBytes(8); uint Version = br.ReadUInt32(); byte[] Unknown_001 = br.ReadBytes(5); int FileDataSizePacked = is64 ? (int)br.ReadInt64() : br.ReadInt32(); int FileCount = is64 ? (int)br.ReadInt64() : br.ReadInt32(); bool IsCompressed = br.ReadByte() == 1; bool IsEncrypted = br.ReadByte() == 1; byte[] Unknown_002 = br.ReadBytes(62); int FileTableSizePacked = is64 ? (int)br.ReadInt64() : br.ReadInt32(); int FileTableSizeUnpacked = is64 ? (int)br.ReadInt64() : br.ReadInt32(); buffer_packed = br.ReadBytes(FileTableSizePacked); int OffsetGlobal = is64 ? (int)br.ReadInt64() : br.ReadInt32(); OffsetGlobal = (int)br.BaseStream.Position; // don't trust value, read current stream location. byte[] FileTableUnpacked = Unpack(buffer_packed, FileTableSizePacked, FileTableSizePacked, FileTableSizeUnpacked, IsEncrypted, IsCompressed); buffer_packed = null; MemoryStream ms = new MemoryStream(FileTableUnpacked); BinaryReader br2 = new BinaryReader(ms); Console.Write("\rReading File Entries...\n"); for (int i = 0; i < FileCount; i++) { BPKG_FTE FileTableEntry = new BPKG_FTE(); FileTableEntry.FilePathLength = is64 ? (int)br2.ReadInt64() : br2.ReadInt32(); FileTableEntry.FilePath = Encoding.Unicode.GetString(br2.ReadBytes(FileTableEntry.FilePathLength * 2)); FileTableEntry.Unknown_001 = br2.ReadByte(); FileTableEntry.IsCompressed = br2.ReadByte() == 1; FileTableEntry.IsEncrypted = br2.ReadByte() == 1; FileTableEntry.Unknown_002 = br2.ReadByte(); FileTableEntry.FileDataSizeUnpacked = is64 ? (int)br2.ReadInt64() : br2.ReadInt32(); FileTableEntry.FileDataSizeSheared = is64 ? (int)br2.ReadInt64() : br2.ReadInt32(); FileTableEntry.FileDataSizeStored = is64 ? (int)br2.ReadInt64() : br2.ReadInt32(); FileTableEntry.FileDataOffset = (is64 ? (int)br2.ReadInt64() : br2.ReadInt32()) + OffsetGlobal; FileTableEntry.Padding = br2.ReadBytes(60); file_path = string.Format("{0}.files\\{1}", FileName, FileTableEntry.FilePath); if (!Directory.Exists((new FileInfo(file_path)).DirectoryName)) { Directory.CreateDirectory((new FileInfo(file_path)).DirectoryName); } // Console.Write("\rExtracting Files: {0}/{1}", (i + 1), FileCount); br.BaseStream.Position = FileTableEntry.FileDataOffset; buffer_packed = br.ReadBytes(FileTableEntry.FileDataSizeStored); buffer_unpacked = Unpack(buffer_packed, FileTableEntry.FileDataSizeStored, FileTableEntry.FileDataSizeSheared, FileTableEntry.FileDataSizeUnpacked, FileTableEntry.IsEncrypted, FileTableEntry.IsCompressed); buffer_packed = null; FileTableEntry = null; if (file_path.EndsWith("xml") || file_path.EndsWith("x16")) { // decode bxml MemoryStream temp = new MemoryStream(); MemoryStream temp2 = new MemoryStream(buffer_unpacked); BXML bns_xml = new BXML(XOR_KEY); Convert(temp2, bns_xml.DetectType(temp2), temp, BXML_TYPE.BXML_PLAIN); temp2.Close(); File.WriteAllBytes(file_path, temp.ToArray()); temp.Close(); buffer_unpacked = null; } else { // extract raw File.WriteAllBytes(file_path, buffer_unpacked); buffer_unpacked = null; } processedEvent((i + 1), FileCount); } br2.Close(); ms.Close(); br2 = null; ms = null; br.Close(); fs.Close(); br = null; fs = null; Console.Write("\nDone!"); }