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 long FileDataOffset; // (relative) offset public BPKG_FTE(Stream stream, BPKG pkg) { Pkg = pkg; bool is64 = pkg.Is64; BinaryReader fte = new BinaryReader(stream); FilePathLength = is64 ? (int)fte.ReadInt64() : fte.ReadInt32(); FilePath = Encoding.Unicode.GetString(fte.ReadBytes(FilePathLength * 2)); fte.ReadByte(); // Unknown IsCompressed = fte.ReadBoolean(); IsEncrypted = fte.ReadBoolean(); fte.ReadByte(); // Unknown FileDataSizeUnpacked = is64 ? (int)fte.ReadInt64() : fte.ReadInt32(); FileDataSizeSheared = is64 ? (int)fte.ReadInt64() : fte.ReadInt32(); FileDataSizeStored = is64 ? (int)fte.ReadInt64() : fte.ReadInt32(); FileDataOffset = (is64 ? fte.ReadInt64() : fte.ReadInt32()) + pkg.BaseOffset; fte.ReadBytes(60); // Padding }