diff --git a/SabreTools.Library/DatFiles/DatFile.cs b/SabreTools.Library/DatFiles/DatFile.cs index c69880b2..0ee6b444 100644 --- a/SabreTools.Library/DatFiles/DatFile.cs +++ b/SabreTools.Library/DatFiles/DatFile.cs @@ -4720,8 +4720,9 @@ namespace SabreTools.Library.DatFiles /// Second extension to split on (Extension Split only) /// True if short filenames should be used, false otherwise (Level Split only) /// True if original filenames should be used as the base for output filename, false otherwise (Level Split only) + /// Long value representing the split point (Size Split only) public void DetermineSplitType(List inputs, string outDir, bool inplace, SplittingMode splittingMode, - List exta, List extb, bool shortname, bool basedat) + List exta, List extb, bool shortname, bool basedat, long radix) { // If we somehow have the "none" split type, return if (splittingMode == SplittingMode.None) @@ -4754,6 +4755,10 @@ namespace SabreTools.Library.DatFiles { SplitByLevel(outDir, shortname, basedat); } + if ((splittingMode & SplittingMode.Size) != 0) + { + SplitBySize(outDir, radix); + } if ((splittingMode & SplittingMode.Type) != 0) { SplitByType(outDir); @@ -5212,7 +5217,94 @@ namespace SabreTools.Library.DatFiles } /// - /// Split a DAT by type of Rom + /// Split a DAT by size of Rom + /// + /// Name of the directory to write the DATs out to + /// Long value representing the split point + /// True if split succeeded, false otherwise + public bool SplitBySize(string outDir, long radix) + { + // Create each of the respective output DATs + Globals.Logger.User("Creating and populating new DATs"); + DatFile lessDat = new DatFile + { + FileName = this.FileName + " (less than " + radix + " )", + Name = this.Name + " (less than " + radix + " )", + Description = this.Description + " (less than " + radix + " )", + Category = this.Category, + Version = this.Version, + Date = this.Date, + Author = this.Author, + Email = this.Email, + Homepage = this.Homepage, + Url = this.Url, + Comment = this.Comment, + Header = this.Header, + Type = this.Type, + ForceMerging = this.ForceMerging, + ForceNodump = this.ForceNodump, + ForcePacking = this.ForcePacking, + DatFormat = this.DatFormat, + DedupeRoms = this.DedupeRoms, + }; + DatFile greaterEqualDat = new DatFile + { + FileName = this.FileName + " (equal-greater than " + radix + " )", + Name = this.Name + " (equal-greater than " + radix + " )", + Description = this.Description + " (equal-greater than " + radix + " )", + Category = this.Category, + Version = this.Version, + Date = this.Date, + Author = this.Author, + Email = this.Email, + Homepage = this.Homepage, + Url = this.Url, + Comment = this.Comment, + Header = this.Header, + Type = this.Type, + ForceMerging = this.ForceMerging, + ForceNodump = this.ForceNodump, + ForcePacking = this.ForcePacking, + DatFormat = this.DatFormat, + DedupeRoms = this.DedupeRoms, + }; + + // Now populate each of the DAT objects in turn + List keys = Keys; + Parallel.ForEach(keys, Globals.ParallelOptions, key => + { + List items = this[key]; + foreach (DatItem item in items) + { + // If the file is not a Rom, it automatically goes in the "lesser" dat + if (item.Type != ItemType.Rom) + { + lessDat.Add(key, item); + } + // If the file is a Rom and less than the radix, put it in the "lesser" dat + else if (item.Type == ItemType.Rom && ((Rom)item).Size < radix) + { + lessDat.Add(key, item); + } + // If the file is a Rom and greater than or equal to the radix, put it in the "greater" dat + else if (item.Type == ItemType.Rom && ((Rom)item).Size >= radix) + { + greaterEqualDat.Add(key, item); + } + } + }); + + // Now, output all of the files to the output directory + Globals.Logger.User("DAT information created, outputting new files"); + bool success = true; + success &= lessDat.Write(outDir); + success &= greaterEqualDat.Write(outDir); + + return success; + } + + /// + /// Split a DAT by type of DatItem /// /// Name of the directory to write the DATs out to /// True if split succeeded, false otherwise diff --git a/SabreTools.Library/Data/Flags.cs b/SabreTools.Library/Data/Flags.cs index a3b81d7c..e9e21777 100644 --- a/SabreTools.Library/Data/Flags.cs +++ b/SabreTools.Library/Data/Flags.cs @@ -287,6 +287,7 @@ namespace SabreTools.Library.Data Hash = Extension << 1, Level = Hash << 1, Type = Level << 1, + Size = Type << 1, } /// diff --git a/SabreTools.Library/README.1ST b/SabreTools.Library/README.1ST index 434a3940..9a2c292b 100644 --- a/SabreTools.Library/README.1ST +++ b/SabreTools.Library/README.1ST @@ -531,6 +531,15 @@ Options: the format of "Original Name (Dir - Name)". This can be used in conjunction with --short to output in the format of "Original Name (Name)" instead. + + -szs, --size Split DAT(s) or folder by file sizes + For a DAT, or set of DATs, allow for splitting based on the sizes + of the files, specificially if the type is a rom (disks don't have + sizes) + + -rad, --radix Set the midpoint to split at + Set the size at which all roms less than the size are put in the + first DAT, and everything greater than or equal goes in the second -ts, --type Split DAT(s) or folder by file types (rom/disk) For a DAT, or set of DATs, allow for splitting based on the types of diff --git a/SabreTools/SabreTools.Help.cs b/SabreTools/SabreTools.Help.cs index 3fe00b89..45b6b43a 100644 --- a/SabreTools/SabreTools.Help.cs +++ b/SabreTools/SabreTools.Help.cs @@ -896,6 +896,17 @@ namespace SabreTools null); } } + private static Feature sizeFlag + { + get + { + return new Feature( + new List() { "-szs", "--size" }, + "Split DAT(s) or folder by file sizes", + FeatureType.Flag, + null); + } + } private static Feature skipFirstOutputFlag { get @@ -1280,6 +1291,17 @@ namespace SabreTools #region Private Int64 features + private static Feature radixInt64Input + { + get + { + return new Feature( + new List() { "-rad", "--radix" }, + "Set the midpoint to split at", + FeatureType.Int64, + null); + } + } #endregion @@ -2095,6 +2117,8 @@ namespace SabreTools split.AddFeature("level", levelFlag); split["level"].AddFeature("short", shortFlag); split["level"].AddFeature("base", baseFlag); + split.AddFeature("size", sizeFlag); + split["size"].AddFeature("radix", radixInt64Input); split.AddFeature("type", typeFlag); #endregion diff --git a/SabreTools/SabreTools.Inits.cs b/SabreTools/SabreTools.Inits.cs index 50dcb60f..0602e087 100644 --- a/SabreTools/SabreTools.Inits.cs +++ b/SabreTools/SabreTools.Inits.cs @@ -189,12 +189,13 @@ namespace SabreTools /// Second extension to split on (Extension Split only) /// True if short filenames should be used, false otherwise (Level Split only) /// True if original filenames should be used as the base for output filename, false otherwise (Level Split only) + /// Long value representing the split point (Size Split only) private static void InitSplit(List inputs, string outDir, bool inplace, DatFormat datFormat, - SplittingMode splittingMode, List exta, List extb, bool shortname, bool basedat) + SplittingMode splittingMode, List exta, List extb, bool shortname, bool basedat, long radix) { DatFile datfile = new DatFile(); datfile.DatFormat = datFormat; - datfile.DetermineSplitType(inputs, outDir, inplace, splittingMode, exta, extb, shortname, basedat); + datfile.DetermineSplitType(inputs, outDir, inplace, splittingMode, exta, extb, shortname, basedat, radix); } /// diff --git a/SabreTools/SabreTools.cs b/SabreTools/SabreTools.cs index 9ffc6a82..1f699f79 100644 --- a/SabreTools/SabreTools.cs +++ b/SabreTools/SabreTools.cs @@ -109,6 +109,7 @@ namespace SabreTools rar = 1, sevenzip = 1, zip = 1; + long radix = 0; string outDir = null, tempDir = ""; DatHeader datHeader = new DatHeader(); @@ -421,6 +422,9 @@ namespace SabreTools case "short": shortname = true; break; + case "size": + splittingMode |= SplittingMode.Size; + break; case "skip-archives": skipFileType = SkipFileType.Archive; break; @@ -540,6 +544,10 @@ namespace SabreTools #region User Int64 Inputs + case "radix": + radix = (long)feat.Value.GetValue() == Int64.MinValue ? (long)feat.Value.GetValue() : 0; + break; + #endregion #region User List Inputs @@ -755,7 +763,7 @@ namespace SabreTools // Split a DAT by the split type case "Split": VerifyInputs(inputs, feature); - InitSplit(inputs, outDir, inplace, datHeader.DatFormat, splittingMode, exta, extb, shortname, basedat); + InitSplit(inputs, outDir, inplace, datHeader.DatFormat, splittingMode, exta, extb, shortname, basedat, radix); break; // Get statistics on input files case "Stats":