public static void Main(string[] args) { Logger.PrintVersion("WSGF"); var flags = CommandLineFlags.ParseFlags <PatcherFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } var fovTarget = flags.FOVTarget?.ToHexOctetsB(); if (!string.IsNullOrWhiteSpace(flags.FOVCalc)) { var parts = flags.FOVCalc.Split('x', ':'); if (parts.Length >= 2 && float.TryParse(parts[0], out var width) && float.TryParse(parts[1], out var height)) { fovTarget = BitConverter.GetBytes(width / height); } } var buffer = File.ReadAllBytes(flags.File); File.WriteAllBytes(Path.ChangeExtension(flags.File, ".bak"), buffer.ToArray()); ReplaceSignature(buffer, "FOV", flags.FOVSignature, fovTarget); ReplaceSignature(buffer, "Unreal Engine 4 Aspect Ratio", flags.UE4RatioSignature, fovTarget); ReplaceSignature(buffer, "Unreal Engine 4 Pillarbox", flags.UE4PillarboxSignature, flags.UE4PillarboxTarget?.ToHexOctetsB()); ReplaceSignature(buffer, "Unreal Engine 4 FOV", flags.UE4YFOVSignature, flags.UE4YFOVTarget?.ToHexOctetsB()); File.WriteAllBytes(flags.File, buffer.ToArray()); }
public static void Main(string[] args) { Logger.PrintVersion("Nyotengu"); var flags = CommandLineFlags.ParseFlags <FilelistFlags>(CommandLineFlags.PrintHelp, args); if (flags == null || string.IsNullOrWhiteSpace(flags.GameDir)) { return; } Logger.Info("Nyotengu", "Generating filename list..."); var nyotengu = new Cethleann.ManagedFS.Nyotengu(flags); nyotengu.LoadFileList(flags.FileList, flags.GameId); foreach (var rdb in Directory.GetFiles(flags.GameDir, "*.rdb")) { nyotengu.AddDataFS(rdb); } nyotengu.SaveGeneratedFileList(null, flags.GameId); Logger.Info("Nyotengu", "Generating KTID property list..."); var propertyList = Cethleann.ManagedFS.Nyotengu.LoadKTIDFileListEx(null, "PropertyList"); foreach (var rdb in nyotengu.RDBs) { for (var i = 0; i < rdb.Entries.Count; ++i) { var entry = rdb.GetEntry(i); if (entry.FileKTID == rdb.Header.NameDatabaseKTID) { continue; } if (entry.TypeInfoKTID != 0xbf6b52c7) { continue; } var namedb = new NDB(rdb.ReadEntry(i).Span); foreach (var(_, strings) in namedb.Entries) { if (strings[1].Length == 0) { continue; } propertyList[RDB.Hash(strings[1])] = ("TypeInfo", strings[1]); foreach (var str in strings.Skip(2)) { propertyList[RDB.Hash(str)] = ("Property", str); } } } } Cethleann.ManagedFS.Nyotengu.SaveGeneratedFileList(propertyList, null, "DEBUG"); }
/// <summary> /// Parses the bebop config file and assigns entries to their corresponding command-line flag. /// </summary> /// <param name="flagStore">A <see cref="CommandLineFlags"/> instance.</param> /// <param name="configPath">The fully qualified path to the bebop config file, or null to trigger searching.</param> /// <returns>true if the config could be parsed without error, otherwise false.</returns> private static bool TryParseConfig(CommandLineFlags flagStore, string?configPath) { if (string.IsNullOrWhiteSpace(configPath)) { return(false); } if (!new FileInfo(configPath).Exists) { return(false); } using var doc = JsonDocument.Parse(File.ReadAllText(configPath)); var root = doc.RootElement; if (root.TryGetProperty("inputFiles", out var inputFileElement)) { flagStore.SchemaFiles = new List <string>(inputFileElement.GetArrayLength()); foreach (var fileElement in inputFileElement.EnumerateArray()) { if (fileElement.GetString() is not { } filePath) { continue; } flagStore.SchemaFiles.Add(filePath); } } if (root.TryGetProperty("inputDirectory", out var inputDirectoryElement)) { flagStore.SchemaDirectory = inputDirectoryElement.GetString(); } if (root.TryGetProperty("namespace", out var nameSpaceElement)) { flagStore.Namespace = nameSpaceElement.GetString(); } if (root.TryGetProperty("generators", out var generatorsElement)) { foreach (var generatorElement in generatorsElement.EnumerateArray()) { if (generatorElement.TryGetProperty("alias", out var aliasElement) && generatorElement.TryGetProperty("outputFile", out var outputElement)) { foreach (var flagAttribute in GetFlagAttributes() .Where(flagAttribute => flagAttribute.Attribute.IsGeneratorFlag && flagAttribute.Attribute.Name.Equals(aliasElement.GetString()))) { flagAttribute.Property.SetValue(flagStore, outputElement.GetString()); } } } } return(true); }
private static void Main(string[] args) { Logger.PrintVersion("Softness"); var flags = CommandLineFlags.ParseFlags <HasherFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } foreach (var str in flags.Strings) { Console.WriteLine($"{(flags.Raw ? RDB.Hash(str) : RDB.Hash(Path.GetFileNameWithoutExtension(str), flags.Format ?? Path.GetExtension(str).Substring(1).ToUpper(), flags.Prefix)):x8},{str}"); } }
private static async Task <int> Main(string[] args) { Flags = CommandLineFlags.ParseFlags <SubSplitFlags>(args); if (Flags == null) { return(1); } if (!File.Exists(Flags.InputFile)) { Logger.Error("Program", "Input file does not exist"); return(4); } Logger.Info("Program", "Downloading ffmpeg"); await FFmpegDownloader.GetLatestVersion(FFmpegVersion.Official); var probe = await FFmpeg.GetMediaInfo(Flags.InputFile); if (probe == null) { Logger.Error("FFmpeg", "Can't probe media file"); return(2); } if (!File.Exists(Flags.PrimarySubtitleFile)) { Logger.Error("Program", "Subtitle file missing"); return(5); } var subtitles = SubtitleFile.GetSubtitles(await File.ReadAllLinesAsync(Flags.PrimarySubtitleFile), out var subtitleLeadIn); if (!File.Exists(Flags.OverrideSubtitleFile)) { if (!string.IsNullOrEmpty(Flags.OverrideSubtitleFile)) { Logger.Warn("Program", "Override Subtitle File does not exist"); } } else { subtitles = SubtitleFile.GetSubtitles(await File.ReadAllLinesAsync(Flags.OverrideSubtitleFile), out subtitleLeadIn).Select((t, index) => subtitles.ElementAt(index) with { Text = t.Text, OriginalText = t.OriginalText }).ToList();
/// <summary> /// Inits the Arguments for this release. /// Returns <code>true</code> if all arguments are valid. /// </summary> private static bool InitArguments(string[] args) { // TODO(peleyal): Add default value option on Argument (and then add those values to the definition above) Arguments = new CommandLineArguments() { Tag = "beta", UseLocalRepository = false }; // Parse command line arguments. CommandLineFlags.ParseArguments(Arguments, args); if (string.IsNullOrEmpty(Arguments.Version)) { CommandLine.WriteError("Version number can't be null"); return(false); } var match = Regex.Match(Arguments.Version, @"^(\d+)\.(\d+)\.(\d)+$"); if (!match.Success) { CommandLine.WriteError("Invalid version Number. Version should be in <Major>.<Minor>.<Build> form."); return(false); } MajorVersion = int.Parse(match.Groups[1].Value); MinorVersion = int.Parse(match.Groups[2].Value); BuildVersion = int.Parse(match.Groups[3].Value); // Create the name of the local working copy. if (String.IsNullOrEmpty(Arguments.OutputDirectory)) { Arguments.OutputDirectory = DateTime.UtcNow.ToString("yyyy-MM-dd-hh-mm-ss"); } string fullPath = Path.GetFullPath(Arguments.OutputDirectory); if (!Directory.Exists(fullPath)) { Directory.CreateDirectory(fullPath); } Environment.CurrentDirectory = WorkingCopy = fullPath; CommandLine.WriteLine(Arguments.ToString()); return(true); }
private static void Main(string[] args) { Logger.PrintVersion("Cethleann"); var flags = CommandLineFlags.ParseFlags <DataExporterFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } var typeName = $"{typeof(DataGame).Namespace}.DataStructs.{flags.GameId:G}.{flags.StructName ?? "__UNDEFINED__"}"; var t = typeof(DataGame).Assembly.GetType(typeName); if (t == null || flags.StructName == null) { if (t == null) { Logger.Error("Cethleann", $"Cannot find type {typeName}"); } var ns = $"{typeof(DataGame).Namespace}.DataStructs.{flags.GameId:G}"; var types = string.Join("\n\t", typeof(DataGame).Assembly.GetTypes().Where(x => x.Namespace == ns).Select(x => x.Name)); Logger.Info("Cethleann", $"Available types for {flags.GameId:G}:\n\t{types}"); return; } // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault switch (flags.GameId) { case DataGame.DissidiaNT: ProcessECB(flags, t); break; case DataGame.DissidiaOO: ProcessXL20(flags, t); break; case DataGame.ThreeHouses: ProcessStruct(flags, t); break; default: throw new ArgumentOutOfRangeException(); } }
public static void Main(string[] args) { Logger.PrintVersion("Nyotengu"); var flags = CommandLineFlags.ParseFlags <FilelistFlags>(CommandLineFlags.PrintHelp, args); if (flags == null || string.IsNullOrWhiteSpace(flags.GameDir)) { return; } var nyotengu = new Cethleann.ManagedFS.Nyotengu(flags); nyotengu.LoadFileList(flags.FileList, flags.GameId); foreach (var rdb in Directory.GetFiles(flags.GameDir, "*.rdb")) { nyotengu.AddDataFS(rdb); } nyotengu.SaveGeneratedFileList(null, flags.GameId); }
private static void Main() { Control.CheckForIllegalCrossThreadCalls = false; //Application.EnableVisualStyles(); //Application.SetCompatibleTextRenderingDefault(false); #if !DEBUG try { #endif // Parse Arguments Arguments = DefaultArguments; PositionalArguments = CommandLineFlags.ParseArguments(Arguments, Environment.GetCommandLineArgs().Skip(1).ToArray()); if (string.IsNullOrEmpty(Arguments.ZoneDirectory)) { MessageBox.Show(String.Join(Environment.NewLine, CommandLineFlags.GenerateCommandLineHelp(Arguments)), "Syntax"); } var backup = new BackgroundWorker(); backup.DoWork += delegate { while (true) { Thread.Sleep(1000 * 60 * 3); if (ZONE != null) { ZONE.SaveZone(true); } } }; backup.RunWorkerAsync(); Application.Run((FORM = new MainForm())); #if !DEBUG } catch (Exception e) { CrashDialog.Show(e); } #endif }
private static void Main(string[] args) { Logger.PrintVersion("Nyotengu"); var flags = CommandLineFlags.ParseFlags <KTIDFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } var ndb = new NDB(); if (!string.IsNullOrEmpty(flags.NDBPath) && File.Exists(flags.NDBPath)) { ndb = new NDB(File.ReadAllBytes(flags.NDBPath)); } var objdb = new OBJDB(File.ReadAllBytes(flags.OBJDBPath)); var filelist = Cethleann.ManagedFS.Nyotengu.LoadKTIDFileList(flags.FileList, flags.GameId); var textureSection = new ResourceSectionHeader { Magic = DataType.TextureGroup, Version = 0x30303630 }; var textureHeader = new TextureGroupHeader { System = objdb.Header.System }; foreach (var ktid in flags.Paths) { if (!File.Exists(ktid)) { continue; } var ktidgroup = new KTIDTextureSet(File.ReadAllBytes(ktid)); var ktidsystem = ktidgroup.Textures.Select(x => objdb.Entries.TryGetValue(x, out var tuple) ? tuple : default).ToArray();
private static void Main(string[] args) { Logger.PrintVersion("Cethleann"); var flags = CommandLineFlags.ParseFlags <XORFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } var files = new List <string>(); foreach (var arg in flags.Paths) { if (!Directory.Exists(arg)) { files.Add(arg); continue; } if (flags.Recursive) { files.AddRange(Directory.GetFiles(arg, flags.Mask, SearchOption.TopDirectoryOnly)); } } foreach (var file in files) { Logger.Info("Cethleann", file); Span <byte> bytes = File.ReadAllBytes(file); for (var i = 0; i < bytes.Length; i++) { bytes[i] ^= (byte)flags.Xor; } File.WriteAllBytes(Path.Combine(Path.GetDirectoryName(file) !, $"dec_{flags.Xor:X}_{Path.GetFileName(file)}"), bytes.ToArray()); } }
/// <summary> /// Parses the bebop config file and assigns entries to their corresponding command-line flag. /// </summary> /// <param name="flagStore">A <see cref="CommandLineFlags"/> instance.</param> /// <param name="configPath">The fully qualified path to the bebop config file, or null to trigger searching.</param> /// <returns>true if the config could be parsed without error, otherwise false.</returns> private static bool TryParseConfig(CommandLineFlags flagStore, string?configPath) { if (string.IsNullOrWhiteSpace(configPath)) { return(false); } if (!new FileInfo(configPath).Exists) { return(false); } var configFile = new FileInfo(configPath); using var doc = JsonDocument.Parse(File.ReadAllText(configPath)); var root = doc.RootElement; if (root.TryGetProperty("inputFiles", out var inputFileElement)) { flagStore.SchemaFiles = new List <string>(inputFileElement.GetArrayLength()); foreach (var fileElement in inputFileElement.EnumerateArray()) { if (fileElement.GetString() is not { } filePath || configFile.DirectoryName is null) { continue; } flagStore.SchemaFiles.Add(Path.GetFullPath(Path.Combine(configFile.DirectoryName, filePath))); } } if (root.TryGetProperty("inputDirectory", out var inputDirectoryElement) && configFile.DirectoryName is not null) { var inputDirectory = inputDirectoryElement.GetString(); if (inputDirectory is not null) { flagStore.SchemaDirectory = Path.GetFullPath(Path.Combine(configFile.DirectoryName, inputDirectory)); } } if (root.TryGetProperty("namespace", out var nameSpaceElement)) { flagStore.Namespace = nameSpaceElement.GetString(); } if (root.TryGetProperty("generators", out var generatorsElement)) { foreach (var generatorElement in generatorsElement.EnumerateArray()) { if (generatorElement.TryGetProperty("alias", out var aliasElement) && generatorElement.TryGetProperty("outputFile", out var outputElement)) { foreach (var flagAttribute in GetFlagAttributes() .Where(flagAttribute => flagAttribute.Attribute.IsGeneratorFlag && flagAttribute.Attribute.Name.Equals(aliasElement.GetString()))) { var outputElementPath = outputElement.GetString(); if (configFile.DirectoryName is not null && outputElementPath is not null) { flagAttribute.Property.SetValue(flagStore, Path.GetFullPath(Path.Combine(configFile.DirectoryName, outputElementPath))); } if (generatorElement.TryGetProperty("langVersion", out var langVersion) && System.Version.TryParse(langVersion.ToString(), out var version)) { foreach (var flag in GetFlagAttributes()) { if ($"{flagAttribute.Attribute.Name}-version".Equals(flag.Attribute.Name, StringComparison.OrdinalIgnoreCase)) { flag.Property.SetValue(flagStore, version, null); } } } } } } } return(true); }
private static void Main(string[] args) { Logger.PrintVersion("Nyotengu"); var flags = CommandLineFlags.ParseFlags <AnimationGraphFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } var objdbNdb = new NDB(); var singletonNdb = new NDB(); if (!string.IsNullOrEmpty(flags.OBJDBNDBPath) && File.Exists(flags.OBJDBNDBPath)) { objdbNdb = new NDB(File.ReadAllBytes(flags.OBJDBNDBPath)); } if (!string.IsNullOrEmpty(flags.SingletonDBNDBPath) && File.Exists(flags.SingletonDBNDBPath)) { singletonNdb = new NDB(File.ReadAllBytes(flags.SingletonDBNDBPath)); } // ReSharper disable InconsistentNaming var CE1DB = new OBJDB(File.ReadAllBytes(flags.OBJDBPath)); var CE1Singleton = new OBJDB(File.ReadAllBytes(flags.SingletonPath)); // ReSharper restore InconsistentNaming var filelist = Cethleann.ManagedFS.Nyotengu.LoadKTIDFileList(flags.FileList, flags.GameId); var animationFiles = new Dictionary <KTIDReference, string>(); foreach (var directory in flags.AnimationDirectories ?? new HashSet <string?>()) { if (directory == null || !Directory.Exists(directory)) { continue; } foreach (var file in Directory.GetFiles(directory)) { var basename = Path.GetFileNameWithoutExtension(file); if (basename.Length != 8 || !KTIDReference.TryParse(basename, out var reference)) { reference = RDB.Hash(file, "G1A"); } animationFiles[reference] = file; } } var typeKTID = RDB.Hash("TypeInfo::Object::MotorCharacterSetting"); foreach (var entry in CE1DB.Entries.Select(x => x.Value).Where(entry => entry.Record.TypeInfoKTID == typeKTID)) { var(_, values) = entry.GetProperty("CharacterModelNameHash"); if (values == null) { continue; } var(_, actions) = entry.GetProperty("CharacterActionObjectNameHashArray"); if (actions == null || actions.Length == 0) { continue; } var nameHashes = values.Where(x => x != null).Select(x => new KTIDReference(x)).ToArray(); if (!nameHashes.Any(x => flags.Hashes.Contains(x))) { continue; } Logger.Info("ANIM", $"Found Character Settings: {string.Join(", ", nameHashes.Select(x => GetKTIDNameValue(x, false, objdbNdb, filelist)))}"); var done = new HashSet <KTIDReference>(); foreach (var actionHash in actions.Select(x => new KTIDReference(x))) { if (!CE1Singleton.Entries.TryGetValue(actionHash, out var player)) { Logger.Error("ANIM", $"Can't find animation player settings for {GetKTIDNameValue(actionHash, false, singletonNdb, filelist)}"); continue; } var properties = player.GetProperties("AnimationDataObjectNameHashArray", "SrcAnimationDataObjectNameHash", "DstAnimationDataObjectNameHash", "FCurveAnimationDataObjectNameHash"); var animationDataHashes = properties.SelectMany(x => x.values ?? Array.Empty <object?>()).ToArray(); var ktidHashes = animationDataHashes.Where(x => x != null).Select(x => new KTIDReference(x)).ToArray(); foreach (var animationDataHash in ktidHashes) { if (!CE1Singleton.Entries.TryGetValue(animationDataHash, out var animationData)) { Logger.Error("ANIM", $"Can't find animation data for {GetKTIDNameValue(animationDataHash, false, singletonNdb, filelist)}"); continue; } var(_, animationHashes) = animationData.GetProperty("G1AFileResourceHash"); if (animationHashes == null) { Logger.Error("ANIM", $"Can't find animation references for {GetKTIDNameValue(animationDataHash, false, singletonNdb, filelist)}"); continue; } foreach (var animationHashActual in animationHashes.Where(x => x != null).Select(x => new KTIDReference(x))) { if (!done.Add(animationHashActual)) { continue; } Logger.Info("ANIM", GetKTIDNameValue(animationHashActual, false, singletonNdb, filelist)); if (string.IsNullOrWhiteSpace(flags.Output) || !animationFiles.TryGetValue(animationHashActual, out var path)) { continue; } if (!Directory.Exists(flags.Output)) { Directory.CreateDirectory(flags.Output); } File.Copy(path, Path.Combine(flags.Output, Path.GetFileName(path)), true); } } } Console.WriteLine(); } }
/// <summary> /// Attempts to parse command-line flags into a <see cref="CommandLineFlags"/> instance /// </summary> /// <param name="args">the array of arguments to parse</param> /// <param name="flagStore">An instance which contains all parsed flags and their values</param> /// <param name="errorMessage">A human-friendly message describing why parsing failed.</param> /// <returns> /// If the provided /// <param name="args"></param> /// were parsed this method returns true. /// </returns> public static bool TryParse(string[] args, out CommandLineFlags flagStore, out string errorMessage) { errorMessage = string.Empty; var props = GetFlagAttributes(); var stringBuilder = new IndentedStringBuilder(); stringBuilder.AppendLine("Usage:"); stringBuilder.Indent(4); foreach (var prop in props.Where(prop => !string.IsNullOrWhiteSpace(prop.Attribute.UsageExample))) { stringBuilder.AppendLine($"{ReservedWords.CompilerName} {prop.Attribute.UsageExample}"); } stringBuilder.Dedent(4); stringBuilder.AppendLine(string.Empty); stringBuilder.AppendLine(string.Empty); stringBuilder.AppendLine("Options:"); stringBuilder.Indent(4); foreach (var prop in props) { stringBuilder.AppendLine($"--{prop.Attribute.Name} {prop.Attribute.HelpText}"); } flagStore = new CommandLineFlags(stringBuilder.ToString()); var parsedFlags = GetFlags(args); if (parsedFlags.Count == 0) { // if no flags passed in try and find the bebop.json config if (TryParseConfig(flagStore, FindBebopConfig())) { return(true); } errorMessage = "No command-line flags found."; return(false); } if (parsedFlags.HasFlag("help")) { flagStore.Help = true; return(true); } if (parsedFlags.HasFlag("version")) { flagStore.Version = true; return(true); } // if the config flag is passed in load settings from that path, otherwise search for it. var bebopConfig = parsedFlags.HasFlag("config") ? parsedFlags.GetFlag("config").GetValue() : FindBebopConfig(); // if bebop.json exist load it. the values in the JSON file are written to the store. if (!string.IsNullOrWhiteSpace(bebopConfig) && new FileInfo(bebopConfig).Exists) { if (!TryParseConfig(flagStore, bebopConfig)) { errorMessage = $"Failed to parse bebop configuration file at '{bebopConfig}'"; return(false); } } // parse all present command-line flags // any flag on the command-line that was also present in bebop.json will be overwritten. foreach (var flag in props) { if (!parsedFlags.HasFlag(flag.Attribute.Name)) { continue; } var parsedFlag = parsedFlags.GetFlag(flag.Attribute.Name); var propertyType = flag.Property.PropertyType; if (flag.Attribute.Name.Equals("check-schema")) { using var reader = new StreamReader(Console.OpenStandardInput()); flagStore.CheckSchemaFile = reader.ReadToEnd(); continue; } if (propertyType == typeof(bool)) { flag.Property.SetValue(flagStore, true); continue; } if (!parsedFlag.HasValues()) { errorMessage = $"command-line flag '{flag.Attribute.Name}' was not assigned any values."; return(false); } if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List <>)) { Type itemType = propertyType.GetGenericArguments()[0]; if (!(Activator.CreateInstance(typeof(List <>).MakeGenericType(itemType)) is IList genericList)) { errorMessage = $"Failed to activate '{flag.Property.Name}'."; return(false); } // file paths wrapped in quotes may contain spaces. foreach (var item in parsedFlag.Values) { if (string.IsNullOrWhiteSpace(item)) { continue; } // remove double quotes from the string so file paths can be parsed properly. genericList.Add(Convert.ChangeType(item.Trim(), itemType)); } flag.Property.SetValue(flagStore, genericList, null); } else if (propertyType.IsEnum) { if (!Enum.TryParse(propertyType, parsedFlag.GetValue(), true, out var parsedEnum)) { errorMessage = $"Failed to parse '{parsedFlag.GetValue()}' into a member of '{propertyType}'."; return(false); } flag.Property.SetValue(flagStore, parsedEnum, null); } else { flag.Property.SetValue(flagStore, Convert.ChangeType(parsedFlag.GetValue(), flag.Property.PropertyType), null); } } errorMessage = string.Empty; return(true); }
private static void Main(string[] args) { Logger.PrintVersion("Cethleann"); var flags = CommandLineFlags.ParseFlags <DownloaderFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } Dictionary <string, FileListEntry> entries = JsonSerializer.Deserialize <Dictionary <string, FileListEntry> >(File.ReadAllText(flags.DataFile)) ?? throw new NullReferenceException(); var pending = new ConcurrentQueue <(string url, string destination, string size)>(); var totalSize = 0UL; foreach (var(name, entry) in entries) { if (!name.Equals(entry.FileName, StringComparison.InvariantCultureIgnoreCase)) { Logger.Warn("Cethleann", $"{name} -> {entry.FileName}"); } var type = Path.GetExtension(entry.FileName).ToUpper().Substring(1); if (type == "DZ") { var bname = Path.GetFileNameWithoutExtension(entry.FileName); if (bname.Contains(".")) { type = $"{Path.GetExtension(bname).ToUpper().Substring(1)}_{type}"; } } if (type == "SWF" && !flags.Swf) { continue; } var path = Path.Combine(flags.OutputDirectory, entry.Directory, type, entry.FileName); if (File.Exists(path)) { continue; } pending.Enqueue(($"{flags.Server}/{entry.Directory}/{entry.FileName}", path, entry.Size.GetHumanReadableBytes())); var basedir = Path.GetDirectoryName(path); if (!Directory.Exists(basedir)) { Directory.CreateDirectory(basedir ?? "./"); } totalSize += entry.Size; } Logger.Warn("Cethleann", $"Going to download {totalSize} bytes ({totalSize.GetHumanReadableBytes()})"); Parallel.ForEach(pending, new ParallelOptions { MaxDegreeOfParallelism = flags.Threads }, pair => { var(url, dest, size) = pair; Logger.Info("Cethleann", url); if (flags.Dry) { return; } using var http = new WebClient(); try { http.DownloadFile(url, dest); Logger.Info("Cethleann", $"Downloaded {size} to {dest}"); } catch (Exception e) { File.WriteAllBytes(dest, Array.Empty <byte>()); Logger.Error("Cethleann", e); } }); }
private static void Main(string[] args) { Logger.PrintVersion("Cethleann"); var flags = CommandLineFlags.ParseFlags <GzFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } var files = new List <string>(); foreach (var arg in flags.Paths) { if (!Directory.Exists(arg)) { files.Add(arg); continue; } files.AddRange(Directory.GetFiles(arg, flags.Mask, SearchOption.AllDirectories)); } Func <byte[], byte[]>?method = null; string?ext = null; var options = new CompressionOptions { BlockSize = flags.BlockSize, Alignment = flags.Alignment, CompressionLevel = flags.Level, Length = flags.Length, ForceLastBlock = flags.CompressLast, PrefixSize = flags.PrefixedSize, Type = flags.Type }; if (flags.IsDz) { ext = ".dz"; if (flags.Compress) { method = bytes => DzCompression.Compress(bytes, options).ToArray(); } else { method = bytes => DzCompression.Decompress(bytes, options).ToArray(); } } else if (flags.IsStream) { ext = ".zl"; if (flags.Compress) { method = bytes => StreamCompression.Compress(bytes, options).ToArray(); } else { method = bytes => StreamCompression.Decompress(bytes, options).ToArray(); } } else if (flags.IsStream8000) { ext = ".z"; if (flags.Compress) { method = bytes => Stream8000Compression.Compress(bytes, options).ToArray(); } else { method = bytes => Stream8000Compression.Decompress(bytes, options).ToArray(); } } else if (flags.IsTable) { ext = ".gz"; if (flags.Compress) { method = bytes => TableCompression.Compress(bytes, options).ToArray(); } else { method = bytes => TableCompression.Decompress(bytes, options).ToArray(); } } if (method == null) { Logger.Error("Cethleann", "You must specify a compression method!"); return; } foreach (var file in files) { var target = flags.Compress ? file + ext : Path.Combine(Path.GetDirectoryName(file) ?? "", Path.GetFileNameWithoutExtension(file)); var baseTarget = target; var modulo = 0; while (File.Exists(target) && flags.Compress) { target = baseTarget + $"_{++modulo}"; } Logger.Info("Cethleann", $"{(flags.Compress ? "C" : "Dec")}ompressing {Path.GetFileName(file)} to {target}"); var bytes = File.ReadAllBytes(file); if (bytes.Length == 0) { Logger.Info("Cethleann", $"{Path.GetFileName(file)} is empty"); continue; } File.WriteAllBytes(target, method(bytes)); if (flags.Delete) { File.Delete(file); } } }
private static void Main(string[] args) { Logger.PrintVersion("Cethleann"); var flags = CommandLineFlags.ParseFlags <DataExporterFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } IManagedFS?fs = default; if (flags.Flayn) { fs = new Flayn(flags); ((Flayn)fs).LoadPatterns(); foreach (var gamedir in flags.GameDirs) { fs.AddDataFS(gamedir); } } else if (flags.Leonhart) { fs = new Leonhart(flags); foreach (var gamedir in flags.GameDirs) { fs.AddDataFS(gamedir); } } else if (flags.Mitsunari) { fs = new Mitsunari(flags); foreach (var gamedir in flags.GameDirs) { fs.AddDataFS(gamedir); } } else if (flags.Nyotengu) { fs = new Nyotengu(flags); foreach (var rdb in flags.GameDirs.SelectMany(gamedir => Directory.GetFiles(gamedir, "*.rdb"))) { fs.AddDataFS(rdb); } ((Nyotengu)fs).LoadExtList(); } else if (flags.Zhao) // yep it's identical, but filenames are suffixed with .hash // so it would try to load RDB BINs in normal installs since those are named .rdb.bin { fs = new Nyotengu(flags); foreach (var rdb in flags.GameDirs.SelectMany(gamedir => Directory.GetFiles(gamedir, "*.rdb.*"))) { fs.AddDataFS(rdb); } ((Nyotengu)fs).LoadExtList(); } else if (flags.Reisalin) { fs = new Reisalin(flags); foreach (var gamedir in flags.GameDirs.SelectMany(gameDir => Directory.GetFiles(gameDir, "*.pak"))) { fs.AddDataFS(gamedir); } } else if (flags.Yshtola) { YshtolaSettings?settings = flags.GameId switch { "DissidiaNT" => new YshtolaDissidiaSettings(), "VenusVacation" => new YshtolaVenusVacationSettings(), _ => default }; if (settings == default) { Logger.Error("Cethleann", $"No decryption settings found for {flags.GameId}!"); return; } fs = new Yshtola(flags, settings); var yshtola = (Yshtola)fs; yshtola.Root = flags.GameDirs.ToArray(); foreach (var tableName in settings.TableNames) { fs.AddDataFS(tableName); } if (!Directory.Exists(flags.OutputDirectory)) { Directory.CreateDirectory(flags.OutputDirectory); } for (var index = 0; index < yshtola.Tables.Count; index++) { var table = yshtola.Tables[index]; var type = Path.GetDirectoryName(yshtola.Settings.TableNames[index]); var name = $"manifest-{type ?? "COMMON"}.{flags.GameId.ToLower()}"; File.WriteAllBytes(Path.Combine(flags.OutputDirectory, name), table.Buffer.ToArray()); } if (flags.YshtolaManifestOnly) { return; } } if (fs == null) { Logger.Error("Cethleann", "No FS specified! Prove --flayn, --reisalin, --leonhart, --mitsunari, --nyotengu, or --yshtola!"); return; } if (!flags.NoFilelist) { fs.LoadFileList(flags.FileList); } if (flags.NyotenguGeneratedFileList && fs is Nyotengu nyotengu) { nyotengu.SaveGeneratedFileList(flags.FileList); return; } for (var index = 0; index < fs.EntryCount; index++) { try { var data = fs.ReadEntry(index).Span; var dt = data.GetDataType(); var ext = UnbundlerLogic.GetExtension(data); var filepath = fs.GetFilename(index, ext, dt) ?? $"{index}.{ext}"; while (filepath.StartsWith("\\") || filepath.StartsWith("/")) { filepath = filepath.Substring(1); } if (flags.Reisalin && filepath.EndsWith(".gz", StringComparison.InvariantCultureIgnoreCase)) { if (data[4] == 0x78) { data = StreamCompression.Decompress(data, new CompressionOptions { Length = -1, Type = DataCompression.Deflate }); } filepath = filepath.Substring(0, filepath.Length - 3); } var pathBase = $@"{flags.OutputDirectory}\{filepath}"; UnbundlerLogic.TryExtractBlob(pathBase, data, false, flags, false); } catch (Exception e) { Logger.Error("Cethleann", e); #if DEBUG throw; #endif } } fs.Dispose(); }
private static void Main(string[] args) { Logger.PrintVersion("Yshtola"); var flags = CommandLineFlags.ParseFlags <DownloaderFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } YshtolaSettings?settings = flags.GameId switch { "DissidiaNT" => new YshtolaDissidiaSettings(), "VenusVacation" => new YshtolaVenusVacationSettings(), _ => default }; if (settings == default) { Logger.Error("Yshtola", $"No decryption settings found for {flags.GameId}!"); return; } using var fs = new Cethleann.ManagedFS.Yshtola(flags, settings) { Root = new[] { flags.GameDir, flags.OutputDirectory } }; foreach (var tableName in settings.TableNames) { fs.AddDataFS(tableName); } var pending = new ConcurrentQueue <(string url, string destination, string size)>(); var totalSize = 0UL; foreach (var table in fs.Tables) { for (var index = 0; index < table.Entries.Length; index++) { var entry = table.Entries[index]; var pkgInfo = table.PackageInfo; if (pkgInfo == null) { continue; } var packageEntry = pkgInfo.InfoTable.Entries[index]; var filepath = entry.Path(table.Buffer, table.Header.Offset); var path = Path.Combine(flags.OutputDirectory, filepath); if (packageEntry.Version <= 0 || File.Exists(path) || File.Exists(Path.Combine(flags.GameDir, filepath))) { continue; } pending.Enqueue(($"{flags.Server}/{packageEntry.Version}/{filepath}", path, ((ulong)entry.CompressedSize).GetHumanReadableBytes())); var basedir = Path.GetDirectoryName(path); if (!Directory.Exists(basedir)) { Directory.CreateDirectory(basedir ?? "./"); } totalSize += entry.CompressedSize; } } Logger.Warn("Yshtola", $"Going to download {totalSize} bytes ({totalSize.GetHumanReadableBytes()})"); Parallel.ForEach(pending, new ParallelOptions { MaxDegreeOfParallelism = flags.Threads }, pair => { var(url, dest, size) = pair; Logger.Info("Yshtola", url); if (flags.Dry) { return; } using var http = new WebClient(); try { http.DownloadFile(url, dest); Logger.Info("Yshtola", $"Downloaded {size} to {dest}"); } catch (Exception e) { File.WriteAllBytes(dest, Array.Empty <byte>()); Logger.Error("Yshtola", e); } }); }
private static void Main(string[] args) { Logger.PrintVersion("Cethleann"); var flags = CommandLineFlags.ParseFlags <UnbundlerToolFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } var files = new List <string>(); foreach (var arg in flags.Paths) { if (!Directory.Exists(arg)) { files.Add(arg); continue; } if (flags.Recursive) { files.AddRange(Directory.GetFiles(arg, flags.Mask, SearchOption.AllDirectories)); } } foreach (var file in files) { try { Logger.Info("Cethleann", $"Extracting {Path.GetFileName(file)}..."); var data = File.ReadAllBytes(file); var pathBase = file; if (!file.EndsWith(".text")) { if (Path.GetFileName(file) == Path.GetFileNameWithoutExtension(file)) { pathBase += "_contents"; } else { pathBase = Path.Combine(Path.GetDirectoryName(file) ?? string.Empty, Path.GetFileNameWithoutExtension(file)); } } if (UnbundlerLogic.TryExtractBlob(pathBase, data, true, flags, true) == 0) { continue; } if (flags.Delete) { File.Delete(file); } } catch (Exception e) { Logger.Error("Cethleann", e); #if DEBUG throw; #endif } } }
private static void Main(string[] args) { Logger.PrintVersion("Cethleann"); var flags = CommandLineFlags.ParseFlags <IdentifyFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } foreach (var file in flags.Paths) { if (file == null || !File.Exists(file)) { continue; } Console.Write($"{file} "); var datablob = new Span <byte>(File.ReadAllBytes(file)); var type = flags.ForceType == DataType.None ? datablob.GetDataType() : flags.ForceType; if (!datablob.IsKnown()) { if (datablob.IsDataTable()) { if (PrintDataTable(datablob, flags)) { continue; } } if (datablob.IsBundle()) { if (PrintBundle(datablob, flags)) { continue; } } if (datablob.IsSliceBundle()) { if (PrintSliceBundle(datablob, flags)) { continue; } } if (datablob.IsPointerBundle()) { if (PrintPointerBundle(datablob, flags)) { continue; } } if (datablob.IsByteBundle()) { if (PrintByteBundle(datablob, flags)) { continue; } } } switch (type) { case DataType.SCEN when PrintSCEN(datablob, flags): case DataType.MDLK when PrintMDLK(datablob, flags): case DataType.KTSR when PrintKTSR(datablob, flags): case DataType.KTSC when PrintKTSC(datablob, flags): case DataType.Model when PrintG1M(datablob, flags): case DataType.XL when PrintXL(datablob): case DataType.GAPK when PrintGAPK(datablob, flags, false): case DataType.GEPK when PrintGAPK(datablob, flags, true): case DataType.GMPK when PrintGMPK(datablob, flags): case DataType.Large when PrintG1L(datablob, flags): case DataType.KOVS when PrintKOVS(datablob, flags): case DataType.ElixirArchive when PrintElixir(datablob, flags): case DataType.RTRPK when PrintRESPACK(datablob, flags): case DataType.EFFRESPK when PrintRESPACK(datablob, flags): case DataType.TDPACK when PrintRESPACK(datablob, flags): case DataType.COLRESPK when PrintRESPACK(datablob, flags): case DataType.MDLRESPK when PrintRESPACK(datablob, flags): case DataType.MDLTEXPK when PrintRESPACK(datablob, flags): case DataType.EXARG when PrintRESPACK(datablob, flags): case DataType.TRRRESPK when PrintRESPACK(datablob, flags): case DataType.G1E_PACK when PrintRESPACK(datablob, flags): case DataType.G1M_PACK when PrintRESPACK(datablob, flags): case DataType.G1H_PACK when PrintRESPACK(datablob, flags): case DataType.G2A_PACK when PrintRESPACK(datablob, flags): case DataType.HEADPACK when PrintRESPACK(datablob, flags): case DataType.G1COPACK when PrintRESPACK(datablob, flags): case DataType.WHD when PrintWHD(datablob, flags): continue; case DataType.None: break; case DataType.LINKDATA: break; case DataType.StructTable: break; case DataType.ECB: break; case DataType.SARC: break; case DataType.SPKG: break; case DataType.KTSS: break; case DataType.OGG: break; case DataType.SPK3: break; case DataType.SwingDefinition: break; case DataType.River: break; case DataType.RIGB: break; case DataType.RIGBL: break; case DataType.ERTR: break; case DataType.DATD: break; case DataType.LCD0: break; case DataType.WEBM: break; case DataType.ScreenLayout: break; case DataType.ScreenLayoutTexture: break; case DataType.VideoSource: break; case DataType.Font2: break; case DataType.Morph: break; case DataType.Collision: break; case DataType.XL20: break; case DataType.TextureGroup: break; case DataType.AnimationV2: break; case DataType.Animation: break; case DataType.Shader: break; case DataType.EffectManager: break; case DataType.Effect: break; case DataType.SEBin: break; case DataType.PostFX: break; case DataType.G1MS: break; case DataType.G1MF: break; case DataType.G1MG: break; case DataType.G1MM: break; case DataType.EXTR: break; case DataType.COLL: break; case DataType.NUNO: break; case DataType.NUNV: break; case DataType.NUNS: break; case DataType.SOFT: break; case DataType.HAIR: break; case DataType.LMPK: break; case DataType.BPK: break; case DataType.RIFF: break; case DataType.HDDB: break; case DataType.WBH: break; case DataType.WBD: break; case DataType.RDB: break; case DataType.RDBIndex: break; case DataType.PortableRDB: break; case DataType.NDB: break; case DataType.NDBIndex: break; case DataType.OBJDB: break; case DataType.OBJDBIndex: break; case DataType.OBJDBRecord: break; case DataType.Compressed: break; case DataType.CompressedChonky: break; case DataType.PackageInfo: break; case DataType.WMV: break; case DataType.DDS: break; case DataType.CharacterData: break; case DataType.CONT: break; case DataType.TMC: break; case DataType.Clip: break; case DataType.Body: break; case DataType.PBSMaterial: break; case DataType.OldTDPack: break; default: Console.WriteLine($"unknown {type.ToFourCC(true)} {(int) type:X8} {((ulong) datablob.Length).GetHumanReadableBytes()}"); continue; } } }
private static void Main(string[] args) { Logger.PrintVersion("Nyotengu"); var flags = CommandLineFlags.ParseFlags <DatabaseFlags>(CommandLineFlags.PrintHelp, args); if (flags == null) { return; } var files = new HashSet <string>(); foreach (var path in flags.Paths) { if (File.Exists(path)) { files.Add(path); } if (!Directory.Exists(path)) { continue; } foreach (var file in Directory.GetFiles(path)) { files.Add(file); } } var ndbFiles = new Dictionary <KTIDReference, string>(); if (flags.NDBPaths != null) { foreach (var nameFile in flags.NDBPaths.Where(Directory.Exists).SelectMany(Directory.GetFiles).Union(flags.NDBPaths.Where(File.Exists))) { ndbFiles[RDB.Hash(Path.GetFileName(nameFile))] = nameFile; if (KTIDReference.TryParse(Path.GetFileNameWithoutExtension(nameFile), NumberStyles.HexNumber, null, out var hashedName)) { ndbFiles[hashedName] = nameFile; } } } var filelist = Cethleann.ManagedFS.Nyotengu.LoadKTIDFileListShared(flags.FileList, flags.GameId); var propertyList = Cethleann.ManagedFS.Nyotengu.LoadKTIDFileList(null, "PropertyList"); var filters = flags.TypeInfoFilter?.Split(',').Select(x => RDB.Hash(x.Trim())).ToHashSet() ?? new HashSet <KTIDReference>(); var typeHashes = new Dictionary <KTIDReference, string>(); var extraHashes = new Dictionary <KTIDReference, string>(); var missingProperties = new HashSet <KTIDReference>(); foreach (var file in files) { Logger.Log(ConsoleSwatch.XTermColor.White, true, Console.Error, "Nyotengu", "INFO", file); Span <byte> buffer = File.ReadAllBytes(file); // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault switch (buffer.GetDataType()) { case DataType.OBJDB: { ProcessOBJDB(buffer, ndbFiles, filelist, propertyList, filters, flags, missingProperties); break; } case DataType.NDB: { if (flags.HashTypes || flags.HashExtra) { HashNDB(buffer, typeHashes, extraHashes, flags); } else if (flags.CreateFilelist) { NDBFilelist(buffer, Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file)), flags, filelist); } else { ProcessNDB(buffer, flags); } break; } default: Logger.Error("Nyotengu", $"Format for {file} is unknown!"); break; } } if (flags.HashTypes) { foreach (var(hash, text) in typeHashes.OrderBy(x => x.Key)) { Console.WriteLine($"TypeInfo,{hash:x8},{text}"); } } if (flags.HashExtra) { foreach (var(hash, text) in extraHashes.OrderBy(x => x.Key)) { Console.WriteLine($"Property,{hash:x8},{text}"); } } // ReSharper disable once InvertIf if (flags.CreateMissingList) { var location = ManagedFSHelper.GetFileListLocation(null, "MissingProperties", "rdb"); using var file = File.Open(location, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read); file.Seek(0, SeekOrigin.End); using var writer = new StreamWriter(file, Encoding.UTF8); foreach (var hash in missingProperties) { writer.WriteLine($"Property,{hash:x8},"); } } }