private static bool ConvertTexture(MemoryStream data, string outputPath, ChunkLookup chunkLookup, ChunkLoader chunkLoader) { var textureHeader = TextureHeader.Read(data); if (textureHeader.Type != TextureType._2d) { return(false); } if (textureHeader.Unknown10 != 0 || (textureHeader.Flags != TextureFlags.None && textureHeader.Flags != TextureFlags.Unknown0 && textureHeader.Flags != (TextureFlags.Unknown0 | TextureFlags.Unknown3) && textureHeader.Flags != TextureFlags.Unknown5) || textureHeader.Unknown1C != 1) { throw new FormatException(); } SHA1 chunkSHA1; long size; if (chunkLookup.GetChunkSHA1(textureHeader.DataChunkId, out chunkSHA1, out size) == false) { throw new InvalidOperationException(); } var dataChunkInfo = chunkLookup.GetChunkVariant(chunkSHA1, size); if (dataChunkInfo == null) { throw new InvalidOperationException(); } byte[] dataBytes; using (var temp = new MemoryStream()) { chunkLoader.Load(dataChunkInfo, textureHeader.TotalSize, temp); temp.Position = 0; dataBytes = temp.GetBuffer(); } using (var output = File.Create(outputPath)) { DDSUtils.WriteFile(textureHeader, dataBytes, output); } return(true); }
public static void Main(string[] args) { bool verbose = false; bool showHelp = false; var options = new OptionSet() { { "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 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 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.Ebx == null) { continue; } foreach (var ebxInfo in bundleInfo.Ebx) { using (var data = new MemoryStream()) { try { chunkLoader.Load(ebxInfo, data); data.Position = 0; } catch (ChunkCryptoKeyMissingException e) { Console.WriteLine("Cannot decrypt '{0}' without crypto key '{1}'.", ebxInfo.Name, e.KeyId); continue; } catch (Exception e) { Console.WriteLine("Exception while loading '{0}':", ebxInfo.Name); Console.WriteLine(e); continue; } var outputName = Helpers.FilterPath(ebxInfo.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; outputPath = Path.Combine(paths.Output, outputName + ".entity"); wasConverted = ConvertEntity(data, outputPath, chunkLookup, chunkLoader); if (wasConverted == false) { outputPath = Path.Combine(paths.Output, outputName + ".ebx"); using (var output = File.Create(outputPath)) { output.WriteFromStream(data, data.Length); } } } } } }