Exemple #1
0
        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());
        }
Exemple #2
0
        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");
        }
Exemple #3
0
        /// <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}");
            }
        }
Exemple #5
0
        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();
Exemple #6
0
        /// <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);
        }
Exemple #7
0
        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);
        }
Exemple #9
0
        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
        }
Exemple #10
0
        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();
Exemple #11
0
        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());
            }
        }
Exemple #12
0
        /// <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);
        }
Exemple #13
0
        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();
            }
        }
Exemple #14
0
        /// <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);
        }
Exemple #15
0
        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);
                }
            });
        }
Exemple #16
0
        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);
                }
            }
        }
Exemple #17
0
        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();
        }
Exemple #18
0
        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);
                }
            });
        }
Exemple #19
0
        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
                }
            }
        }
Exemple #20
0
        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;
                }
            }
        }
Exemple #21
0
        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},");
                }
            }
        }