private bool TestBundleForIDStrings(string bundle_id) { string bundle_id_path = Path.Combine(StaticStorage.settings.AssetsFolder, bundle_id); if (!File.Exists(Path.Combine(StaticStorage.settings.AssetsFolder, bundle_id + ".bundle")) || !File.Exists(Path.Combine(StaticStorage.settings.AssetsFolder, bundle_id + "_h.bundle"))) return false; BundleHeader bundle = new BundleHeader(); if (!bundle.Load(bundle_id_path)) { StaticStorage.log.writeLine(string.Format("[Update error] Failed to parse bundle header. ({0})", bundle_id)); return false; } string bundle_file = bundle_id_path + ".bundle"; if (!File.Exists(bundle_file)) { StaticStorage.log.writeLine(String.Format("[Update error] Bundle file does not exist. ({0})", bundle_file)); return false; } foreach (BundleEntry be in bundle.Entries) { NameEntry ne = StaticStorage.Index.Id2Name(be.Id); if (ne != null && ne.Path == 0x9234DD22C60D71B8 && ne.Extension == 0x9234DD22C60D71B8) { return true; } } return false; }
public bool RetrieveHashlist() { HashSet<string> new_paths = new HashSet<string>(); HashSet<string> new_exts = new HashSet<string>(); HashSet<string> new_other = new HashSet<string>(); StringBuilder sb = new StringBuilder(); string[] known_bundles = { "all_7", "all_0", "all_14" }; //Payday: The Heist, Payday 2 Demo, Payday 2 string[] idstring_data; foreach (string bundle_id in known_bundles) { string bundle_id_path = Path.Combine(StaticStorage.settings.AssetsFolder, bundle_id); if (!File.Exists(Path.Combine(StaticStorage.settings.AssetsFolder, bundle_id + ".bundle")) || !File.Exists(Path.Combine(StaticStorage.settings.AssetsFolder, bundle_id + "_h.bundle"))) continue; BundleHeader bundle = new BundleHeader(); if (!bundle.Load(bundle_id_path)) { StaticStorage.log.writeLine(string.Format("[Update error] Failed to parse bundle header. ({0})", bundle_id)); return false; } string bundle_file = bundle_id_path + ".bundle"; if (!File.Exists(bundle_file)) { StaticStorage.log.writeLine(string.Format("[Update error] Bundle file does not exist. ({0})", bundle_file)); return false; } using (FileStream fs = new FileStream(bundle_file, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs)) { byte[] data; foreach (BundleEntry be in bundle.Entries) { NameEntry ne = StaticStorage.Index.Id2Name(be.Id); if (ne == null) continue; if (ne.Path == 0x9234DD22C60D71B8 && ne.Extension == 0x9234DD22C60D71B8) { fs.Position = be.Address; if (be.Length == -1) data = br.ReadBytes((int)(fs.Length - fs.Position)); else data = br.ReadBytes((int)be.Length); foreach (byte read in data) sb.Append((char)read); idstring_data = sb.ToString().Split('\0'); sb.Clear(); foreach (string idstring in idstring_data) { if (idstring.Contains("/")) new_paths.Add(idstring); else if (!idstring.Contains("/") && !idstring.Contains(".") && !idstring.Contains(":") && !idstring.Contains("\\")) new_exts.Add(idstring); else new_other.Add(idstring); } new_paths.Add("idstring_lookup"); new_paths.Add("existing_banks"); StaticStorage.Known_Index.Clear(); StaticStorage.Known_Index.Load(ref new_paths, ref new_exts, ref new_other); StaticStorage.Known_Index.GenerateHashList(HashlistFile); new_paths.Clear(); new_exts.Clear(); return true; } } br.Close(); } fs.Close(); } } return false; }
/// <summary> /// The retrieve file from bundle. /// </summary> /// <param name="bundleId"> /// The bundle id. /// </param> /// <param name="data"> /// The file data. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> private bool RetrieveFile(string bundleId, out MemoryStream data) { data = new MemoryStream(); var inHeader = new BundleHeader(); if (!inHeader.Load(Path.Combine(this._assetFolder, "asset_backups", bundleId))) return false; var inBundle = new FileStream(Path.Combine(this._assetFolder, bundleId + ".bundle"), FileMode.Open, FileAccess.Read); var inBundleBinary = new BinaryReader(inBundle); int currentEntry = 1; int entryCount = inHeader.Entries.Count; foreach (BundleEntry entry in inHeader.Entries) { if (currentEntry % 100 == 0) { this.SetBundleProgress( string.Format("Reading entry {0}/{1}", currentEntry, entryCount), (int)((currentEntry / (float)entryCount) * 100.0f)); } if (this._rewriteItems.ContainsKey(entry.Id)) { inBundle.Seek(entry.Address, SeekOrigin.Begin); long readLength = entry.Length == -1 ? inBundle.Length - inBundle.Position : entry.Length; data.Write(inBundleBinary.ReadBytes((int)readLength), 0, (int)readLength); break; } currentEntry += 1; } inBundleBinary.Close(); inBundle.Close(); this.SetBundleProgress("Done", 100); return true; }
public void StartBundle() { if (!String.IsNullOrWhiteSpace(StaticStorage.settings.ListLogFile)) { listlog = StaticStorage.settings.ListLogFile; } else { listlog = "./listlog.log"; } string extract_folder; if (String.IsNullOrWhiteSpace(StaticStorage.settings.CustomExtractPath)) { if (!Directory.Exists(Path.Combine(StaticStorage.settings.AssetsFolder, "extract"))) { Directory.CreateDirectory(Path.Combine(StaticStorage.settings.AssetsFolder, "extract")); } extract_folder = Path.Combine(StaticStorage.settings.AssetsFolder, "extract"); } else { extract_folder = StaticStorage.settings.CustomExtractPath; } TextWriteLine("Loading blb index..."); if (!TestAssetsFolder()) { //this.StartExtracting.Enabled = true; MessageBox.Show("Failed to parse bundle_db.blb. Are you sure the path is valid and the file is not corrupt?"); TextWriteLine("Failed to parse bundle_db.blb. Are you sure the path is valid and the file is not corrupt?"); //Finished = true; return; } //You don't need to clear them, they're loaded once and done. //KnownIndex.Clear(); //NameIndex.Clear(); TextWriteLine("Paths and Extensions Updated Successfully"); listlogger = new StreamWriter(listlog, true); if (extract_one && extract_id.Length > 0) { bundle = new BundleHeader(); if (!bundle.Load(Path.Combine(StaticStorage.settings.AssetsFolder, extract_id))) { MessageBox.Show("Failed to parse bundle header."); TextWriteLine("Failed to parse bundle header."); //Finished = true; return; } if (StaticStorage.settings.List || StaticStorage.settings.ListData) { current_bundle = 0; total_bundle = 1; progress = 0; ListBundle(Path.Combine(StaticStorage.settings.AssetsFolder, extract_id)); current_bundle = 1; total_bundle = 1; progress = 100; //Finished = true; } else { current_bundle = 0; total_bundle = 1; progress = 0; TextWriteLine("Extract bundle: " + extract_id); ExtractBundle(extract_id); current_bundle = 1; total_bundle = 1; progress = 100; //Finished = true; } } else { int TotalBundles = 0; int CurrentBundle = 0; //float Division = 100.0f; TotalBundles = Directory.EnumerateFiles(StaticStorage.settings.AssetsFolder, "*_h.bundle").Count(); current_bundle = 0; total_bundle = (uint)TotalBundles; progress = (uint)(((float)CurrentBundle / TotalBundles) * 100); foreach (string file in Directory.EnumerateFiles(StaticStorage.settings.AssetsFolder, "*_h.bundle")) { string bundle_id = file.Replace("_h.bundle", ""); bundle_id = Path.GetFileName(bundle_id); string bundle_path = file.Replace("_h.bundle", ""); //Console.WriteLine(bundle_id); bundle = new BundleHeader(); TextWriteLine("Loading bundle header " + bundle_id); if (!bundle.Load(bundle_path)) { MessageBox.Show("Failed to parse bundle header."); TextWriteLine("Failed to parse bundle header."); //TextWriteLine("Done"); return; } if (StaticStorage.settings.List || StaticStorage.settings.ListData) { //TextWriteLine("List Only"); ListBundle(bundle_path); CurrentBundle++; current_bundle = (uint)CurrentBundle; total_bundle = (uint)TotalBundles; progress = (uint)(((float)CurrentBundle / TotalBundles) * 100); } else { TextWriteLine("Extracting bundle: " + bundle_id); ExtractBundle(bundle_id); //TextWriteLine("Extraction Done"); CurrentBundle++; current_bundle = (uint)CurrentBundle; total_bundle = (uint)TotalBundles; progress = (uint)(((float)CurrentBundle / TotalBundles) * 100); } } } //DialogResult dialogResult = MessageBox.Show("Finished", "Finished", MessageBoxButtons.OK); //if (dialogResult == DialogResult.OK) //{ //Finished = true; //} listlogger.Close(); listlogger = null; }
/// <summary> /// The patch bundle. /// </summary> /// <param name="bundleId"> /// The bundle id. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> private bool PatchBundle(string bundleId) { System.Diagnostics.Stopwatch st_total = new System.Diagnostics.Stopwatch(); System.Diagnostics.Stopwatch st_entry = new System.Diagnostics.Stopwatch(); System.Diagnostics.Stopwatch st_writing = new System.Diagnostics.Stopwatch(); bool isAll = bundleId.Contains("all_"); var inHeader = new BundleHeader(); if (!inHeader.Load(Path.Combine(this._assetFolder, bundleId))) { return false; } var outHeader = new BundleHeader(); outHeader.Footer = inHeader.Footer; outHeader.Header = inHeader.Header; outHeader.HasLengthField = inHeader.HasLengthField; var inBundle = new FileStream(Path.Combine(this._assetFolder, bundleId + ".bundle"), FileMode.Open, FileAccess.Read); var outBundle = new FileStream( Path.Combine(this._assetFolder, bundleId + ".bundle.new"), FileMode.Create, FileAccess.ReadWrite); //BufferedStream bsin = new BufferedStream(inBundle); //BufferedStream bsout = new BufferedStream(outBundle); var br = new BinaryReader(inBundle); var bw = new BinaryWriter(outBundle); long inFileLength = inBundle.Length; int currentAddress = 0; int currentEntry = 1; int entryCount = inHeader.Entries.Count; //stream buffers //int bufferSize = 4096; //1024^2 byte[] buffer = new byte[this.bufferSize]; if (isAll) inHeader.SortEntriesAddress(); foreach (BundleEntry entry in inHeader.Entries) { st_total.Restart(); st_entry.Restart(); if (currentEntry % 100 == 0) { this.SetBundleProgress( string.Format("Writing entry {0}/{1}", currentEntry, entryCount), (int)((currentEntry / (float)entryCount) * 100.0f)); } var newEntry = new BundleEntry(); newEntry.Id = entry.Id; newEntry.Length = entry.Length; newEntry.Address = (uint)currentAddress; bool replaced = false; bool firstpatched = false; bool restore = false; if (this._rewriteItems.ContainsKey(entry.Id)) { if (this._rewriteItems[entry.Id].toRestore) restore = true; MemoryStream newData = new MemoryStream(); if (restore) { if (this._backupType == 0) { var inRestoreBundle = new FileStream(Path.Combine(this._assetFolder, "asset_backups", bundleId + ".bundle"), FileMode.Open, FileAccess.Read); var inRestoreHeader = new BundleHeader(); if (!inRestoreHeader.Load(Path.Combine(this._assetFolder, "asset_backups", bundleId))) return false; foreach (BundleEntry restoreEntry in inRestoreHeader.Entries) { if (restoreEntry.Id == entry.Id) { newEntry.Length = this.RestoreEntry(restoreEntry, 0, inRestoreBundle, newData); replaced = true; break; } } } else { NameEntry ne = StaticStorage.Index.Id2Name(entry.Id); if (File.Exists(Path.Combine(this._assetFolder, "asset_backups", ne.ToString()))) { using (FileStream importFS = new FileStream(Path.Combine(this._assetFolder, "asset_backups", ne.ToString()), FileMode.Open, FileAccess.Read)) { using (BinaryReader importBR = new BinaryReader(importFS)) { newEntry.Length = (int)importFS.Length; newData.Seek(0, SeekOrigin.Begin); newData.Write(importBR.ReadBytes((int)importFS.Length), 0, (int)importFS.Length); replaced = true; } } } else { return false; } } } if (this._rewriteItems[entry.Id].priorityBundleRewriteItem != new BundleRewriteItem()) { newEntry.Length = this.WriteZipEntry(entry, inBundle, newData, this._rewriteItems[entry.Id].priorityBundleRewriteItem); firstpatched = true; replaced = true; } foreach (var rewriteItem in this._rewriteItems[entry.Id].BundleRewriteItem_queue) { if (rewriteItem.toRemove) continue; if (!firstpatched) { newEntry.Length = this.WriteZipEntry(entry, inBundle, newData, rewriteItem); firstpatched = true; } else { newEntry.Length = this.WriteZipEntry(newEntry, newData, newData, rewriteItem); } replaced = true; } if (newData.Length > 0L) { //buffer = new byte[megabyte]; newData.Position = 0L; int bytesRead = newData.Read(buffer, 0, this.bufferSize); while (bytesRead > 0) { outBundle.Write(buffer, 0, bytesRead); bytesRead = newData.Read(buffer, 0, this.bufferSize); } //outBundle.Seek(currentAddress, SeekOrigin.Begin); //newData.CopyTo(outBundle); } } st_entry.Stop(); st_writing.Restart(); if (replaced) currentAddress += newEntry.Length; outHeader.Entries.Add(newEntry); if (!replaced) { /* inBundle.Seek(entry.Address, SeekOrigin.Begin); long entryLength = entry.Length == -1 ? inBundle.Length - inBundle.Position : entry.Length; var br = new BinaryReader(inBundle); var bw = new BinaryWriter(outBundle); bw.Write(br.ReadBytes((int)entryLength)); currentAddress += (int)entryLength; */ //inBundle.Seek(entry.Address, SeekOrigin.Begin); inBundle.Seek((long)entry.Address, SeekOrigin.Begin); long entryLength = (entry.Length == -1 ? inFileLength - (long)entry.Address : (long)entry.Length); int remaining = (int)entryLength; int totalread = 0; //buffer = new byte[megabyte]; //bw.Write(br.ReadBytes((int)entryLength)); int bytesRead = inBundle.Read(buffer, 0, (((remaining - totalread) / this.bufferSize) > 0 ? this.bufferSize : remaining - totalread)); totalread += bytesRead; while (bytesRead > 0 && totalread <= remaining) { bw.Write(buffer, 0, bytesRead); bytesRead = inBundle.Read(buffer, 0, (((remaining - totalread) / this.bufferSize) > 0 ? this.bufferSize : remaining - totalread)); totalread += bytesRead; } //bw.Flush(); currentAddress += (int)entryLength; } currentEntry += 1; CurrentEntryCount++; SpeedEntryCount++; st_writing.Stop(); st_total.Stop(); if (st_total.ElapsedMilliseconds > 200) Console.WriteLine(bundleId + " - T: " + st_total.ElapsedMilliseconds + " ms. [entry: " + st_entry.ElapsedMilliseconds + " ms. writing: " + st_writing.ElapsedMilliseconds + " ms.] with " + newEntry.Length + " for replaced " + replaced); } bw.Flush(); inBundle.Close(); outBundle.Close(); if (isAll) outHeader.SortEntriesId(); var outHeaderStream = new FileStream( Path.Combine(this._assetFolder, bundleId + "_h.bundle"), FileMode.OpenOrCreate, FileAccess.Write); var outHeaderBr = new BinaryWriter(outHeaderStream); outHeader.WriteHeader(outHeaderBr); foreach (BundleEntry entry in outHeader.Entries) { entry.WriteEntry(outHeaderBr, outHeader.HasLengthField); } outHeader.WriteFooter(outHeaderBr); outHeaderBr.Close(); outHeaderStream.Close(); File.Delete(Path.Combine(this._assetFolder, bundleId + ".bundle")); File.Move(Path.Combine(this._assetFolder, bundleId + ".bundle.new"), Path.Combine(this._assetFolder, bundleId + ".bundle")); this.SetBundleProgress("Done", 100); return true; }
/// <summary> /// The patch bundle restore. /// </summary> /// <param name="bundleId"> /// The bundle id. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> private bool PatchBundleRestore(BundleMod mod, string bundleId, bool method) { if (method) { if (!File.Exists(Path.Combine(this._assetFolder, bundleId + ".bundle")) || !File.Exists(Path.Combine(this._assetFolder, bundleId + "_h.bundle")) || !File.Exists(Path.Combine(this._assetFolder, "asset_backups", bundleId + ".bundle")) || !File.Exists(Path.Combine(this._assetFolder, "asset_backups", bundleId + "_h.bundle"))) return false; File.Delete(Path.Combine(this._assetFolder, bundleId + ".bundle")); File.Delete(Path.Combine(this._assetFolder, bundleId + "_h.bundle")); File.Copy(Path.Combine(this._assetFolder, "asset_backups", bundleId + ".bundle"), Path.Combine(this._assetFolder, bundleId + ".bundle"), true); File.Copy(Path.Combine(this._assetFolder, "asset_backups", bundleId + "_h.bundle"), Path.Combine(this._assetFolder, bundleId + "_h.bundle"), true); this.SetBundleProgress("Done", 100); return true; } var inHeader = new BundleHeader(); var inRestoreHeader = new BundleHeader(); Dictionary<uint, BundleEntry> inRestoreDictionary = new Dictionary<uint, BundleEntry>(); if (!inHeader.Load(Path.Combine(this._assetFolder, bundleId))) { return false; } if (!inRestoreHeader.Load(Path.Combine(this._assetFolder, "asset_backups", bundleId))) return false; foreach (BundleEntry entry in inRestoreHeader.Entries) { if (!inRestoreDictionary.ContainsKey(entry.Id)) inRestoreDictionary.Add(entry.Id, entry); } var outHeader = new BundleHeader(); outHeader.Footer = inHeader.Footer; outHeader.Header = inHeader.Header; outHeader.HasLengthField = inHeader.HasLengthField; var inRestoreBundle = new FileStream(Path.Combine(this._assetFolder, "asset_backups", bundleId + ".bundle"), FileMode.Open, FileAccess.Read); var inBundle = new FileStream(Path.Combine(this._assetFolder, bundleId + ".bundle"), FileMode.Open, FileAccess.Read); var outBundle = new FileStream( Path.Combine(this._assetFolder, bundleId + ".bundle.new"), FileMode.OpenOrCreate, FileAccess.ReadWrite); int currentAddress = 0; int currentEntry = 1; int entryCount = inHeader.Entries.Count; foreach (BundleEntry entry in inHeader.Entries) { if (currentEntry % 100 == 0) { this.SetBundleProgress( string.Format("Writing entry {0}/{1}", currentEntry, entryCount), (int)((currentEntry / (float)entryCount) * 100.0f)); } var newEntry = new BundleEntry(); newEntry.Id = entry.Id; newEntry.Length = entry.Length; newEntry.Address = (uint)currentAddress; bool replaced = false; foreach (int length in from rewriteItem in mod.ItemQueue where rewriteItem.Ids.Contains(entry.Id) select this.RestoreEntry(inRestoreDictionary[entry.Id], (uint)currentAddress, inRestoreBundle, outBundle)) { currentAddress += length; newEntry.Length = length; replaced = true; break; } outHeader.Entries.Add(newEntry); if (!replaced) { inBundle.Seek(entry.Address, SeekOrigin.Begin); long entryLength = entry.Length == -1 ? inBundle.Length - inBundle.Position : entry.Length; var br = new BinaryReader(inBundle); var bw = new BinaryWriter(outBundle); bw.Write(br.ReadBytes((int)entryLength)); currentAddress += (int)entryLength; } currentEntry += 1; } inBundle.Close(); inRestoreBundle.Close(); outBundle.Close(); var outHeaderStream = new FileStream( Path.Combine(this._assetFolder, bundleId + "_h.bundle"), FileMode.OpenOrCreate, FileAccess.Write); var outHeaderBr = new BinaryWriter(outHeaderStream); outHeader.WriteHeader(outHeaderBr); foreach (BundleEntry entry in outHeader.Entries) { entry.WriteEntry(outHeaderBr, outHeader.HasLengthField); } outHeader.WriteFooter(outHeaderBr); outHeaderBr.Close(); outHeaderStream.Close(); File.Delete(Path.Combine(this._assetFolder, bundleId + ".bundle")); File.Move(Path.Combine(this._assetFolder, bundleId + ".bundle.new"), Path.Combine(this._assetFolder, bundleId + ".bundle")); this.SetBundleProgress("Done", 100); return true; }
/// <summary> /// The locate bundles to rewrite. /// </summary> /// <param name="success"> /// The success. /// </param> /// <returns> /// The <see cref="HashSet"/>. /// </returns> private HashSet<string> LocateBundlesToRewrite(out bool success) { success = false; var bundles = new HashSet<string>(); this.SetTotalProgress("Determining Bundles To Modify", -1); List<string> files = Directory.EnumerateFiles(this._assetFolder, "*_h.bundle").ToList(); for (int i = 0; i < files.Count; i++ ) { string file = files[i]; this.SetBundleProgress( string.Format("Reviewing Bundle {0}/{1}", i, files.Count), (int)((i / (float)files.Count) * 100.0f)); string bundlePath = file.Replace("_h.bundle", string.Empty); var header = new BundleHeader(); if (!header.Load(bundlePath)) { this.Error = "Failed to parse bundle header: " + bundlePath; return bundles; } foreach (BundleEntry entry in header.Entries) { bool found = false; if (this._mod.ItemQueue.Any(rewriteItem => rewriteItem.Ids.Contains(entry.Id))) { bundles.Add(Path.GetFileNameWithoutExtension(bundlePath)); this.TotalEntryCount += header.Entries.Count; found = true; } if (found) { break; } } } this.SetBundleProgress("Done", 100); success = true; return bundles; }
private void CheckBundle(string bundleId) { var bundleSize = new FileInfo(bundleId + ".bundle").Length; //repair can be attempted, no guarantees //repair.. it's f****d. var bundle = new BundleHeader(); if (!bundle.Load(bundleId)) { throw new Exception("Corrupted BundleHeader"); } //repair can be attempted, no guarantees //repair would consist of checking against a backup, given it exists foreach (BundleEntry be in bundle.Entries) { NameEntry ne = StaticStorage.Index.Id2Name(be.Id); if (ne == null) { throw new Exception("Invalid NameEntry"); } if (be.Address + be.Length > bundleSize) { throw new Exception("Attempt to read past end of bundle"); } } //can be repaired //repair would consist of resorting the entries, given they are all valid if (Path.GetFileNameWithoutExtension(bundleId).StartsWith("all_")) { //it's an all_ bundle... BundleHeader items should be sorted by Address (length 0 first) uint prevID = 0; foreach (BundleEntry entry in bundle.Entries) { if (entry.Id < prevID) throw new Exception("Invalid BundleEntry not sorted by ID"); prevID = entry.Id; } } else { //it's a regular bundle... BundleHeader items should be sorted by ID uint prevAddress = 0; foreach (BundleEntry entry in bundle.Entries) { if (entry.Address < prevAddress) throw new Exception("Invalid BundleEntry not sorted by Address"); prevAddress = entry.Address; } } }
/// <summary> /// The backup bundle entry. /// </summary> /// <param name="bundlePath"> /// The bundle path. /// </param> private void BackupEntries(BundleMod mod, string bundlePath) { string backupFolder = Path.Combine(this._assetFolder, "asset_backups") + "\\"; Directory.CreateDirectory(backupFolder); var header = new BundleHeader(); if (!header.Load(bundlePath)) { this.Error = "Failed to parse bundle header: " + bundlePath; } var bundleFS = new FileStream(bundlePath + ".bundle", FileMode.Open, FileAccess.Read); var bundleBR = new BinaryReader(bundleFS); foreach (BundleEntry entry in header.Entries) { BundleRewriteItem rewriteEntryItem; BundleRewriteItem backupRewriteItem = new BundleRewriteItem(); if (mod.ItemQueue.Any(rewriteItem => rewriteItem.Ids.Contains(entry.Id))) { NameEntry ne = StaticStorage.Index.Id2Name(entry.Id); rewriteEntryItem = mod.ItemQueue.First(rewriteItem => rewriteItem.Ids.Contains(entry.Id)); if (!File.Exists(backupFolder + ne.ToString())) { using (FileStream exportFS = new FileStream(backupFolder + ne.ToString(), FileMode.CreateNew, FileAccess.Write)) { using (BinaryWriter exportBW = new BinaryWriter(exportFS)) { long entryLength = entry.Length == -1 ? bundleFS.Length - bundleFS.Position : entry.Length; bundleFS.Seek(entry.Address, SeekOrigin.Begin); exportBW.Write(bundleBR.ReadBytes((int)entryLength)); } } } } } bundleBR.Close(); bundleFS.Close(); }
/// <summary> /// The retrieve file from bundle. /// </summary> /// <param name="bundleId"> /// The bundle id. /// </param> /// <param name="data"> /// The file data. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> public bool RetrieveFile(BundleRewriteItem item, out MemoryStream data) { data = new MemoryStream(); if (item.Ids == null) { item.Ids = StaticStorage.Index.Entry2Id( item.BundlePath, item.BundleExtension, item.BundleLanguage, item.IsLanguageSpecific); } string bundleId = ""; foreach (string file in Directory.EnumerateFiles(this._assetFolder, "*_h.bundle")) { string bundlePath = file.Replace("_h.bundle", string.Empty); var header = new BundleHeader(); if (!header.Load(bundlePath)) { this.Error = "Failed to parse bundle header: " + bundlePath; return false; } foreach (BundleEntry entry in header.Entries) { if (item.Ids.Contains(entry.Id) && entry.Length > 0) { bundleId = Path.GetFileNameWithoutExtension(bundlePath); var inBundle = new FileStream(Path.Combine(this._assetFolder, bundleId + ".bundle"), FileMode.Open, FileAccess.Read); var inBundleBinary = new BinaryReader(inBundle); inBundle.Seek(entry.Address, SeekOrigin.Begin); long readLength = entry.Length == -1 ? inBundle.Length - inBundle.Position : entry.Length; data.Write(inBundleBinary.ReadBytes((int)readLength), 0, (int)readLength); data.Position = 0L; inBundleBinary.Close(); inBundle.Close(); return true; } } } return false; }
/// <summary> /// The locate bundles. /// </summary> /// <param name="success"> /// The success. /// </param> /// <returns> /// The <see cref="HashSet"/>. /// </returns> public Dictionary<string, List<uint>> LocateBundles(out bool success, List<uint> ids) { success = false; var bundles = new Dictionary<string, List<uint>>(); var files = Directory.EnumerateFiles(this._assetFolder, "*_h.bundle").ToList(); for (int i = 0; i < files.Count; i++ ) { string file = files[i]; this.SetBundleProgress( string.Format("Reviewing Bundle {0}/{1}", i, files.Count), (int)((i / (float)files.Count) * 100.0f)); List<uint> enties = new List<uint>(); string bundlePath = file.Replace("_h.bundle", string.Empty); var header = new BundleHeader(); if (!header.Load(bundlePath)) { this.Error = "Failed to parse bundle header: " + bundlePath; return bundles; } foreach (BundleEntry entry in header.Entries) { if (ids.Contains(entry.Id)) { enties.Add(entry.Id); } } if (enties.Count > 0) bundles.Add(Path.GetFileNameWithoutExtension(bundlePath), enties); } this.SetBundleProgress("Done", 100); success = true; return bundles; }