diff --git a/SabreTools.Helper/Data/Build.cs b/SabreTools.Helper/Data/Build.cs index 299e0d73..9dae8815 100644 --- a/SabreTools.Helper/Data/Build.cs +++ b/SabreTools.Helper/Data/Build.cs @@ -204,6 +204,7 @@ namespace SabreTools.Helper.Data helptext.Add(" -ls, --lvl-split Split a SuperDAT or folder by internal path"); helptext.Add(" -out= Output directory"); helptext.Add(" -s, --short Use short output names"); + helptext.Add(" -r, --restore Restore original filename to each output DAT"); // Sort helptext.Add(" -ss, --sort Sort input files by a set of DATs"); diff --git a/SabreTools.Helper/Dats/DatFile.cs b/SabreTools.Helper/Dats/DatFile.cs index f5dd4155..ce4abe8f 100644 --- a/SabreTools.Helper/Dats/DatFile.cs +++ b/SabreTools.Helper/Dats/DatFile.cs @@ -5026,9 +5026,10 @@ namespace SabreTools.Helper.Dats /// Name of the directory to write the DATs out to /// Parent path for replacement /// True if short names should be used, false otherwise + /// True if original filenames should be used as the base for output filename, false otherwise /// Logger object for console and file writing /// True if split succeeded, false otherwise - public bool SplitByLevel(string outDir, string basepath, bool shortname, Logger logger) + public bool SplitByLevel(string outDir, string basepath, bool shortname, bool restore, Logger logger) { // Sanitize the basepath to be more predictable basepath = (basepath.EndsWith(Path.DirectorySeparatorChar.ToString()) ? basepath : basepath + Path.DirectorySeparatorChar); @@ -5051,7 +5052,7 @@ namespace SabreTools.Helper.Dats if (tempDat.Name != null && tempDat.Name != Style.GetDirectoryName(key)) { // Process and output the DAT - SplitByLevelHelper(tempDat, outDir, shortname, logger); + SplitByLevelHelper(tempDat, outDir, shortname, restore, logger); // Reset the DAT for the next items tempDat = (DatFile)CloneHeader(); @@ -5078,7 +5079,7 @@ namespace SabreTools.Helper.Dats } // Then we write the last DAT out since it would be skipped otherwise - SplitByLevelHelper(tempDat, outDir, shortname, logger); + SplitByLevelHelper(tempDat, outDir, shortname, restore, logger); return true; } @@ -5108,8 +5109,9 @@ namespace SabreTools.Helper.Dats /// DAT to clean and write out /// Directory to write out to /// True if short naming scheme should be used, false otherwise + /// True if original filenames should be used as the base for output filename, false otherwise /// Logger object for file and console output - private void SplitByLevelHelper(DatFile datFile, string outDir, bool shortname, Logger logger) + private void SplitByLevelHelper(DatFile datFile, string outDir, bool shortname, bool restore, Logger logger) { // Get the path that the file will be written out to string path = HttpUtility.HtmlDecode(String.IsNullOrEmpty(datFile.Name) @@ -5124,7 +5126,8 @@ namespace SabreTools.Helper.Dats : datFile.Name.Replace("/", " - ").Replace("\\", " - ") ) ); - datFile.Description += " (" + datFile.Name.Replace("/", " - ").Replace("\\", " - ") + ")"; + datFile.FileName = (restore ? FileName + " (" + datFile.FileName + ")" : datFile.FileName); + datFile.Description = Description + " (" + datFile.Name.Replace("/", " - ").Replace("\\", " - ") + ")"; datFile.Name = Name + " (" + datFile.Name.Replace("/", " - ").Replace("\\", " - ") + ")"; datFile.Type = null; diff --git a/SabreTools.Helper/Tools/Style.cs b/SabreTools.Helper/Tools/Style.cs index 399945cb..1a1267f3 100644 --- a/SabreTools.Helper/Tools/Style.cs +++ b/SabreTools.Helper/Tools/Style.cs @@ -28,6 +28,60 @@ namespace SabreTools.Helper.Tools { #region DAT Cleaning + /// + /// Clean a game (or rom) name to the WoD standard + /// + /// Name of the game to be cleaned + /// The cleaned name + public static string CleanGameName(string game) + { + ///Run the name through the filters to make sure that it's correct + game = NormalizeChars(game); + game = RussianToLatin(game); + game = SearchPattern(game); + + game = new Regex(@"(([[(].*[\)\]] )?([^([]+))").Match(game).Groups[1].Value; + game = game.TrimStart().TrimEnd(); + return game; + } + + /// + /// Clean a game (or rom) name to the WoD standard + /// + /// Array representing the path to be cleaned + /// The cleaned name + public static string CleanGameName(string[] game) + { + game[game.Length - 1] = CleanGameName(game[game.Length - 1]); + string outgame = String.Join(Path.DirectorySeparatorChar.ToString(), game); + outgame = outgame.TrimStart().TrimEnd(); + return outgame; + } + + /// + /// Clean a hash string and pad to the correct size + /// + /// Hash string to sanitize + /// Amount of characters to pad to + /// Cleaned string + public static string CleanHashData(string hash, int padding) + { + // First get the hash to the correct length + hash = (String.IsNullOrEmpty(hash) ? "" : hash.Trim()); + hash = (hash.StartsWith("0x") ? hash.Remove(0, 2) : hash); + hash = (hash == "-" ? "" : hash); + hash = (String.IsNullOrEmpty(hash) ? "" : hash.PadLeft(padding, '0')); + hash = hash.ToLowerInvariant(); + + // Then make sure that it has the correct characters + if (!Regex.IsMatch(hash, "[0-9a-f]{" + padding + "}")) + { + hash = ""; + } + + return hash; + } + /// /// Generate a proper outfile name based on a DAT and output directory /// @@ -196,85 +250,10 @@ namespace SabreTools.Helper.Tools return outfile; } - /// - /// Clean a game (or rom) name to the WoD standard - /// - /// Name of the game to be cleaned - /// The cleaned name - public static string CleanGameName(string game) - { - ///Run the name through the filters to make sure that it's correct - game = NormalizeChars(game); - game = RussianToLatin(game); - game = SearchPattern(game); - - game = new Regex(@"(([[(].*[\)\]] )?([^([]+))").Match(game).Groups[1].Value; - game = game.TrimStart().TrimEnd(); - return game; - } - - /// - /// Clean a game (or rom) name to the WoD standard - /// - /// Array representing the path to be cleaned - /// The cleaned name - public static string CleanGameName(string[] game) - { - game[game.Length - 1] = CleanGameName(game[game.Length - 1]); - string outgame = String.Join(Path.DirectorySeparatorChar.ToString(), game); - outgame = outgame.TrimStart().TrimEnd(); - return outgame; - } - - /// - /// Clean a hash string and pad to the correct size - /// - /// Hash string to sanitize - /// Amount of characters to pad to - /// Cleaned string - public static string CleanHashData(string hash, int padding) - { - // First get the hash to the correct length - hash = (String.IsNullOrEmpty(hash) ? "" : hash.Trim()); - hash = (hash.StartsWith("0x") ? hash.Remove(0, 2) : hash); - hash = (hash == "-" ? "" : hash); - hash = (String.IsNullOrEmpty(hash) ? "" : hash.PadLeft(padding, '0')); - hash = hash.ToLowerInvariant(); - - // Then make sure that it has the correct characters - if (!Regex.IsMatch(hash, "[0-9a-f]{" + padding + "}")) - { - hash = ""; - } - - return hash; - } - #endregion #region String Manipulation - /// - /// Get if a string contains Unicode characters - /// - /// Input string to test - /// True if the string contains at least one Unicode character, false otherwise - public static bool IsUnicode(string s) - { - return (s.Any(c => c > 255)); - } - - /// - /// Remove all chars that are considered path unsafe - /// - /// Input string to clean - /// Cleaned string - public static string RemovePathUnsafeCharacters(string s) - { - List invalidPath = Path.GetInvalidPathChars().ToList(); - return new string(s.Where(c => !invalidPath.Contains(c)).ToArray()); - } - /// /// Compare strings as numeric /// @@ -396,6 +375,27 @@ namespace SabreTools.Helper.Tools .ToArray()); } + /// + /// Get if a string contains Unicode characters + /// + /// Input string to test + /// True if the string contains at least one Unicode character, false otherwise + public static bool IsUnicode(string s) + { + return (s.Any(c => c > 255)); + } + + /// + /// Remove all chars that are considered path unsafe + /// + /// Input string to clean + /// Cleaned string + public static string RemovePathUnsafeCharacters(string s) + { + List invalidPath = Path.GetInvalidPathChars().ToList(); + return new string(s.Where(c => !invalidPath.Contains(c)).ToArray()); + } + /// /// Split a line as if it were a CMP rom line /// @@ -549,6 +549,38 @@ namespace SabreTools.Helper.Tools return input; } + /// + /// Convert Cyrillic lettering to Latin lettering + /// + /// String to be parsed + /// String with characters replaced + public static string RussianToLatin(string input) + { + string[,] charmap = { + { "А", "A" }, { "Б", "B" }, { "В", "V" }, { "Г", "G" }, { "Д", "D" }, + { "Е", "E" }, { "Ё", "Yo" }, { "Ж", "Zh" }, { "З", "Z" }, { "И", "I" }, + { "Й", "J" }, { "К", "K" }, { "Л", "L" }, { "М", "M" }, { "Н", "N" }, + { "О", "O" }, { "П", "P" }, { "Р", "R" }, { "С", "S" }, { "Т", "T" }, + { "У", "U" }, { "Ф", "f" }, { "Х", "Kh" }, { "Ц", "Ts" }, { "Ч", "Ch" }, + { "Ш", "Sh" }, { "Щ", "Sch" }, { "Ъ", "" }, { "Ы", "y" }, { "Ь", "" }, + { "Э", "e" }, { "Ю", "yu" }, { "Я", "ya" }, { "а", "a" }, { "б", "b" }, + { "в", "v" }, { "г", "g" }, { "д", "d" }, { "е", "e" }, { "ё", "yo" }, + { "ж", "zh" }, { "з", "z" }, { "и", "i" }, { "й", "j" }, { "к", "k" }, + { "л", "l" }, { "м", "m" }, { "н", "n" }, { "о", "o" }, { "п", "p" }, + { "р", "r" }, { "с", "s" }, { "т", "t" }, { "у", "u" }, { "ф", "f" }, + { "х", "kh" }, { "ц", "ts" }, { "ч", "ch" }, { "ш", "sh" }, { "щ", "sch" }, + { "ъ", "" }, { "ы", "y" }, { "ь", "" }, { "э", "e" }, { "ю", "yu" }, + { "я", "ya" }, + }; + + for (int i = 0; i < charmap.GetLength(0); i++) + { + input = input.Replace(charmap[i, 0], charmap[i, 1]); + } + + return input; + } + /// /// Replace special characters and patterns /// @@ -593,38 +625,6 @@ namespace SabreTools.Helper.Tools return input; } - /// - /// Convert Cyrillic lettering to Latin lettering - /// - /// String to be parsed - /// String with characters replaced - public static string RussianToLatin(string input) - { - string[,] charmap = { - { "А", "A" }, { "Б", "B" }, { "В", "V" }, { "Г", "G" }, { "Д", "D" }, - { "Е", "E" }, { "Ё", "Yo" }, { "Ж", "Zh" }, { "З", "Z" }, { "И", "I" }, - { "Й", "J" }, { "К", "K" }, { "Л", "L" }, { "М", "M" }, { "Н", "N" }, - { "О", "O" }, { "П", "P" }, { "Р", "R" }, { "С", "S" }, { "Т", "T" }, - { "У", "U" }, { "Ф", "f" }, { "Х", "Kh" }, { "Ц", "Ts" }, { "Ч", "Ch" }, - { "Ш", "Sh" }, { "Щ", "Sch" }, { "Ъ", "" }, { "Ы", "y" }, { "Ь", "" }, - { "Э", "e" }, { "Ю", "yu" }, { "Я", "ya" }, { "а", "a" }, { "б", "b" }, - { "в", "v" }, { "г", "g" }, { "д", "d" }, { "е", "e" }, { "ё", "yo" }, - { "ж", "zh" }, { "з", "z" }, { "и", "i" }, { "й", "j" }, { "к", "k" }, - { "л", "l" }, { "м", "m" }, { "н", "n" }, { "о", "o" }, { "п", "p" }, - { "р", "r" }, { "с", "s" }, { "т", "t" }, { "у", "u" }, { "ф", "f" }, - { "х", "kh" }, { "ц", "ts" }, { "ч", "ch" }, { "ш", "sh" }, { "щ", "sch" }, - { "ъ", "" }, { "ы", "y" }, { "ь", "" }, { "э", "e" }, { "ю", "yu" }, - { "я", "ya" }, - }; - - for (int i = 0; i < charmap.GetLength(0); i++) - { - input = input.Replace(charmap[i, 0], charmap[i, 1]); - } - - return input; - } - #endregion #region Externally sourced methods diff --git a/SabreTools/Partials/SabreTools_Inits.cs b/SabreTools/Partials/SabreTools_Inits.cs index 3d1d86a8..2970b162 100644 --- a/SabreTools/Partials/SabreTools_Inits.cs +++ b/SabreTools/Partials/SabreTools_Inits.cs @@ -257,7 +257,8 @@ namespace SabreTools /// List of inputs to be used /// Output directory for the split files /// True if short filenames should be used, false otherwise - private static void InitLevelSplit(List inputs, string outDir, bool shortname) + /// True if original filenames should be used as the base for output filename, false otherwise + private static void InitLevelSplit(List inputs, string outDir, bool shortname, bool restore) { // Loop over the input files foreach (string input in inputs) @@ -266,7 +267,7 @@ namespace SabreTools { DatFile datFile = new DatFile(); datFile.Parse(Path.GetFullPath(input), 0, 0, _logger, softlist: true, keep: true); - datFile.SplitByLevel(outDir, Path.GetDirectoryName(input), shortname, _logger); + datFile.SplitByLevel(outDir, Path.GetDirectoryName(input), shortname, restore, _logger); } else if (Directory.Exists(input)) { @@ -274,7 +275,7 @@ namespace SabreTools { DatFile datFile = new DatFile(); datFile.Parse(Path.GetFullPath(file), 0, 0, _logger, softlist: true, keep: true); - datFile.SplitByLevel(outDir, (input.EndsWith(Path.DirectorySeparatorChar.ToString()) ? input : input + Path.DirectorySeparatorChar), shortname, _logger); + datFile.SplitByLevel(outDir, (input.EndsWith(Path.DirectorySeparatorChar.ToString()) ? input : input + Path.DirectorySeparatorChar), shortname, restore, _logger); } } else diff --git a/SabreTools/SabreTools.cs b/SabreTools/SabreTools.cs index 1c612479..0d4901f5 100644 --- a/SabreTools/SabreTools.cs +++ b/SabreTools/SabreTools.cs @@ -994,7 +994,7 @@ namespace SabreTools // Split a SuperDAT by lowest available level else if (splitByLevel) { - InitLevelSplit(inputs, outDir, shortname); + InitLevelSplit(inputs, outDir, shortname, restore); } // Split a DAT by item type