2020-07-31 23:17:12 -07:00
using System ;
using System.Collections.Generic ;
2020-08-27 21:40:08 -07:00
using System.IO ;
2020-08-27 22:19:31 -07:00
using System.Threading.Tasks ;
2020-12-08 13:23:59 -08:00
using SabreTools.Core ;
2020-12-08 16:37:08 -08:00
using SabreTools.DatFiles ;
2020-12-10 23:24:09 -08:00
using SabreTools.DatTools ;
2020-12-07 13:57:26 -08:00
using SabreTools.Help ;
2020-12-07 15:08:57 -08:00
using SabreTools.IO ;
2020-12-08 11:09:05 -08:00
using SabreTools.Logging ;
2020-07-31 23:17:12 -07:00
namespace SabreTools.Features
{
internal class Update : BaseFeature
{
public const string Value = "Update" ;
public Update ( )
{
Name = Value ;
2021-02-17 15:53:07 -08:00
Flags = new List < string > ( ) { "ud" , "update" } ;
2020-07-31 23:17:12 -07:00
Description = "Update and manipulate DAT(s)" ;
2020-12-07 13:57:26 -08:00
_featureType = ParameterType . Flag ;
2020-07-31 23:17:12 -07:00
LongDescription = "This is the multitool part of the program, allowing for almost every manipulation to a DAT, or set of DATs. This is also a combination of many different programs that performed DAT manipulation that work better together." ;
2020-12-07 13:57:26 -08:00
Features = new Dictionary < string , Help . Feature > ( ) ;
2020-07-31 23:17:12 -07:00
2021-02-03 10:48:23 -08:00
// Common Features
AddCommonFeatures ( ) ;
2020-07-31 23:17:12 -07:00
// Output Formats
AddFeature ( OutputTypeListInput ) ;
2024-03-05 20:26:38 -05:00
this [ OutputTypeListInput ] ! . AddFeature ( PrefixStringInput ) ;
this [ OutputTypeListInput ] ! . AddFeature ( PostfixStringInput ) ;
this [ OutputTypeListInput ] ! . AddFeature ( QuotesFlag ) ;
this [ OutputTypeListInput ] ! . AddFeature ( RomsFlag ) ;
this [ OutputTypeListInput ] ! . AddFeature ( GamePrefixFlag ) ;
this [ OutputTypeListInput ] ! . AddFeature ( AddExtensionStringInput ) ;
this [ OutputTypeListInput ] ! . AddFeature ( ReplaceExtensionStringInput ) ;
this [ OutputTypeListInput ] ! . AddFeature ( RemoveExtensionsFlag ) ;
this [ OutputTypeListInput ] ! . AddFeature ( RombaFlag ) ;
this [ OutputTypeListInput ] [ RombaFlag ] ! . AddFeature ( RombaDepthInt32Input ) ;
this [ OutputTypeListInput ] ! . AddFeature ( DeprecatedFlag ) ;
2020-07-31 23:17:12 -07:00
AddHeaderFeatures ( ) ;
AddFeature ( KeepEmptyGamesFlag ) ;
AddFeature ( CleanFlag ) ;
AddFeature ( RemoveUnicodeFlag ) ;
AddFeature ( DescriptionAsNameFlag ) ;
AddInternalSplitFeatures ( ) ;
AddFeature ( TrimFlag ) ;
2024-03-05 20:26:38 -05:00
this [ TrimFlag ] ! . AddFeature ( RootDirStringInput ) ;
2020-07-31 23:17:12 -07:00
AddFeature ( SingleSetFlag ) ;
AddFeature ( DedupFlag ) ;
AddFeature ( GameDedupFlag ) ;
AddFeature ( MergeFlag ) ;
2024-03-05 20:26:38 -05:00
this [ MergeFlag ] ! . AddFeature ( NoAutomaticDateFlag ) ;
2020-07-31 23:17:12 -07:00
AddFeature ( DiffAllFlag ) ;
2024-03-05 20:26:38 -05:00
this [ DiffAllFlag ] ! . AddFeature ( NoAutomaticDateFlag ) ;
2020-07-31 23:17:12 -07:00
AddFeature ( DiffDuplicatesFlag ) ;
2024-03-05 20:26:38 -05:00
this [ DiffDuplicatesFlag ] ! . AddFeature ( NoAutomaticDateFlag ) ;
2020-07-31 23:17:12 -07:00
AddFeature ( DiffIndividualsFlag ) ;
2024-03-05 20:26:38 -05:00
this [ DiffIndividualsFlag ] ! . AddFeature ( NoAutomaticDateFlag ) ;
2020-07-31 23:17:12 -07:00
AddFeature ( DiffNoDuplicatesFlag ) ;
2024-03-05 20:26:38 -05:00
this [ DiffNoDuplicatesFlag ] ! . AddFeature ( NoAutomaticDateFlag ) ;
2020-07-31 23:17:12 -07:00
AddFeature ( DiffAgainstFlag ) ;
2024-03-05 20:26:38 -05:00
this [ DiffAgainstFlag ] ! . AddFeature ( BaseDatListInput ) ;
this [ DiffAgainstFlag ] ! . AddFeature ( ByGameFlag ) ;
2020-07-31 23:17:12 -07:00
AddFeature ( BaseReplaceFlag ) ;
2024-03-05 20:26:38 -05:00
this [ BaseReplaceFlag ] ! . AddFeature ( BaseDatListInput ) ;
this [ BaseReplaceFlag ] ! . AddFeature ( UpdateFieldListInput ) ;
this [ BaseReplaceFlag ] [ UpdateFieldListInput ] ! . AddFeature ( OnlySameFlag ) ;
2020-07-31 23:17:12 -07:00
AddFeature ( ReverseBaseReplaceFlag ) ;
2024-03-05 20:26:38 -05:00
this [ ReverseBaseReplaceFlag ] ! . AddFeature ( BaseDatListInput ) ;
this [ ReverseBaseReplaceFlag ] ! . AddFeature ( UpdateFieldListInput ) ;
this [ ReverseBaseReplaceFlag ] [ UpdateFieldListInput ] ! . AddFeature ( OnlySameFlag ) ;
2020-07-31 23:17:12 -07:00
AddFeature ( DiffCascadeFlag ) ;
2024-03-05 20:26:38 -05:00
this [ DiffCascadeFlag ] ! . AddFeature ( SkipFirstOutputFlag ) ;
2020-07-31 23:17:12 -07:00
AddFeature ( DiffReverseCascadeFlag ) ;
2024-03-05 20:26:38 -05:00
this [ DiffReverseCascadeFlag ] ! . AddFeature ( SkipFirstOutputFlag ) ;
2020-08-21 10:38:42 -07:00
AddFeature ( ExtraIniListInput ) ;
2020-07-31 23:17:12 -07:00
AddFilteringFeatures ( ) ;
AddFeature ( OutputDirStringInput ) ;
AddFeature ( InplaceFlag ) ;
}
2024-03-05 23:41:00 -05:00
public override bool ProcessFeatures ( Dictionary < string , Feature ? > features )
2020-07-31 23:17:12 -07:00
{
2021-03-19 20:52:11 -07:00
// If the base fails, just fail out
if ( ! base . ProcessFeatures ( features ) )
return false ;
2020-07-31 23:17:12 -07:00
// Get feature flags
2024-03-05 20:07:38 -05:00
var updateMachineFieldNames = GetUpdateMachineFields ( features ) ;
var updateItemFieldNames = GetUpdateDatItemFields ( features ) ;
2020-07-31 23:17:12 -07:00
var updateMode = GetUpdateMode ( features ) ;
// Normalize the extensions
Header . AddExtension = ( string . IsNullOrWhiteSpace ( Header . AddExtension ) | | Header . AddExtension . StartsWith ( "." )
? Header . AddExtension
: $".{Header.AddExtension}" ) ;
Header . ReplaceExtension = ( string . IsNullOrWhiteSpace ( Header . ReplaceExtension ) | | Header . ReplaceExtension . StartsWith ( "." )
? Header . ReplaceExtension
: $".{Header.ReplaceExtension}" ) ;
2021-08-17 12:35:31 -07:00
// If we're in a non-replacement special update mode and the names aren't set, set defaults
if ( updateMode ! = 0
& & ! ( updateMode . HasFlag ( UpdateMode . DiffAgainst ) | | updateMode . HasFlag ( UpdateMode . BaseReplace ) ) )
2020-07-31 23:17:12 -07:00
{
// Get the values that will be used
if ( string . IsNullOrWhiteSpace ( Header . Date ) )
Header . Date = DateTime . Now . ToString ( "yyyy-MM-dd" ) ;
if ( string . IsNullOrWhiteSpace ( Header . Name ) )
{
Header . Name = ( updateMode ! = 0 ? "DiffDAT" : "MergeDAT" )
+ ( Header . Type = = "SuperDAT" ? "-SuperDAT" : string . Empty )
2020-08-30 23:11:05 -07:00
+ ( Cleaner . DedupeRoms ! = DedupeType . None ? "-deduped" : string . Empty ) ;
2020-07-31 23:17:12 -07:00
}
if ( string . IsNullOrWhiteSpace ( Header . Description ) )
{
Header . Description = ( updateMode ! = 0 ? "DiffDAT" : "MergeDAT" )
+ ( Header . Type = = "SuperDAT" ? "-SuperDAT" : string . Empty )
2020-08-30 23:11:05 -07:00
+ ( Cleaner . DedupeRoms ! = DedupeType . None ? " - deduped" : string . Empty ) ;
2020-07-31 23:17:12 -07:00
if ( ! GetBoolean ( features , NoAutomaticDateValue ) )
Header . Description + = $" ({Header.Date})" ;
}
if ( string . IsNullOrWhiteSpace ( Header . Category ) & & updateMode ! = 0 )
Header . Category = "DiffDAT" ;
if ( string . IsNullOrWhiteSpace ( Header . Author ) )
2021-03-22 16:37:29 -07:00
Header . Author = $"SabreTools {Prepare.Version}" ;
if ( string . IsNullOrWhiteSpace ( Header . Comment ) )
Header . Comment = $"Generated by SabreTools {Prepare.Version}" ;
2020-07-31 23:17:12 -07:00
}
// If no update fields are set, default to Names
2024-03-05 20:07:38 -05:00
if ( updateItemFieldNames = = null | | updateItemFieldNames . Count = = 0 )
{
updateItemFieldNames = [ ] ;
updateItemFieldNames [ "item" ] = [ Models . Metadata . Rom . NameKey ] ;
}
2020-07-31 23:17:12 -07:00
2020-08-01 21:42:28 -07:00
// Ensure we only have files in the inputs
2020-12-10 22:16:53 -08:00
List < ParentablePath > inputPaths = PathTool . GetFilesOnly ( Inputs , appendparent : true ) ;
List < ParentablePath > basePaths = PathTool . GetFilesOnly ( GetList ( features , BaseDatListValue ) ) ;
2020-08-01 21:42:28 -07:00
2020-12-18 22:37:33 -08:00
// Ensure the output directory
OutputDir = OutputDir . Ensure ( ) ;
2020-08-01 21:42:28 -07:00
// If we're in standard update mode, run through all of the inputs
if ( updateMode = = UpdateMode . None )
{
2020-08-27 21:40:08 -07:00
// Loop through each input and update
2024-02-28 22:54:56 -05:00
#if NET452_OR_GREATER | | NETCOREAPP
2020-08-27 22:19:31 -07:00
Parallel . ForEach ( inputPaths , Globals . ParallelOptions , inputPath = >
2024-02-28 22:54:56 -05:00
#elif NET40_OR_GREATER
Parallel . ForEach ( inputPaths , inputPath = >
#else
foreach ( var inputPath in inputPaths )
#endif
2020-08-27 21:40:08 -07:00
{
// Create a new base DatFile
DatFile datFile = DatFile . Create ( Header ) ;
2020-10-07 15:42:30 -07:00
logger . User ( $"Processing '{Path.GetFileName(inputPath.CurrentPath)}'" ) ;
2020-12-10 13:53:34 -08:00
Parser . ParseInto ( datFile , inputPath , keep : true ,
2020-08-27 21:40:08 -07:00
keepext : datFile . Header . DatFormat . HasFlag ( DatFormat . TSV )
| | datFile . Header . DatFormat . HasFlag ( DatFormat . CSV )
| | datFile . Header . DatFormat . HasFlag ( DatFormat . SSV ) ) ;
2020-08-28 13:59:42 -07:00
// Perform additional processing steps
2021-02-01 11:43:38 -08:00
Extras . ApplyExtras ( datFile ) ;
2023-04-19 12:04:25 -04:00
Splitter . ApplySplitting ( datFile , useTags : false ) ;
2024-03-05 20:26:38 -05:00
datFile . ExecuteFilters ( FilterRunner ) ;
2021-02-01 11:43:38 -08:00
Cleaner . ApplyCleaning ( datFile ) ;
2021-02-01 12:11:32 -08:00
Remover . ApplyRemovals ( datFile ) ;
2020-08-27 21:40:08 -07:00
// Get the correct output path
string realOutDir = inputPath . GetOutputPath ( OutputDir , GetBoolean ( features , InplaceValue ) ) ;
// Try to output the file, overwriting only if it's not in the current directory
2020-12-10 14:03:07 -08:00
Writer . Write ( datFile , realOutDir , overwrite : GetBoolean ( features , InplaceValue ) ) ;
2024-02-28 21:59:13 -05:00
#if NET40_OR_GREATER | | NETCOREAPP
2020-08-27 22:19:31 -07:00
} ) ;
2024-02-28 21:59:13 -05:00
#else
}
#endif
2020-08-27 21:40:08 -07:00
2021-03-19 20:52:11 -07:00
return true ;
2020-08-01 21:42:28 -07:00
}
// Reverse inputs if we're in a required mode
if ( updateMode . HasFlag ( UpdateMode . DiffReverseCascade ) )
{
updateMode | = UpdateMode . DiffCascade ;
2020-08-27 21:40:08 -07:00
inputPaths . Reverse ( ) ;
2020-08-01 21:42:28 -07:00
}
if ( updateMode . HasFlag ( UpdateMode . ReverseBaseReplace ) )
{
updateMode | = UpdateMode . BaseReplace ;
2020-08-27 21:40:08 -07:00
basePaths . Reverse ( ) ;
2020-08-01 21:42:28 -07:00
}
// Create a DAT to capture inputs
2020-07-31 23:17:12 -07:00
DatFile userInputDat = DatFile . Create ( Header ) ;
2020-08-01 21:42:28 -07:00
// Populate using the correct set
List < DatHeader > datHeaders ;
if ( updateMode . HasFlag ( UpdateMode . DiffAgainst ) | | updateMode . HasFlag ( UpdateMode . BaseReplace ) )
2020-12-13 23:09:24 -08:00
datHeaders = DatFileTool . PopulateUserData ( userInputDat , basePaths ) ;
2020-08-01 21:42:28 -07:00
else
2020-12-13 23:09:24 -08:00
datHeaders = DatFileTool . PopulateUserData ( userInputDat , inputPaths ) ;
2020-08-27 21:46:19 -07:00
2020-08-28 13:59:42 -07:00
// Perform additional processing steps
2021-02-01 11:43:38 -08:00
Extras . ApplyExtras ( userInputDat ) ;
2023-04-19 12:04:25 -04:00
Splitter . ApplySplitting ( userInputDat , useTags : false ) ;
2024-03-05 20:26:38 -05:00
userInputDat . ExecuteFilters ( FilterRunner ) ;
2021-02-01 11:43:38 -08:00
Cleaner . ApplyCleaning ( userInputDat ) ;
2021-02-01 12:11:32 -08:00
Remover . ApplyRemovals ( userInputDat ) ;
2020-08-01 21:42:28 -07:00
// Output only DatItems that are duplicated across inputs
if ( updateMode . HasFlag ( UpdateMode . DiffDupesOnly ) )
2020-08-27 22:27:23 -07:00
{
2020-12-13 23:09:24 -08:00
DatFile dupeData = DatFileTool . DiffDuplicates ( userInputDat , inputPaths ) ;
2020-08-27 22:27:23 -07:00
2023-04-19 16:39:58 -04:00
InternalStopwatch watch = new ( "Outputting duplicate DAT" ) ;
2020-12-10 14:03:07 -08:00
Writer . Write ( dupeData , OutputDir , overwrite : false ) ;
2020-08-27 22:27:23 -07:00
watch . Stop ( ) ;
}
2020-08-01 21:42:28 -07:00
// Output only DatItems that are not duplicated across inputs
if ( updateMode . HasFlag ( UpdateMode . DiffNoDupesOnly ) )
2020-08-27 22:27:23 -07:00
{
2020-12-13 23:09:24 -08:00
DatFile outerDiffData = DatFileTool . DiffNoDuplicates ( userInputDat , inputPaths ) ;
2020-08-27 22:27:23 -07:00
2023-04-19 16:39:58 -04:00
InternalStopwatch watch = new ( "Outputting no duplicate DAT" ) ;
2020-12-10 14:03:07 -08:00
Writer . Write ( outerDiffData , OutputDir , overwrite : false ) ;
2020-08-27 22:27:23 -07:00
watch . Stop ( ) ;
}
2020-08-01 21:42:28 -07:00
// Output only DatItems that are unique to each input
if ( updateMode . HasFlag ( UpdateMode . DiffIndividualsOnly ) )
2020-08-27 22:27:23 -07:00
{
// Get all of the output DatFiles
2020-12-13 23:09:24 -08:00
List < DatFile > datFiles = DatFileTool . DiffIndividuals ( userInputDat , inputPaths ) ;
2020-08-27 22:27:23 -07:00
// Loop through and output the new DatFiles
2023-04-19 16:39:58 -04:00
InternalStopwatch watch = new ( "Outputting all individual DATs" ) ;
2020-08-27 22:27:23 -07:00
2024-02-28 22:54:56 -05:00
#if NET452_OR_GREATER | | NETCOREAPP
2020-08-27 22:27:23 -07:00
Parallel . For ( 0 , inputPaths . Count , Globals . ParallelOptions , j = >
2024-02-28 22:54:56 -05:00
#elif NET40_OR_GREATER
Parallel . For ( 0 , inputPaths . Count , j = >
#else
for ( int j = 0 ; j < inputPaths . Count ; j + + )
#endif
2020-08-27 22:27:23 -07:00
{
string path = inputPaths [ j ] . GetOutputPath ( OutputDir , GetBoolean ( features , InplaceValue ) ) ;
// Try to output the file
2020-12-10 14:03:07 -08:00
Writer . Write ( datFiles [ j ] , path , overwrite : GetBoolean ( features , InplaceValue ) ) ;
2024-02-28 22:54:56 -05:00
#if NET40_OR_GREATER | | NETCOREAPP
2020-08-27 22:27:23 -07:00
} ) ;
2024-02-28 22:54:56 -05:00
#else
}
#endif
2020-08-27 22:27:23 -07:00
watch . Stop ( ) ;
}
2020-08-01 21:42:28 -07:00
// Output cascaded diffs
if ( updateMode . HasFlag ( UpdateMode . DiffCascade ) )
{
2020-08-27 22:19:31 -07:00
// Preprocess the DatHeaders
2024-02-28 22:54:56 -05:00
#if NET452_OR_GREATER | | NETCOREAPP
2020-08-27 22:19:31 -07:00
Parallel . For ( 0 , datHeaders . Count , Globals . ParallelOptions , j = >
2024-02-28 22:54:56 -05:00
#elif NET40_OR_GREATER
Parallel . For ( 0 , datHeaders . Count , j = >
#else
for ( int j = 0 ; j < datHeaders . Count ; j + + )
#endif
2020-08-27 22:19:31 -07:00
{
// If we're outputting to the runtime folder, rename
if ( ! GetBoolean ( features , InplaceValue ) & & OutputDir = = Environment . CurrentDirectory )
{
string innerpost = $" ({j} - {inputPaths[j].GetNormalizedFileName(true)} Only)" ;
datHeaders [ j ] = userInputDat . Header ;
datHeaders [ j ] . FileName + = innerpost ;
datHeaders [ j ] . Name + = innerpost ;
datHeaders [ j ] . Description + = innerpost ;
}
2024-02-28 22:54:56 -05:00
#if NET40_OR_GREATER | | NETCOREAPP
2020-08-27 22:19:31 -07:00
} ) ;
2024-02-28 22:54:56 -05:00
#else
}
#endif
2020-08-27 22:19:31 -07:00
// Get all of the output DatFiles
2020-12-13 23:09:24 -08:00
List < DatFile > datFiles = DatFileTool . DiffCascade ( userInputDat , datHeaders ) ;
2020-08-27 22:19:31 -07:00
// Loop through and output the new DatFiles
2023-04-19 16:39:58 -04:00
InternalStopwatch watch = new ( "Outputting all created DATs" ) ;
2020-08-27 22:19:31 -07:00
int startIndex = GetBoolean ( features , SkipFirstOutputValue ) ? 1 : 0 ;
2024-02-28 22:54:56 -05:00
#if NET452_OR_GREATER | | NETCOREAPP
2020-08-27 22:19:31 -07:00
Parallel . For ( startIndex , inputPaths . Count , Globals . ParallelOptions , j = >
2024-02-28 22:54:56 -05:00
#elif NET40_OR_GREATER
Parallel . For ( startIndex , inputPaths . Count , j = >
#else
for ( int j = startIndex ; j < inputPaths . Count ; j + + )
#endif
2020-08-27 22:19:31 -07:00
{
string path = inputPaths [ j ] . GetOutputPath ( OutputDir , GetBoolean ( features , InplaceValue ) ) ;
// Try to output the file
2020-12-10 14:03:07 -08:00
Writer . Write ( datFiles [ j ] , path , overwrite : GetBoolean ( features , InplaceValue ) ) ;
2024-02-28 22:54:56 -05:00
#if NET40_OR_GREATER | | NETCOREAPP
2020-08-27 22:19:31 -07:00
} ) ;
2024-02-28 22:54:56 -05:00
#else
}
#endif
2020-08-27 22:19:31 -07:00
watch . Stop ( ) ;
2020-08-01 21:42:28 -07:00
}
// Output differences against a base DAT
if ( updateMode . HasFlag ( UpdateMode . DiffAgainst ) )
{
2020-08-27 21:40:08 -07:00
// Loop through each input and diff against the base
2024-02-28 22:54:56 -05:00
#if NET452_OR_GREATER | | NETCOREAPP
2020-08-27 22:19:31 -07:00
Parallel . ForEach ( inputPaths , Globals . ParallelOptions , inputPath = >
2024-02-28 22:54:56 -05:00
#elif NET40_OR_GREATER
Parallel . ForEach ( inputPaths , inputPath = >
#else
foreach ( var inputPath in inputPaths )
#endif
2020-08-27 21:40:08 -07:00
{
2020-08-28 13:59:42 -07:00
// Parse the path to a new DatFile
2021-08-17 12:35:31 -07:00
DatFile repDat = DatFile . Create ( Header ) ;
2020-12-10 13:53:34 -08:00
Parser . ParseInto ( repDat , inputPath , indexId : 1 , keep : true ) ;
2020-08-28 13:59:42 -07:00
// Perform additional processing steps
2021-02-01 11:43:38 -08:00
Extras . ApplyExtras ( repDat ) ;
2023-04-19 12:04:25 -04:00
Splitter . ApplySplitting ( repDat , useTags : false ) ;
2024-03-05 20:26:38 -05:00
repDat . ExecuteFilters ( FilterRunner ) ;
2021-02-01 11:43:38 -08:00
Cleaner . ApplyCleaning ( repDat ) ;
2021-02-01 12:11:32 -08:00
Remover . ApplyRemovals ( repDat ) ;
2020-08-27 21:40:08 -07:00
// Now replace the fields from the base DatFile
2020-12-13 23:09:24 -08:00
DatFileTool . DiffAgainst ( userInputDat , repDat , GetBoolean ( Features , ByGameValue ) ) ;
2020-08-27 21:40:08 -07:00
// Finally output the diffed DatFile
string interOutDir = inputPath . GetOutputPath ( OutputDir , GetBoolean ( features , InplaceValue ) ) ;
2020-12-10 14:03:07 -08:00
Writer . Write ( repDat , interOutDir , overwrite : GetBoolean ( features , InplaceValue ) ) ;
2024-02-28 21:59:13 -05:00
#if NET40_OR_GREATER | | NETCOREAPP
2020-08-27 22:19:31 -07:00
} ) ;
2024-02-28 21:59:13 -05:00
#else
}
#endif
2020-08-01 21:42:28 -07:00
}
2020-08-27 21:40:08 -07:00
// Output DATs after replacing fields from a base DatFile
2020-08-01 21:42:28 -07:00
if ( updateMode . HasFlag ( UpdateMode . BaseReplace ) )
{
2020-08-27 21:40:08 -07:00
// Loop through each input and apply the base DatFile
2024-02-28 22:54:56 -05:00
#if NET452_OR_GREATER | | NETCOREAPP
2020-08-27 22:19:31 -07:00
Parallel . ForEach ( inputPaths , Globals . ParallelOptions , inputPath = >
2024-02-28 22:54:56 -05:00
#elif NET40_OR_GREATER
Parallel . ForEach ( inputPaths , inputPath = >
#else
foreach ( var inputPath in inputPaths )
#endif
2020-08-27 21:40:08 -07:00
{
2020-08-28 13:59:42 -07:00
// Parse the path to a new DatFile
2021-08-17 12:35:31 -07:00
DatFile repDat = DatFile . Create ( Header ) ;
2020-12-10 13:53:34 -08:00
Parser . ParseInto ( repDat , inputPath , indexId : 1 , keep : true ) ;
2020-08-28 13:59:42 -07:00
// Perform additional processing steps
2021-02-01 11:43:38 -08:00
Extras . ApplyExtras ( repDat ) ;
2023-04-19 12:04:25 -04:00
Splitter . ApplySplitting ( repDat , useTags : false ) ;
2024-03-05 20:26:38 -05:00
repDat . ExecuteFilters ( FilterRunner ) ;
2021-02-01 11:43:38 -08:00
Cleaner . ApplyCleaning ( repDat ) ;
2021-02-01 12:11:32 -08:00
Remover . ApplyRemovals ( repDat ) ;
2020-08-27 21:40:08 -07:00
// Now replace the fields from the base DatFile
2020-12-13 23:09:24 -08:00
DatFileTool . BaseReplace (
2020-12-13 13:22:06 -08:00
userInputDat ,
repDat ,
2024-03-05 20:07:38 -05:00
updateMachineFieldNames ,
updateItemFieldNames ,
2020-12-13 13:22:06 -08:00
GetBoolean ( features , OnlySameValue ) ) ;
2020-08-27 21:40:08 -07:00
// Finally output the replaced DatFile
string interOutDir = inputPath . GetOutputPath ( OutputDir , GetBoolean ( features , InplaceValue ) ) ;
2020-12-10 14:03:07 -08:00
Writer . Write ( repDat , interOutDir , overwrite : GetBoolean ( features , InplaceValue ) ) ;
2024-02-28 21:59:13 -05:00
#if NET40_OR_GREATER | | NETCOREAPP
2020-08-27 22:19:31 -07:00
} ) ;
2024-02-28 21:59:13 -05:00
#else
}
#endif
2020-08-01 21:42:28 -07:00
}
2020-08-01 21:54:42 -07:00
// Merge all input files and write
// This has to be last due to the SuperDAT handling
if ( updateMode . HasFlag ( UpdateMode . Merge ) )
2020-08-27 21:40:08 -07:00
{
// If we're in SuperDAT mode, prefix all games with their respective DATs
if ( string . Equals ( userInputDat . Header . Type , "SuperDAT" , StringComparison . OrdinalIgnoreCase ) )
2021-02-01 11:43:38 -08:00
DatFileTool . ApplySuperDAT ( userInputDat , inputPaths ) ;
2020-08-27 21:40:08 -07:00
2020-12-10 14:03:07 -08:00
Writer . Write ( userInputDat , OutputDir ) ;
2020-08-27 21:40:08 -07:00
}
2021-03-19 20:52:11 -07:00
return true ;
2020-07-31 23:17:12 -07:00
}
}
}