public static void Main(string[] args) { bool convertTextures = false; bool showHelp = false; var options = new OptionSet() { { "convert-textures", "convert textures", v => convertTextures = 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_[sb|toc] [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } string bundlePath, superbundlePath, layoutPath, outputBasePath; if (Path.GetExtension(extras[0]) == ".sb") { superbundlePath = Path.GetFullPath(extras[0]); bundlePath = Path.ChangeExtension(superbundlePath, ".toc"); layoutPath = Helpers.FindLayoutPath(superbundlePath); outputBasePath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(superbundlePath, null) + "_unpack"; } else { bundlePath = Path.GetFullPath(extras[0]); superbundlePath = Path.ChangeExtension(bundlePath, ".sb"); layoutPath = Helpers.FindLayoutPath(bundlePath); outputBasePath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(bundlePath, null) + "_unpack"; } if (string.IsNullOrEmpty(layoutPath) == true) { Console.WriteLine("Could not find layout file."); return; } var dataPath = Path.GetDirectoryName(layoutPath) ?? ""; var bundle = TableOfContentsFile.Read(bundlePath); var superbundle = SuperbundleFile.Read(superbundlePath); var extensionsById = ResourceTypes.GetExtensions(); if (bundle.IsCas == false) { throw new NotImplementedException(); } else { var commonBundlePaths = Directory.GetFiles(dataPath, "chunks*.toc", SearchOption.AllDirectories); var commonBundles = new List <TableOfContentsFile>(); foreach (var commonBundlePath in commonBundlePaths) { var commonBundle = TableOfContentsFile.Read(commonBundlePath); commonBundles.Add(commonBundle); } var superbundleName = Path.ChangeExtension(superbundlePath.Substring(dataPath.Length + 1), null); superbundleName = Helpers.FilterName(superbundleName).ToLowerInvariant(); var layout = LayoutFile.Read(layoutPath); var installChunks = GetSuperbundleInstallChunks(layout, superbundleName); var catalogLookup = new CatalogLookup(dataPath); foreach (var installChunk in installChunks) { if (catalogLookup.Add(installChunk.InstallBundle) == false) { Console.WriteLine("Failed to load catalog for '{0}'.", installChunk.Name); } } foreach (var bundleInfo in superbundle.Bundles) { if (bundleInfo.Resources == null) { continue; } foreach (var resourceInfo in bundleInfo.Resources) { var entry = catalogLookup.GetEntry(resourceInfo); if (entry == null) { Console.WriteLine("Could not find catalog entry for '{0}'.", resourceInfo.Name); continue; } if (entry.CompressedSize != resourceInfo.Size) { throw new FormatException(); } var outputName = Helpers.FilterPath(resourceInfo.Name); var outputPath = Path.Combine(outputBasePath, outputName + ".dummy"); var outputParentPath = Path.GetDirectoryName(outputPath); if (string.IsNullOrEmpty(outputParentPath) == false) { Directory.CreateDirectory(outputParentPath); } Console.WriteLine("{0}", resourceInfo.Name); bool wasConverted = false; if (convertTextures == true && resourceInfo.ResourceType == ResourceTypes.Texture) { wasConverted = ConvertTexture(bundleInfo, resourceInfo, entry, outputPath, catalogLookup, commonBundles); } if (wasConverted == false) { string extension; if (extensionsById.TryGetValue(resourceInfo.ResourceType, out extension) == true) { extension = "." + extension; } else { extension = ".#" + resourceInfo.ResourceType.ToString("X8"); } outputPath = Path.Combine(outputBasePath, outputName + extension); using (var output = File.Create(outputPath)) { Extraction.Extract(resourceInfo, entry, output); } } } } } }
public static void Main(string[] args) { bool noPatch = false; bool noCatch = false; int logLevelOrdinal = 3; bool showHelp = false; var options = new OptionSet() { { "no-catch", "don't catch exceptions when loading data", v => noCatch = v != null }, { "v|verbose", "increase log level (-v/-vv/-vvv)", v => IncreaseLogLevel(v, ref logLevelOrdinal) }, { "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]+ game_dir [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } LogHelper.SetConfiguration(NLog.LogLevel.FromOrdinal(logLevelOrdinal)); var outputBasePath = extras.Count > 1 ? extras[1] : "res_unpack"; List <string> files = Directory.GetFiles(extras[0], "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".toc", StringComparison.OrdinalIgnoreCase)).ToList(); for (int i = 0; i < files.Count; i++) { var inputPath = files[i]; string superbundleName; var dataBasePath = Discovery.FindBasePath(inputPath, out superbundleName); if (string.IsNullOrEmpty(dataBasePath) == true) { Logger.Error("Failed to discover base game path."); continue; } Console.WriteLine("----- " + (i + 1) + " of " + files.Count + " - " + Path.GetFileName(inputPath) + " ----"); Thread.Sleep(1000); var dataManager = DataManager.Initialize(dataBasePath, noPatch); if (dataManager == null) { Logger.Fatal("Could not initialize superbundle manager."); continue; } var extensionsById = ResourceTypes.GetExtensions(); VfsFormats.SuperbundleFile superbundle = null; try { superbundle = dataManager.MountSuperbundle(superbundleName); } catch { superbundle = null; } if (superbundle == null) { continue; } foreach (var resourceInfo in superbundle.Bundles .Where(bi => bi.Resources != null) .SelectMany(bi => bi.Resources) .OrderBy(bi => bi.Name)) { using (var data = new MemoryStream()) { Logger.Info(resourceInfo.Name); if (noCatch == true) { dataManager.LoadData(resourceInfo, data); data.Position = 0; } else { try { dataManager.LoadData(resourceInfo, data); data.Position = 0; } catch (ChunkCryptoKeyMissingException e) { Logger.Warn("Cannot decrypt '{0}' without crypto key '{1}'.", resourceInfo.Name, e.KeyId); continue; } catch (Exception e) { Logger.Warn(e, "Exception while loading '{0}':", resourceInfo.Name); continue; } } if (resourceInfo.ResourceType != ResourceTypes.Texture) { continue; } var outputName = Helpers.FilterPath(resourceInfo.Name); var outputPath = Path.Combine(outputBasePath, outputName + ".dummy"); var outputParentPath = Path.GetDirectoryName(outputPath); if (string.IsNullOrEmpty(outputParentPath) == false) { Directory.CreateDirectory(outputParentPath); } outputPath = Path.Combine(outputBasePath, outputName + ".dds"); Console.WriteLine(outputPath); ConvertTexture(data, outputPath, dataManager); } } dataManager.Dispose(); } }
public static void Main(string[] args) { bool convertTextures = false; bool verbose = false; bool showHelp = false; var options = new OptionSet() { { "convert-textures", "convert textures", v => convertTextures = 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_[sb|toc] [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } Paths paths; if (Paths.Discover(extras[0], extras.Count > 1 ? extras[1] : null, out paths) == false) { Console.WriteLine("Failed to discover data paths."); return; } var extensionsById = ResourceTypes.GetExtensions(); var superbundleName = Path.ChangeExtension(paths.Superbundle.Substring(paths.Data.Length + 1), null); superbundleName = Helpers.FilterName(superbundleName).ToLowerInvariant(); var layout = LayoutFile.Read(Path.Combine(paths.Data, "layout.toc")); var chunkLookup = new ChunkLookup(layout, paths.Data); var chunkLoader = new ChunkLoader(chunkLookup); var initFileSystemPath = Path.Combine(paths.Data, "initfs_Win32"); CasEncryptHelper.TryLoad(initFileSystemPath, chunkLoader); var superbundle = chunkLookup.AddBundle(superbundleName); // add common chunk bundles (chunks*.toc/sb) foreach (var superbundleInfo in layout.Superbundles.Where( sbi => ChunkLookup.IsChunkBundle(sbi.Name) == true)) { if (chunkLookup.AddBundle(superbundleInfo.Name.ToLowerInvariant()) == null) { Console.WriteLine("Failed to load catalog for '{0}'.", superbundleInfo.Name); } } foreach (var bundleInfo in superbundle.Bundles) { if (bundleInfo.Resources == null) { continue; } foreach (var resourceInfo in bundleInfo.Resources) { using (var data = new MemoryStream()) { try { chunkLoader.Load(resourceInfo, data); data.Position = 0; } catch (ChunkCryptoKeyMissingException e) { Console.WriteLine("Cannot decrypt '{0}' without crypto key '{1}'.", resourceInfo.Name, e.KeyId); continue; } catch (Exception e) { Console.WriteLine("Exception while loading '{0}':", resourceInfo.Name); Console.WriteLine(e); continue; } var outputName = Helpers.FilterPath(resourceInfo.Name); var outputPath = Path.Combine(paths.Output, outputName + ".dummy"); var outputParentPath = Path.GetDirectoryName(outputPath); if (string.IsNullOrEmpty(outputParentPath) == false) { Directory.CreateDirectory(outputParentPath); } if (verbose == true) { Console.WriteLine("{0}", resourceInfo.Name); } bool wasConverted = false; if (convertTextures == true && resourceInfo.ResourceType == ResourceTypes.Texture) { outputPath = Path.Combine(paths.Output, outputName + ".dds"); wasConverted = ConvertTexture(data, outputPath, chunkLookup, chunkLoader); } if (wasConverted == false) { string extension; if (extensionsById.TryGetValue(resourceInfo.ResourceType, out extension) == true) { extension = "." + extension; } else { extension = ".#" + resourceInfo.ResourceType.ToString("X8"); } outputPath = Path.Combine(paths.Output, outputName + extension); using (var output = File.Create(outputPath)) { output.WriteFromStream(data, data.Length); } } } } } }
public static void Main(string[] args) { bool convertTextures = false; bool noPatch = false; bool noCatch = false; int logLevelOrdinal = 3; bool showHelp = false; var options = new OptionSet() { { "t|convert-textures", "convert textures", v => convertTextures = v != null }, { "no-patch", "don't use patch data", v => noPatch = v != null }, { "no-catch", "don't catch exceptions when loading data", v => noCatch = v != null }, { "v|verbose", "increase log level (-v/-vv/-vvv)", v => IncreaseLogLevel(v, ref logLevelOrdinal) }, { "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_[sb|toc] [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } LogHelper.SetConfiguration(NLog.LogLevel.FromOrdinal(logLevelOrdinal)); var inputPath = extras[0]; var outputBasePath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, null) + "_res_unpack"; string superbundleName; var dataBasePath = Discovery.FindBasePath(inputPath, out superbundleName); if (string.IsNullOrEmpty(dataBasePath) == true) { Logger.Error("Failed to discover base game path."); return; } var dataManager = DataManager.Initialize(dataBasePath, noPatch); if (dataManager == null) { Logger.Fatal("Could not initialize superbundle manager."); return; } var extensionsById = ResourceTypes.GetExtensions(); var superbundle = dataManager.MountSuperbundle(superbundleName); foreach (var resourceInfo in superbundle.Bundles .Where(bi => bi.Resources != null) .SelectMany(bi => bi.Resources) .OrderBy(bi => bi.Name)) { using (var data = new MemoryStream()) { Logger.Info(resourceInfo.Name); if (noCatch == true) { dataManager.LoadData(resourceInfo, data); data.Position = 0; } else { try { dataManager.LoadData(resourceInfo, data); data.Position = 0; } catch (ChunkCryptoKeyMissingException e) { Logger.Warn("Cannot decrypt '{0}' without crypto key '{1}'.", resourceInfo.Name, e.KeyId); continue; } catch (Exception e) { Logger.Warn(e, "Exception while loading '{0}':", resourceInfo.Name); continue; } } var outputName = Helpers.FilterPath(resourceInfo.Name); var outputPath = Path.Combine(outputBasePath, outputName + ".dummy"); var outputParentPath = Path.GetDirectoryName(outputPath); if (string.IsNullOrEmpty(outputParentPath) == false) { Directory.CreateDirectory(outputParentPath); } bool wasConverted = false; if (convertTextures == true && resourceInfo.ResourceType == ResourceTypes.Texture) { outputPath = Path.Combine(outputBasePath, outputName + ".dds"); wasConverted = ConvertTexture(data, outputPath, dataManager); } if (wasConverted == false) { string extension; if (extensionsById.TryGetValue(resourceInfo.ResourceType, out extension) == true) { extension = "." + extension; } else { extension = ".#" + resourceInfo.ResourceType.ToString("X8"); } outputPath = Path.Combine(outputBasePath, outputName + extension); using (var output = File.Create(outputPath)) { data.Position = 0; output.WriteFromStream(data, data.Length); } } } } dataManager.Dispose(); }