public static void Extract(string FileName, Action <int, int> processedEvent, bool is64 = false) { using (FileStream fs = new FileStream(FileName, FileMode.Open)) { BinaryReader br = new BinaryReader(fs); BPKG pkg = new BPKG(fs, is64); for (var i = 0; i < pkg.Files.Length; i++) { BPKG_FTE fte = pkg.Files[i]; // Seek to location of binary file data fs.Position = fte.FileDataOffset; byte[] packedFileData = br.ReadBytes(fte.FileDataSizeStored); byte[] unpackedFileData = Unpack(packedFileData, fte.FileDataSizeStored, fte.FileDataSizeSheared, fte.FileDataSizeUnpacked, fte.IsEncrypted, fte.IsCompressed); string extractedPath = $"{FileName}.files\\{fte.FilePath}"; string extractedDir = new FileInfo(extractedPath).DirectoryName; if (!Directory.Exists(extractedDir)) { ; } Directory.CreateDirectory(extractedDir); if (extractedPath.EndsWith("xml") || extractedPath.EndsWith("x16")) { // decode bxml MemoryStream output = new MemoryStream(); MemoryStream input = new MemoryStream(unpackedFileData); Convert(input, BXML.DetectType(input), output, BXML_TYPE.BXML_PLAIN); using (WinFileIO writer = new WinFileIO(output.ToArray())) { writer.OpenForWriting(extractedPath); writer.WriteBlocks((int)output.Length); } } else { // extract raw File.WriteAllBytes(extractedPath, unpackedFileData); } processedEvent(i + 1, pkg.Files.Length); } } }
public static void Compress(string Folder, Action <int, int> reportProgress, bool is64 = false, int compression = 1) { string[] files = Directory.EnumerateFiles(Folder, "*", SearchOption.AllDirectories).ToArray(); MemoryStream fileTableEntriesStream = new MemoryStream(); MemoryStream fileTableStream = new MemoryStream(); for (var i = 0; i < files.Length; i++) { reportProgress(i + 1, files.Length); string path = files[i].Replace(Folder, "").TrimStart('\\'); byte[] unpackedFileBuffer; using (FileStream fis = new FileStream(files[i], FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 2 << 15)) using (MemoryStream buf = new MemoryStream()) { if (path.EndsWith(".xml") || path.EndsWith(".x16")) { // encode bxml Convert(fis, BXML.DetectType(fis), buf, BXML_TYPE.BXML_BINARY); } else { // compress raw fis.CopyTo(buf); } unpackedFileBuffer = buf.ToArray(); } BPKG_FTE entry = new BPKG_FTE { FilePathLength = path.Length, FilePath = path, IsCompressed = true, IsEncrypted = true, FileDataOffset = (int)fileTableStream.Position, FileDataSizeUnpacked = unpackedFileBuffer.Length }; byte[] packedFileBuffer = Pack(unpackedFileBuffer, out entry.FileDataSizeSheared, out entry.FileDataSizeStored, entry.IsEncrypted, entry.IsCompressed, compression); fileTableStream.Write(packedFileBuffer, 0, packedFileBuffer.Length); entry.WriteTo(fileTableEntriesStream, is64); } MemoryStream packageStream = new MemoryStream(); BinaryWriter package = new BinaryWriter(packageStream); package.Write(new[] { (byte)'U', (byte)'O', (byte)'S', (byte)'E', (byte)'D', (byte)'A', (byte)'L', (byte)'B' }); // Signature package.Write(2); // Version package.Write(new byte[] { 0, 0, 0, 0, 0 }); // Unknown 1 if (is64) { package.Write(fileTableStream.Length); package.Write((long)files.Length); } else { package.Write((int)fileTableStream.Length); package.Write(files.Length); } package.Write(true); // Is compressed package.Write(true); // Is encrypted package.Write(new byte[62]); // Unknown 2 int FTESizePacked; byte[] packedFTEBuffer = Pack(fileTableEntriesStream.ToArray(), out _, out FTESizePacked, true, true, compression); if (is64) { package.Write((long)FTESizePacked); package.Write(fileTableEntriesStream.Length); } else { package.Write(FTESizePacked); package.Write((int)fileTableEntriesStream.Length); } package.Write(packedFTEBuffer); int globalOffset = (int)packageStream.Position + (is64 ? 8 : 4); if (is64) { package.Write((long)globalOffset); } else { package.Write(globalOffset); } // Write the packed file data package.Write(fileTableStream.ToArray()); WinFileIO writer = new WinFileIO(packageStream.ToArray()); writer.OpenForWriting(Folder.Replace(".files", "")); writer.WriteBlocks((int)packageStream.Length); writer.Close(); }