diff --git a/SabreTools.Library/DatFiles/DatFile.cs b/SabreTools.Library/DatFiles/DatFile.cs
index a4038d9b..aa66538a 100644
--- a/SabreTools.Library/DatFiles/DatFile.cs
+++ b/SabreTools.Library/DatFiles/DatFile.cs
@@ -295,31 +295,6 @@ namespace SabreTools.Library.DatFiles
}
}
- ///
- /// Fill a DatFile with all items with a particular source index ID
- ///
- /// DatFile to add found items to
- /// Source index ID to retrieve items for
- /// DatFile containing all items with the source index ID/returns>
- public void FillWithSourceIndex(DatFile indexDat, int index)
- {
- // Loop through and add the items for this index to the output
- Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key =>
- {
- List items = DatItem.Merge(Items[key]);
-
- // If the rom list is empty or null, just skip it
- if (items == null || items.Count == 0)
- return;
-
- foreach (DatItem item in items)
- {
- if (item.Source.Index == index)
- indexDat.Items.Add(key, item);
- }
- });
- }
-
///
/// Output diffs against a base set represented by the current DAT
///
@@ -625,6 +600,56 @@ namespace SabreTools.Library.DatFiles
return outerDiffData;
}
+ ///
+ /// Fill a DatFile with all items with a particular ItemType
+ ///
+ /// DatFile to add found items to
+ /// ItemType to retrieve items for
+ /// DatFile containing all items with the ItemType/returns>
+ public void FillWithItemType(DatFile indexDat, ItemType itemType)
+ {
+ // Loop through and add the items for this index to the output
+ Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key =>
+ {
+ List items = DatItem.Merge(Items[key]);
+
+ // If the rom list is empty or null, just skip it
+ if (items == null || items.Count == 0)
+ return;
+
+ foreach (DatItem item in items)
+ {
+ if (item.ItemType == itemType)
+ indexDat.Items.Add(key, item);
+ }
+ });
+ }
+
+ ///
+ /// Fill a DatFile with all items with a particular source index ID
+ ///
+ /// DatFile to add found items to
+ /// Source index ID to retrieve items for
+ /// DatFile containing all items with the source index ID/returns>
+ public void FillWithSourceIndex(DatFile indexDat, int index)
+ {
+ // Loop through and add the items for this index to the output
+ Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key =>
+ {
+ List items = DatItem.Merge(Items[key]);
+
+ // If the rom list is empty or null, just skip it
+ if (items == null || items.Count == 0)
+ return;
+
+ foreach (DatItem item in items)
+ {
+ if (item.Source.Index == index)
+ indexDat.Items.Add(key, item);
+ }
+ });
+ }
+
///
/// Populate from multiple paths while returning the invividual headers
///
@@ -1868,6 +1893,7 @@ namespace SabreTools.Library.DatFiles
#endregion
+ // TODO: See if any of the helper methods can be broken up a bit more neatly
#region Populate DAT from Directory
///
@@ -2223,6 +2249,7 @@ namespace SabreTools.Library.DatFiles
#endregion
+ // TODO: See if any of the helper methods can be broken up a bit more neatly
#region Rebuilding and Verifying
///
@@ -3032,15 +3059,14 @@ namespace SabreTools.Library.DatFiles
///
/// Split a DAT by input extensions
///
- /// Name of the directory to write the DATs out to
/// List of extensions to split on (first DAT)
/// List of extensions to split on (second DAT)
- /// True if split succeeded, false otherwise
- public bool SplitByExtension(string outDir, List extA, List extB)
+ /// Extension Set A and Extension Set B DatFiles
+ public (DatFile extADat, DatFile extBDat) SplitByExtension(List extA, List extB)
{
// If roms is empty, return false
if (Items.TotalCount == 0)
- return false;
+ return (null, null);
// Make sure all of the extensions don't have a dot at the beginning
var newExtA = extA.Select(s => s.TrimStart('.').ToLowerInvariant());
@@ -3050,15 +3076,15 @@ namespace SabreTools.Library.DatFiles
string newExtBString = string.Join(",", newExtB);
// Set all of the appropriate outputs for each of the subsets
- DatFile datdataA = Create(Header.CloneStandard());
- datdataA.Header.FileName += $" ({newExtAString})";
- datdataA.Header.Name += $" ({newExtAString})";
- datdataA.Header.Description += $" ({newExtAString})";
+ DatFile extADat = Create(Header.CloneStandard());
+ extADat.Header.FileName += $" ({newExtAString})";
+ extADat.Header.Name += $" ({newExtAString})";
+ extADat.Header.Description += $" ({newExtAString})";
- DatFile datdataB = Create(Header.CloneStandard());
- datdataB.Header.FileName += $" ({newExtBString})";
- datdataB.Header.Name += $" ({newExtBString})";
- datdataB.Header.Description += $" ({newExtBString})";
+ DatFile extBDat = Create(Header.CloneStandard());
+ extBDat.Header.FileName += $" ({newExtBString})";
+ extBDat.Header.Name += $" ({newExtBString})";
+ extBDat.Header.Description += $" ({newExtBString})";
// Now separate the roms accordingly
Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key =>
@@ -3068,25 +3094,22 @@ namespace SabreTools.Library.DatFiles
{
if (newExtA.Contains(PathExtensions.GetNormalizedExtension(item.Name)))
{
- datdataA.Items.Add(key, item);
+ extADat.Items.Add(key, item);
}
else if (newExtB.Contains(PathExtensions.GetNormalizedExtension(item.Name)))
{
- datdataB.Items.Add(key, item);
+ extBDat.Items.Add(key, item);
}
else
{
- datdataA.Items.Add(key, item);
- datdataB.Items.Add(key, item);
+ extADat.Items.Add(key, item);
+ extBDat.Items.Add(key, item);
}
}
});
- // Then write out both files
- bool success = datdataA.Write(outDir);
- success &= datdataB.Write(outDir);
-
- return success;
+ // Then return both DatFiles
+ return (extADat, extBDat);
}
///
@@ -3094,6 +3117,7 @@ namespace SabreTools.Library.DatFiles
///
/// Name of the directory to write the DATs out to
/// True if split succeeded, false otherwise
+ /// TODO: Can this follow the same pattern as type split?
public bool SplitByHash(string outDir)
{
// Create each of the respective output DATs
@@ -3333,23 +3357,22 @@ namespace SabreTools.Library.DatFiles
///
/// 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)
+ /// Less Than and Greater Than DatFiles
+ public (DatFile lessThan, DatFile greaterThan) SplitBySize(long radix)
{
// Create each of the respective output DATs
Globals.Logger.User("Creating and populating new DATs");
- DatFile lessDat = Create(Header.CloneStandard());
- lessDat.Header.FileName += $" (less than {radix})";
- lessDat.Header.Name += $" (less than {radix})";
- lessDat.Header.Description += $" (less than {radix})";
+ DatFile lessThan = Create(Header.CloneStandard());
+ lessThan.Header.FileName += $" (less than {radix})";
+ lessThan.Header.Name += $" (less than {radix})";
+ lessThan.Header.Description += $" (less than {radix})";
- DatFile greaterEqualDat = Create(Header.CloneStandard());
- greaterEqualDat.Header.FileName += $" (equal-greater than {radix})";
- greaterEqualDat.Header.Name += $" (equal-greater than {radix})";
- greaterEqualDat.Header.Description += $" (equal-greater than {radix})";
+ DatFile greaterThan = Create(Header.CloneStandard());
+ greaterThan.Header.FileName += $" (equal-greater than {radix})";
+ greaterThan.Header.Name += $" (equal-greater than {radix})";
+ greaterThan.Header.Description += $" (equal-greater than {radix})";
// Now populate each of the DAT objects in turn
Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key =>
@@ -3359,90 +3382,59 @@ namespace SabreTools.Library.DatFiles
{
// If the file is not a Rom, it automatically goes in the "lesser" dat
if (item.ItemType != ItemType.Rom)
- lessDat.Items.Add(key, item);
+ lessThan.Items.Add(key, item);
// If the file is a Rom and less than the radix, put it in the "lesser" dat
else if (item.ItemType == ItemType.Rom && (item as Rom).Size < radix)
- lessDat.Items.Add(key, item);
+ lessThan.Items.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.ItemType == ItemType.Rom && (item as Rom).Size >= radix)
- greaterEqualDat.Items.Add(key, item);
+ greaterThan.Items.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;
+ // Then return both DatFiles
+ return (lessThan, greaterThan);
}
///
/// Split a DAT by type of DatItem
///
- /// Name of the directory to write the DATs out to
- /// True if split succeeded, false otherwise
- public bool SplitByType(string outDir)
+ /// Dictionary of ItemType to DatFile mappings
+ public Dictionary SplitByType()
{
// Create each of the respective output DATs
Globals.Logger.User("Creating and populating new DATs");
- DatFile diskdat = Create(Header.CloneStandard());
- diskdat.Header.FileName += " (Disk)";
- diskdat.Header.Name += " (Disk)";
- diskdat.Header.Description += " (Disk)";
+ // Create the set of type-to-dat mappings
+ Dictionary typeDats = new Dictionary();
- DatFile mediadat = Create(Header.CloneStandard());
- mediadat.Header.FileName += " (Media)";
- mediadat.Header.Name += " (Media)";
- mediadat.Header.Description += " (Media)";
+ // We only care about a subset of types
+ List outputTypes = new List
+ {
+ ItemType.Disk,
+ ItemType.Media,
+ ItemType.Rom,
+ ItemType.Sample,
+ };
- DatFile romdat = Create(Header.CloneStandard());
- romdat.Header.FileName += " (Rom)";
- romdat.Header.Name += " (Rom)";
- romdat.Header.Description += " (Rom)";
-
- DatFile sampledat = Create(Header.CloneStandard());
- sampledat.Header.FileName += " (Sample)";
- sampledat.Header.Name += " (Sample)";
- sampledat.Header.Description += " (Sample)";
+ // Setup all of the DatFiles
+ foreach (ItemType itemType in outputTypes)
+ {
+ typeDats[itemType] = Create(Header.CloneStandard());
+ typeDats[itemType].Header.FileName += $" ({itemType})";
+ typeDats[itemType].Header.Name += $" ({itemType})";
+ typeDats[itemType].Header.Description += $" ({itemType})";
+ }
// Now populate each of the DAT objects in turn
- Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key =>
+ Parallel.ForEach(outputTypes, Globals.ParallelOptions, itemType =>
{
- List items = Items[key];
- foreach (DatItem item in items)
- {
- // If the file is a Disk
- if (item.ItemType == ItemType.Disk)
- diskdat.Items.Add(key, item);
-
- // If the file is a Media
- else if (item.ItemType == ItemType.Media)
- mediadat.Items.Add(key, item);
-
- // If the file is a Rom
- else if (item.ItemType == ItemType.Rom)
- romdat.Items.Add(key, item);
-
- // If the file is a Sample
- else if (item.ItemType == ItemType.Sample)
- sampledat.Items.Add(key, item);
- }
+ FillWithItemType(typeDats[itemType], itemType);
});
- // Now, output all of the files to the output directory
- Globals.Logger.User("DAT information created, outputting new files");
- bool success = true;
- success &= diskdat.Write(outDir);
- success &= mediadat.Write(outDir);
- success &= romdat.Write(outDir);
- success &= sampledat.Write(outDir);
-
- return success;
+ return typeDats;
}
#endregion
diff --git a/SabreTools/Features/Split.cs b/SabreTools/Features/Split.cs
index 5e76a39f..7347dca1 100644
--- a/SabreTools/Features/Split.cs
+++ b/SabreTools/Features/Split.cs
@@ -1,9 +1,12 @@
using System.Collections.Generic;
+using System.Threading.Tasks;
using SabreTools.Library.Data;
using SabreTools.Library.DatFiles;
+using SabreTools.Library.DatItems;
using SabreTools.Library.Help;
using SabreTools.Library.IO;
+using SabreTools.Library.Tools;
namespace SabreTools.Features
{
@@ -61,10 +64,15 @@ namespace SabreTools.Features
// Extension splitting
if (splittingMode.HasFlag(SplittingMode.Extension))
{
- internalDat.SplitByExtension(
- OutputDir,
- GetList(features, ExtAListValue),
- GetList(features, ExtBListValue));
+ (DatFile extADat, DatFile extBDat) = internalDat.SplitByExtension(GetList(features, ExtAListValue), GetList(features, ExtBListValue));
+
+ InternalStopwatch watch = new InternalStopwatch("Outputting extension-split DATs");
+
+ // Output both possible DatFiles
+ extADat.Write(OutputDir);
+ extBDat.Write(OutputDir);
+
+ watch.Stop();
}
// Hash splitting
@@ -83,11 +91,33 @@ namespace SabreTools.Features
// Size splitting
if (splittingMode.HasFlag(SplittingMode.Size))
- internalDat.SplitBySize(OutputDir, GetInt64(features, RadixInt64Value));
+ {
+ (DatFile lessThan, DatFile greaterThan) = internalDat.SplitBySize(GetInt64(features, RadixInt64Value));
+
+ InternalStopwatch watch = new InternalStopwatch("Outputting size-split DATs");
+
+ // Output both possible DatFiles
+ lessThan.Write(OutputDir);
+ greaterThan.Write(OutputDir);
+
+ watch.Stop();
+ }
// Type splitting
if (splittingMode.HasFlag(SplittingMode.Type))
- internalDat.SplitByType(OutputDir);
+ {
+ Dictionary typeDats = internalDat.SplitByType();
+
+ InternalStopwatch watch = new InternalStopwatch("Outputting ItemType DATs");
+
+ // Loop through each type DatFile
+ Parallel.ForEach(typeDats.Keys, Globals.ParallelOptions, itemType =>
+ {
+ typeDats[itemType].Write(OutputDir);
+ });
+
+ watch.Stop();
+ }
}
}
}
diff --git a/SabreTools/Features/Update.cs b/SabreTools/Features/Update.cs
index e828d1ac..d242e72f 100644
--- a/SabreTools/Features/Update.cs
+++ b/SabreTools/Features/Update.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
+
using SabreTools.Library.Data;
using SabreTools.Library.DatFiles;
using SabreTools.Library.DatItems;