public void Process()
        {
            if (Context.Options.OutDir == null)
            {
                Context.Logger.LogMessage("Output directory must be specified.");
                return;
            }

            var localFs = new LocalFileSystem(Context.Options.InFile);
            var outFs   = new LocalFileSystem(Context.Options.OutDir);

            FsClient.Register("search".ToU8Span(), localFs);
            FsClient.Register("out".ToU8Span(), outFs);

            IEnumerable <DirectoryEntryEx> entries = FsClient.EnumerateEntries("search:/", "*.xci",
                                                                               SearchOptions.CaseInsensitive | SearchOptions.RecurseSubdirectories)
                                                     .Concat(FsClient.EnumerateEntries("search:/", "*.nsp",
                                                                                       SearchOptions.CaseInsensitive | SearchOptions.RecurseSubdirectories))
                                                     .Concat(FsClient.EnumerateEntries("search:/", "*.nca",
                                                                                       SearchOptions.CaseInsensitive | SearchOptions.RecurseSubdirectories))
                                                     .Concat(FsClient.EnumerateEntries("search:/", "*.nso",
                                                                                       SearchOptions.CaseInsensitive | SearchOptions.RecurseSubdirectories));

            {
                foreach (DirectoryEntryEx entry in entries)
                {
                    try
                    {
                        Context.Logger.LogMessage(entry.FullPath);

                        string extension = Path.GetExtension(entry.Name);

                        if (extension.ToLower() == ".xci")
                        {
                            ProcessXci(entry.FullPath);
                        }
                        else if (extension.ToLower() == ".nsp")
                        {
                            ProcessNsp(entry.FullPath);
                        }
                        else if (extension.ToLower() == ".nca")
                        {
                            ProcessNcaFile(entry.FullPath);
                        }
                        else if (extension.ToLower() == ".nso")
                        {
                            string parentDirectory = PathTools.GetParentDirectory(entry.FullPath);

                            // Don't process sets multiple times
                            if (LooseNsoSetsProcessed.Contains(parentDirectory))
                            {
                                continue;
                            }

                            if (IsNsoSetDirectory(parentDirectory))
                            {
                                ProcessNsoSetDirectory(parentDirectory);
                                LooseNsoSetsProcessed.Add(parentDirectory);
                            }
                            else
                            {
                                ProcessNso(entry.FullPath);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Error processing {entry.FullPath}");
                        Console.WriteLine(ex);
                    }
                }
            }

            CalculateVersions();
            RenameOutput();

            FsClient.Unmount("search");
            FsClient.Unmount("out");
        }