////[CodeDescription("Returns a byte[] representing the INFLATE'd representation of compressedData[]")] public static byte[] DeflaterExpandInternal(bool bUseXceed, byte[] compressedData) { if ((compressedData == null) || (compressedData.Length == 0)) { return(new byte[0]); } int offset = 0; if (((compressedData.Length > 2) && (compressedData[0] == 120)) && (compressedData[1] == 0x9c)) { offset = 2; } if (bUseXceed) { return(QuickCompression.Decompress(compressedData, offset, compressedData.Length - offset, CompressionMethod.Deflated, false)); } MemoryStream stream = new MemoryStream(compressedData, offset, compressedData.Length - offset); MemoryStream stream2 = new MemoryStream(compressedData.Length); using (DeflateStream stream3 = new DeflateStream(stream, CompressionMode.Decompress)) { byte[] buffer = new byte[0x8000]; int count = 0; while ((count = stream3.Read(buffer, 0, buffer.Length)) > 0) { stream2.Write(buffer, 0, count); } } return(stream2.ToArray()); }
public static void Main(string[] args) { bool showHelp = false; bool extractUnknowns = true; string filterPattern = null; bool overwriteFiles = false; bool paranoia = false; bool verbose = false; var options = new OptionSet() { { "o|overwrite", "overwrite existing files", v => overwriteFiles = v != null }, { "nu|no-unknowns", "don't extract unknown files", v => extractUnknowns = v == null }, { "f|filter=", "only extract files using pattern", v => filterPattern = v }, { "p|paranoid", "be paranoid (validate hash when uncompressing files)", v => paranoia = v != null }, { "v|verbose", "be verbose", v => verbose = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || extras.Count > 2 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ input_bix [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } string bixPath = Path.GetFullPath(extras[0]); string outputPath = extras.Count > 1 ? Path.GetFullPath(extras[1]) : Path.ChangeExtension(bixPath, null) + "_unpack"; Regex filter = null; if (string.IsNullOrEmpty(filterPattern) == false) { filter = new Regex(filterPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); } var manager = ProjectData.Manager.Load(); if (manager.ActiveProject == null) { Console.WriteLine("Warning: no active project loaded."); } var hashes = manager.LoadListsBigNames(); var bix = new BigFileInventory(); using (var input = File.OpenRead(bixPath)) { bix.Deserialize(input, Endian.Little); } var basePath = Path.GetDirectoryName(bixPath); if (string.IsNullOrEmpty(basePath) == true) { throw new InvalidOperationException(); } var bigPath = Path.Combine(basePath, bix.BigFileName + ".big"); using (var input = File.OpenRead(bigPath)) { long current = 0; long total = bix.Entries.Count; foreach (var entry in bix.Entries) { current++; string name = hashes[entry.Id]; if (name == null) { if (extractUnknowns == false) { continue; } KeyValuePair <string, string> extension; // detect type { var guess = new byte[64]; int read = 0; var offset = (entry.Offset << 2) + (entry.Size.LoadOffset & 0xFFF); if (entry.Size.CompressedSize == 0) { if (entry.Size.UncompressedSize > 0) { input.Seek(offset, SeekOrigin.Begin); read = input.Read(guess, 0, (int)Math.Min(entry.Size.UncompressedSize, guess.Length)); } } else { input.Seek(offset, SeekOrigin.Begin); // todo: don't uncompress everything var uncompressedData = QuickCompression.Decompress(input); read = Math.Min(guess.Length, uncompressedData.Length); Array.Copy(uncompressedData, 0, guess, 0, read); } extension = FileDetection.Detect(guess, Math.Min(guess.Length, read)); } name = entry.Id.ToString("X8"); name = Path.ChangeExtension(name, "." + extension.Value); name = Path.Combine(extension.Key, name); name = Path.Combine("__UNKNOWN", name); } else { name = name.Replace(@"/", @"\"); if (name.StartsWith(@"\") == true) { name = name.Substring(1); } } if (filter != null && filter.IsMatch(name) == false) { continue; } var entryPath = Path.Combine(outputPath, name); if (overwriteFiles == false && File.Exists(entryPath) == true) { continue; } var entryParentPath = Path.GetDirectoryName(entryPath); if (string.IsNullOrEmpty(entryParentPath) == true) { throw new InvalidOperationException(); } Directory.CreateDirectory(entryParentPath); if (verbose == true) { Console.WriteLine("[{0}/{1}] {2}", current, total, name); } using (var output = File.Create(entryPath)) { if (entry.Size.CompressedSize == 0) { if (entry.Size.LoadOffset != 0 || entry.Size.CompressedExtra != 0) { throw new InvalidOperationException(); } if (entry.Size.UncompressedSize > 0) { input.Seek(entry.Offset << 2, SeekOrigin.Begin); output.WriteFromStream(input, entry.Size.UncompressedSize); } } else { var uncompressedSize = entry.Size.CompressedSize + entry.Size.LoadOffset - entry.Size.CompressedExtra; if (uncompressedSize != entry.Size.UncompressedSize) { } if (entry.Size.UncompressedSize > 0) { input.Seek((entry.Offset << 2) + (entry.Size.LoadOffset & 0xFFF), SeekOrigin.Begin); QuickCompression.Decompress(input, output); } } } } } }