Ejemplo n.º 1
0
 private void Save(object sender, RoutedEventArgs e)
 {
     if (!File.Exists(currentSPCFilename))
     {
         SaveAs(sender, e);
     }
     else
     {
         currentSPC.Save(currentSPCFilename);
         statusText.Text = $"{currentSPCFilename} saved.";
     }
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Processes a previously-extracted subfile that's open in an editor. This process runs its translation steps backwards,
        /// before finally re-packing the final product into the original SPC file it came from.
        /// </summary>
        /// <param name="tempDir">The temporary directory where the extracted subfile data is located.</param>
        /// <param name="info">The <see cref="EditorTrackingInfo"/> associated with the editor and subfile.</param>
        private void RepackArchiveSubfile(string tempDir, EditorTrackingInfo info)
        {
            // First, run all translation steps in reverse
            var translationSteps    = info.SelectedAssociation.TranslationSteps;
            var translatedFilenames = info.SubfileNameHistory;

            for (int step = (translationSteps.Count - 1); step >= 0; --step)
            {
                // Resolve internal/external translator
                object resolvedTranslator = Config.FileAssociationConfig.ResolveInternalExternal(translationSteps[step]) as Process;

                // Run the translation step
                if (resolvedTranslator is Window)
                {
                    Window translatorWindow = resolvedTranslator as Window;

                    // Finally, open the target editor window as blocking
                    translatorWindow.ShowDialog();
                }
                else if (resolvedTranslator is Process)
                {
                    Process translatorProcess = resolvedTranslator as Process;

                    // Setup the target process' launch args
                    translatorProcess.StartInfo.Arguments = Path.Combine(tempDir, translatedFilenames[step + 1]);

                    translatorProcess.Start();
                    translatorProcess.WaitForExit();
                }
                else
                {
                    // If we get here, there's been an error and we should abort
                    return;
                }
            }

            // The final translated filename is the original file & format, repack it
            SpcFile spc = new SpcFile();

            spc.Load(info.OriginArchivePath);
            string fullSubfilePath = Path.Combine(tempDir, translatedFilenames[0]);

            spc.InsertSubfile(fullSubfilePath);
            spc.Save(info.OriginArchivePath);
        }
Ejemplo n.º 3
0
        static void Main(string[] args)
        {
            Console.WriteLine("SPC Tool by CaptainSwag101\n" +
                              "Version 0.0.2, built on 2019-09-25\n");

            // Parse input argument
            if (args.Length == 0)
            {
                return;
            }

            FileInfo info = new FileInfo(args[0]);

            if (!info.Exists)
            {
                Console.WriteLine($"ERROR: \"{args[0]}\" does not exist.");
                return;
            }

            if (info.Extension.ToLowerInvariant() != ".spc")
            {
                Console.WriteLine("ERROR: Input file does not have the \".spc\" extension.");
                return;
            }

            // If the first argument is a valid SPC file (and if we reach this point it probably is), it is the input.
            input = args[0];

            // Parse operation argument
            // If command starts with "--", it is our operation to perform
            if (args.Length > 1 && args[1].StartsWith("--"))
            {
                string op = args[1].TrimStart('-').ToLowerInvariant();
                if (validOperations.Keys.Any(op.Contains))
                {
                    operation = op;
                }
                else
                {
                    Console.WriteLine("ERROR: Invalid operation specified.");
                    return;
                }
            }

            // Parse target arguments
            for (int i = 2; i < args.Length; ++i)
            {
                targets.Add(args[i]);
            }

            // Load the input file
            SpcFile spc = new SpcFile();

            spc.Load(input);

            // Execute operation
            if (operation == null)
            {
                Console.WriteLine("ERROR: No operation specified.");
            }
            else if (validOperations[operation] != -1 && targets.Count != validOperations[operation])
            {
                Console.WriteLine($"ERROR: Invalid number of target(s) specified, expected {validOperations[operation]}.");
            }
            else
            {
                switch (operation)
                {
                case "list":
                case "bench":
                    Console.WriteLine($"\"{info.Name}\" contains the following subfiles:\n");
                    foreach (SpcSubfile subfile in spc.Subfiles)
                    {
                        Console.WriteLine($"Subfile name: \"{subfile.Name}\"");
                        Console.WriteLine($"\tCompression flag: {subfile.CompressionFlag}");
                        Console.WriteLine($"\tUnknown flag: {subfile.UnknownFlag}");
                        Console.WriteLine($"\tCurrent size: {subfile.CurrentSize.ToString("n0")} bytes");
                        Console.WriteLine($"\tOriginal size: {subfile.OriginalSize.ToString("n0")} bytes");

                        // Benchmark decompression and compression
                        if (operation == "bench")
                        {
                            Stopwatch stopwatch = new Stopwatch();

                            Console.Write("Decompressing...");
                            stopwatch.Start();
                            subfile.Decompress();
                            stopwatch.Stop();
                            Console.WriteLine($" Done! Took {stopwatch.Elapsed.ToString()}");

                            Console.Write("Compressing...");
                            stopwatch.Restart();
                            subfile.Compress();
                            stopwatch.Stop();
                            Console.WriteLine($" Done! Took {stopwatch.Elapsed.ToString()}");
                        }

                        Console.WriteLine();
                    }
                    break;

                case "extract":
                    // Setup an output directory for extracted files
                    output ??= info.DirectoryName + Path.DirectorySeparatorChar + info.Name.Substring(0, info.Name.Length - info.Extension.Length);
                    Directory.CreateDirectory(output);

                    // Generate list of subfiles to be extracted that match the target regex
                    List <string> subfilesToExtract = new List <string>();
                    foreach (string target in targets)
                    {
                        string regexTarget = "^" + Regex.Escape(target).Replace("\\?", ".").Replace("\\*", ".*") + "$";

                        foreach (SpcSubfile subfile in spc.Subfiles)
                        {
                            if (Regex.IsMatch(subfile.Name, regexTarget))
                            {
                                subfilesToExtract.Add(subfile.Name);
                            }
                        }
                    }

                    // Extract the subfiles using Tasks
                    Task[] extractTasks = new Task[subfilesToExtract.Count];

                    // IMPORTANT: If we ever switch to a for loop instead of foreach,
                    // make sure to make a local scoped copy of the subfile name in order to prevent
                    // threading weirdness from passing the wrong string value and causing random issues.
                    foreach (string subfileName in subfilesToExtract)
                    {
                        Console.WriteLine($"Extracting \"{subfileName}\"...");

                        extractTasks[subfilesToExtract.IndexOf(subfileName)] = Task.Factory.StartNew(() => spc.ExtractSubfile(subfileName, output));
                    }

                    // Wait until all target subfiles have been extracted
                    Task.WaitAll(extractTasks);
                    break;

                case "insert":
                    // Insert the subfiles using Tasks
                    Task[] insertTasks = new Task[targets.Count];

                    // IMPORTANT: If we ever switch to a for loop instead of foreach,
                    // make sure to make a local scoped copy of the subfile name in order to prevent
                    // threading weirdness from passing the wrong string value and causing random issues.
                    foreach (string subfileName in targets)
                    {
                        Console.WriteLine($"Inserting \"{subfileName}\"...");

                        insertTasks[targets.IndexOf(subfileName)] = spc.InsertSubfileAsync(subfileName, confirmation: ConfirmOverwrite);
                    }

                    // Wait until all target subfiles have been inserted
                    foreach (Task task in insertTasks)
                    {
                        task.Start();
                        task.Wait();
                    }

                    // Save the spc file
                    spc.Save(input);
                    break;
                }
            }

            if (pauseAfterComplete)
            {
                Console.WriteLine("Press Enter to close...");
                Console.Read();
            }
        }