Reorganize application

This commit is contained in:
Matt Nadareski
2020-07-31 23:17:12 -07:00
parent a0af82737e
commit 4bd0c10b0a
15 changed files with 3717 additions and 3619 deletions

View File

@@ -12,6 +12,7 @@ using Microsoft.Data.Sqlite;
namespace RombaSharp namespace RombaSharp
{ {
// TODO: Split this like SabreTools
public partial class RombaSharp public partial class RombaSharp
{ {
#region Private Flag features #region Private Flag features

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.IO;
using SabreTools.Library.Data;
using SabreTools.Library.DatFiles;
using SabreTools.Library.Help;
namespace SabreTools.Features
{
internal class DatFromDir : BaseFeature
{
public const string Value = "DATFromDir";
public DatFromDir()
{
Name = Value;
Flags = new List<string>() { "-d", "--d2d", "--dfd" };
Description = "Create DAT(s) from an input directory";
_featureType = FeatureType.Flag;
LongDescription = "Create a DAT file from an input directory or set of files. By default, this will output a DAT named based on the input directory and the current date. It will also treat all archives as possible games and add all three hashes (CRC, MD5, SHA-1) for each file.";
Features = new Dictionary<string, Feature>();
// Hash Features
AddFeature(SkipMd5Flag);
#if NET_FRAMEWORK
AddFeature(SkipRipeMd160Flag);
#endif
AddFeature(SkipSha1Flag);
AddFeature(SkipSha256Flag);
AddFeature(SkipSha384Flag);
AddFeature(SkipSha512Flag);
AddFeature(NoAutomaticDateFlag);
AddFeature(ArchivesAsFilesFlag);
AddFeature(OutputTypeListInput);
this[OutputTypeListInput].AddFeature(DeprecatedFlag);
AddFeature(RombaFlag);
AddFeature(SkipArchivesFlag);
AddFeature(SkipFilesFlag);
AddHeaderFeatures();
AddFeature(AddBlankFilesFlag);
AddFeature(AddDateFlag);
AddFeature(CopyFilesFlag);
AddFeature(HeaderStringInput);
AddFeature(ChdsAsFilesFlag);
AddFilteringFeatures();
AddFeature(TempStringInput);
AddFeature(OutputDirStringInput);
AddFeature(ThreadsInt32Input);
}
public override void ProcessFeatures(Dictionary<string, Feature> features)
{
base.ProcessFeatures(features);
// Get feature flags
bool addBlankFiles = GetBoolean(features, AddBlankFilesValue);
bool addFileDates = GetBoolean(features, AddDateValue);
bool archivesAsFiles = GetBoolean(features, ArchivesAsFilesValue);
bool chdsAsFiles = GetBoolean(features, ChdsAsFilesValue);
bool copyFiles = GetBoolean(features, CopyFilesValue);
bool noAutomaticDate = GetBoolean(features, NoAutomaticDateValue);
string tempDir = GetString(features, TempStringValue);
var omitFromScan = GetOmitFromScan(features);
var skipFileType = GetSkipFileType(features);
// Create a new DATFromDir object and process the inputs
DatFile basedat = DatFile.Create(Header);
basedat.Header.Date = DateTime.Now.ToString("yyyy-MM-dd");
// For each input directory, create a DAT
foreach (string path in Inputs)
{
if (Directory.Exists(path) || File.Exists(path))
{
// Clone the base Dat for information
DatFile datdata = DatFile.Create(basedat.Header);
string basePath = Path.GetFullPath(path);
bool success = datdata.PopulateFromDir(
basePath,
omitFromScan,
noAutomaticDate,
archivesAsFiles,
skipFileType,
addBlankFiles,
addFileDates,
tempDir,
copyFiles,
Header.Header,
chdsAsFiles,
Filter);
if (success)
{
datdata.Write(OutputDir);
}
else
{
Console.WriteLine();
OutputRecursive(0);
}
}
}
}
}
}

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
using SabreTools.Library.Data;
using SabreTools.Library.Help;
namespace SabreTools.Features
{
internal class DisplayHelp : BaseFeature
{
public const string Value = "Help";
public DisplayHelp()
{
Name = Value;
Flags = new List<string>() { "-?", "-h", "--help" };
Description = "Show this help";
_featureType = FeatureType.Flag;
LongDescription = "Built-in to most of the programs is a basic help text.";
Features = new Dictionary<string, Feature>();
}
public override bool ProcessArgs(string[] args, Help help)
{
// If we had something else after help
if (args.Length > 1)
{
help.OutputIndividualFeature(args[1]);
return true;
}
// Otherwise, show generic help
else
{
help.OutputGenericHelp();
return true;
}
}
}
}

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
using SabreTools.Library.Data;
using SabreTools.Library.Help;
namespace SabreTools.Features
{
internal class DisplayHelpDetailed : BaseFeature
{
public const string Value = "Help (Detailed)";
public DisplayHelpDetailed()
{
Name = Value;
Flags = new List<string>() { "-??", "-hd", "--help-detailed" };
Description = "Show this detailed help";
_featureType = FeatureType.Flag;
LongDescription = "Display a detailed help text to the screen.";
Features = new Dictionary<string, Feature>();
}
public override bool ProcessArgs(string[] args, Help help)
{
// If we had something else after help
if (args.Length > 1)
{
help.OutputIndividualFeature(args[1], includeLongDescription: true);
return true;
}
// Otherwise, show generic help
else
{
help.OutputAllHelp();
return true;
}
}
}
}

View File

@@ -0,0 +1,52 @@
using System.Collections.Generic;
using SabreTools.Library.Data;
using SabreTools.Library.Help;
using SabreTools.Library.Skippers;
using SabreTools.Library.Tools;
namespace SabreTools.Features
{
internal class Extract : BaseFeature
{
public const string Value = "Extract";
public Extract()
{
Name = Value;
Flags = new List<string>() { "-ex", "--extract" };
Description = "Extract and remove copier headers";
_featureType = FeatureType.Flag;
LongDescription = @"This will detect, store, and remove copier headers from a file or folder of files. The headers are backed up and collated by the hash of the unheadered file. Files are then output without the detected copier header alongside the originals with the suffix .new. No input files are altered in the process.
The following systems have headers that this program can work with:
- Atari 7800
- Atari Lynx
- Commodore PSID Music
- NEC PC - Engine / TurboGrafx 16
- Nintendo Famicom / Nintendo Entertainment System
- Nintendo Famicom Disk System
- Nintendo Super Famicom / Super Nintendo Entertainment System
- Nintendo Super Famicom / Super Nintendo Entertainment System SPC";
Features = new Dictionary<string, Feature>();
AddFeature(OutputDirStringInput);
AddFeature(NoStoreHeaderFlag);
}
public override void ProcessFeatures(Dictionary<string, Feature> features)
{
base.ProcessFeatures(features);
// Get feature flags
bool nostore = GetBoolean(features, NoStoreHeaderValue);
// Get only files from the inputs
List<ParentablePath> files = DirectoryExtensions.GetFilesOnly(Inputs);
foreach (ParentablePath file in files)
{
Transform.DetectTransformStore(file.CurrentPath, OutputDir, nostore);
}
}
}
}

View File

@@ -0,0 +1,48 @@
using System.Collections.Generic;
using SabreTools.Library.Data;
using SabreTools.Library.Help;
using SabreTools.Library.Skippers;
using SabreTools.Library.Tools;
namespace SabreTools.Features
{
internal class Restore : BaseFeature
{
public const string Value = "Restore";
public Restore()
{
Name = Value;
Flags = new List<string>() { "-re", "--restore" };
Description = "Restore header to file based on SHA-1";
_featureType = FeatureType.Flag;
LongDescription = @"This will make use of stored copier headers and reapply them to files if they match the included hash. More than one header can be applied to a file, so they will be output to new files, suffixed with .newX, where X is a number. No input files are altered in the process.
The following systems have headers that this program can work with:
- Atari 7800
- Atari Lynx
- Commodore PSID Music
- NEC PC - Engine / TurboGrafx 16
- Nintendo Famicom / Nintendo Entertainment System
- Nintendo Famicom Disk System
- Nintendo Super Famicom / Super Nintendo Entertainment System
- Nintendo Super Famicom / Super Nintendo Entertainment System SPC";
Features = new Dictionary<string, Feature>();
AddFeature(OutputDirStringInput);
}
public override void ProcessFeatures(Dictionary<string, Feature> features)
{
base.ProcessFeatures(features);
// Get only files from the inputs
List<ParentablePath> files = DirectoryExtensions.GetFilesOnly(Inputs);
foreach (ParentablePath file in files)
{
Transform.RestoreHeader(file.CurrentPath, OutputDir);
}
}
}
}

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
using SabreTools.Library.Data;
using SabreTools.Library.Help;
namespace SabreTools.Features
{
internal class Script : BaseFeature
{
public const string Value = "Script";
public Script()
{
Name = Value;
Flags = new List<string>() { "--script" };
Description = "Enable script mode (no clear screen)";
_featureType = FeatureType.Flag;
LongDescription = "For times when SabreTools is being used in a scripted environment, the user may not want the screen to be cleared every time that it is called. This flag allows the user to skip clearing the screen on run just like if the console was being redirected.";
Features = new Dictionary<string, Feature>();
}
}
}

120
SabreTools/Features/Sort.cs Normal file
View File

@@ -0,0 +1,120 @@
using System.Collections.Generic;
using System.IO;
using SabreTools.Library.Data;
using SabreTools.Library.DatFiles;
using SabreTools.Library.Help;
using SabreTools.Library.Tools;
namespace SabreTools.Features
{
internal class Sort : BaseFeature
{
public const string Value = "Sort";
public Sort()
{
Name = Value;
Flags = new List<string>() { "-ss", "--sort" };
Description = "Sort inputs by a set of DATs";
_featureType = FeatureType.Flag;
LongDescription = "This feature allows the user to quickly rebuild based on a supplied DAT file(s). By default all files will be rebuilt to uncompressed folders in the output directory.";
Features = new Dictionary<string, Feature>();
AddFeature(DatListInput);
AddFeature(OutputDirStringInput);
AddFeature(DepotFlag);
AddFeature(DeleteFlag);
AddFeature(InverseFlag);
AddFeature(QuickFlag);
AddFeature(ChdsAsFilesFlag);
AddFeature(AddDateFlag);
AddFeature(IndividualFlag);
// Output Formats
AddFeature(Torrent7zipFlag);
AddFeature(TarFlag);
AddFeature(TorrentGzipFlag);
this[TorrentGzipFlag].AddFeature(RombaFlag);
//AddFeature(SharedInputs.TorrentLrzipFlag);
//AddFeature(SharedInputs.TorrentLz4Flag);
//AddFeature(SharedInputs.TorrentRarFlag);
//AddFeature(SharedInputs.TorrentXzFlag);
//this[SharedInputs.TorrentXzFlag].AddFeature(SharedInputs.RombaFlag);
AddFeature(TorrentZipFlag);
//AddFeature(SharedInputs.TorrentZpaqFlag);
//AddFeature(SharedInputs.TorrentZstdFlag);
AddFeature(HeaderStringInput);
AddInternalSplitFeatures();
AddFeature(UpdateDatFlag);
AddFeature(ThreadsInt32Input);
}
public override void ProcessFeatures(Dictionary<string, Feature> features)
{
base.ProcessFeatures(features);
// Get feature flags
bool chdsAsFiles = GetBoolean(features, ChdsAsFilesValue);
bool date = GetBoolean(features, AddDateValue);
bool delete = GetBoolean(features, DeleteValue);
bool depot = GetBoolean(features, DepotValue);
bool inverse = GetBoolean(features, InverseValue);
bool quickScan = GetBoolean(features, QuickValue);
bool romba = GetBoolean(features, RombaValue);
bool updateDat = GetBoolean(features, UpdateDatValue);
string headerToCheckAgainst = GetString(features, HeaderStringValue);
var outputFormat = GetOutputFormat(features);
// If we have TorrentGzip output and the romba flag, update
if (romba && outputFormat == OutputFormat.TorrentGzip)
outputFormat = OutputFormat.TorrentGzipRomba;
// If we hae TorrentXZ output and the romba flag, update
if (romba && outputFormat == OutputFormat.TorrentXZ)
outputFormat = OutputFormat.TorrentXZRomba;
// Get a list of files from the input datfiles
var datfiles = GetList(features, DatListValue);
var datfilePaths = DirectoryExtensions.GetFilesOnly(datfiles);
// If we are in individual mode, process each DAT on their own, appending the DAT name to the output dir
if (GetBoolean(features, IndividualValue))
{
foreach (ParentablePath datfile in datfilePaths)
{
DatFile datdata = DatFile.Create();
datdata.Parse(datfile, 99, keep: true);
// If we have the depot flag, respect it
if (depot)
datdata.RebuildDepot(Inputs, Path.Combine(OutputDir, datdata.Header.FileName), date, delete, inverse, outputFormat, updateDat, headerToCheckAgainst);
else
datdata.RebuildGeneric(Inputs, Path.Combine(OutputDir, datdata.Header.FileName), quickScan, date, delete, inverse, outputFormat, updateDat, headerToCheckAgainst, chdsAsFiles);
}
}
// Otherwise, process all DATs into the same output
else
{
InternalStopwatch watch = new InternalStopwatch("Populating internal DAT");
// Add all of the input DATs into one huge internal DAT
DatFile datdata = DatFile.Create();
foreach (ParentablePath datfile in datfilePaths)
{
datdata.Parse(datfile, 99, keep: true);
}
watch.Stop();
// If we have the depot flag, respect it
if (depot)
datdata.RebuildDepot(Inputs, OutputDir, date, delete, inverse, outputFormat, updateDat, headerToCheckAgainst);
else
datdata.RebuildGeneric(Inputs, OutputDir, quickScan, date, delete, inverse, outputFormat, updateDat, headerToCheckAgainst, chdsAsFiles);
}
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Collections.Generic;
using SabreTools.Library.Data;
using SabreTools.Library.DatFiles;
using SabreTools.Library.Help;
namespace SabreTools.Features
{
internal class Split : BaseFeature
{
public const string Value = "Split";
public Split()
{
Name = Value;
Flags = new List<string>() { "-sp", "--split" };
Description = "Split input DATs by a given criteria";
_featureType = FeatureType.Flag;
LongDescription = "This feature allows the user to split input DATs by a number of different possible criteria. See the individual input information for details. More than one split type is allowed at a time.";
Features = new Dictionary<string, Feature>();
AddFeature(OutputTypeListInput);
this[OutputTypeListInput].AddFeature(DeprecatedFlag);
AddFeature(OutputDirStringInput);
AddFeature(InplaceFlag);
AddFeature(ExtensionFlag);
this[ExtensionFlag].AddFeature(ExtaListInput);
this[ExtensionFlag].AddFeature(ExtbListInput);
AddFeature(HashFlag);
AddFeature(LevelFlag);
this[LevelFlag].AddFeature(ShortFlag);
this[LevelFlag].AddFeature(BaseFlag);
AddFeature(SizeFlag);
this[SizeFlag].AddFeature(RadixInt64Input);
AddFeature(TypeFlag);
}
public override void ProcessFeatures(Dictionary<string, Feature> features)
{
base.ProcessFeatures(features);
DatFile datfile = DatFile.Create(Header.DatFormat);
datfile.DetermineSplitType(
Inputs,
OutputDir,
GetBoolean(features, InplaceValue),
GetSplittingMode(features),
GetList(features, ExtAListValue),
GetList(features, ExtBListValue),
GetBoolean(features, ShortValue),
GetBoolean(features, BaseValue),
GetInt64(features, RadixInt64Value));
}
}
}

View File

@@ -0,0 +1,69 @@
using System.Collections.Generic;
using System.IO;
using SabreTools.Library.Data;
using SabreTools.Library.DatFiles;
using SabreTools.Library.Help;
namespace SabreTools.Features
{
internal class Stats : BaseFeature
{
public const string Value = "Stats";
public Stats()
{
Name = Value;
Flags = new List<string>() { "-st", "--stats" };
Description = "Get statistics on all input DATs";
_featureType = FeatureType.Flag;
LongDescription = @"This will output by default the combined statistics for all input DAT files.
The stats that are outputted are as follows:
- Total uncompressed size
- Number of games found
- Number of roms found
- Number of disks found
- Items that include a CRC
- Items that include a MD5
- Items that include a SHA-1
- Items that include a SHA-256
- Items that include a SHA-384
- Items that include a SHA-512
- Items with Nodump status";
Features = new Dictionary<string, Feature>();
AddFeature(ReportTypeListInput);
AddFeature(FilenameStringInput);
AddFeature(OutputDirStringInput);
AddFeature(BaddumpColumnFlag);
AddFeature(NodumpColumnFlag);
AddFeature(IndividualFlag);
}
public override void ProcessFeatures(Dictionary<string, Feature> features)
{
base.ProcessFeatures(features);
string filename = Header.FileName;
if (Path.GetFileName(filename) != filename)
{
if (string.IsNullOrWhiteSpace(OutputDir))
OutputDir = Path.GetDirectoryName(filename);
else
OutputDir = Path.Combine(OutputDir, Path.GetDirectoryName(filename));
filename = Path.GetFileName(filename);
}
ItemDictionary.OutputStats(
Inputs,
filename,
OutputDir,
GetBoolean(features, IndividualValue),
GetBoolean(features, BaddumpColumnValue),
GetBoolean(features, NodumpColumnValue),
GetStatReportFormat(features));
}
}
}

View File

@@ -0,0 +1,159 @@
using System;
using System.Collections.Generic;
using SabreTools.Library.Data;
using SabreTools.Library.DatFiles;
using SabreTools.Library.Help;
namespace SabreTools.Features
{
internal class Update : BaseFeature
{
public const string Value = "Update";
public Update()
{
Name = Value;
Flags = new List<string>() { "-ud", "--update" };
Description = "Update and manipulate DAT(s)";
_featureType = FeatureType.Flag;
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.";
Features = new Dictionary<string, Feature>();
// Output Formats
AddFeature(OutputTypeListInput);
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].AddFeature(DeprecatedFlag);
AddHeaderFeatures();
AddFeature(KeepEmptyGamesFlag);
AddFeature(CleanFlag);
AddFeature(RemoveUnicodeFlag);
AddFeature(DescriptionAsNameFlag);
AddInternalSplitFeatures();
AddFeature(TrimFlag);
this[TrimFlag].AddFeature(RootDirStringInput);
AddFeature(SingleSetFlag);
AddFeature(DedupFlag);
AddFeature(GameDedupFlag);
AddFeature(MergeFlag);
this[MergeFlag].AddFeature(NoAutomaticDateFlag);
AddFeature(DiffAllFlag);
this[DiffAllFlag].AddFeature(NoAutomaticDateFlag);
AddFeature(DiffDuplicatesFlag);
this[DiffDuplicatesFlag].AddFeature(NoAutomaticDateFlag);
AddFeature(DiffIndividualsFlag);
this[DiffIndividualsFlag].AddFeature(NoAutomaticDateFlag);
AddFeature(DiffNoDuplicatesFlag);
this[DiffNoDuplicatesFlag].AddFeature(NoAutomaticDateFlag);
AddFeature(DiffAgainstFlag);
this[DiffAgainstFlag].AddFeature(BaseDatListInput);
AddFeature(BaseReplaceFlag);
this[BaseReplaceFlag].AddFeature(BaseDatListInput);
this[BaseReplaceFlag].AddFeature(UpdateFieldListInput);
this[BaseReplaceFlag][UpdateFieldListInput].AddFeature(OnlySameFlag);
this[BaseReplaceFlag].AddFeature(UpdateNamesFlag);
this[BaseReplaceFlag].AddFeature(UpdateHashesFlag);
this[BaseReplaceFlag].AddFeature(UpdateDescriptionFlag);
this[BaseReplaceFlag][UpdateDescriptionFlag].AddFeature(OnlySameFlag);
this[BaseReplaceFlag].AddFeature(UpdateGameTypeFlag);
this[BaseReplaceFlag].AddFeature(UpdateYearFlag);
this[BaseReplaceFlag].AddFeature(UpdateManufacturerFlag);
this[BaseReplaceFlag].AddFeature(UpdateParentsFlag);
AddFeature(ReverseBaseReplaceFlag);
this[ReverseBaseReplaceFlag].AddFeature(BaseDatListInput);
this[ReverseBaseReplaceFlag].AddFeature(UpdateFieldListInput);
this[ReverseBaseReplaceFlag][UpdateFieldListInput].AddFeature(OnlySameFlag);
this[ReverseBaseReplaceFlag].AddFeature(UpdateNamesFlag);
this[ReverseBaseReplaceFlag].AddFeature(UpdateHashesFlag);
this[ReverseBaseReplaceFlag].AddFeature(UpdateDescriptionFlag);
this[ReverseBaseReplaceFlag][UpdateDescriptionFlag].AddFeature(OnlySameFlag);
this[ReverseBaseReplaceFlag].AddFeature(UpdateGameTypeFlag);
this[ReverseBaseReplaceFlag].AddFeature(UpdateYearFlag);
this[ReverseBaseReplaceFlag].AddFeature(UpdateManufacturerFlag);
this[ReverseBaseReplaceFlag].AddFeature(UpdateParentsFlag);
AddFeature(DiffCascadeFlag);
this[DiffCascadeFlag].AddFeature(SkipFirstOutputFlag);
AddFeature(DiffReverseCascadeFlag);
this[DiffReverseCascadeFlag].AddFeature(SkipFirstOutputFlag);
AddFilteringFeatures();
AddFeature(OutputDirStringInput);
AddFeature(InplaceFlag);
AddFeature(ThreadsInt32Input);
}
public override void ProcessFeatures(Dictionary<string, Feature> features)
{
base.ProcessFeatures(features);
// Get feature flags
var updateFields = GetUpdateFields(features);
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}");
// If we're in a special update mode and the names aren't set, set defaults
if (updateMode != 0)
{
// 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)
+ (Header.DedupeRoms != DedupeType.None ? "-deduped" : string.Empty);
}
if (string.IsNullOrWhiteSpace(Header.Description))
{
Header.Description = (updateMode != 0 ? "DiffDAT" : "MergeDAT")
+ (Header.Type == "SuperDAT" ? "-SuperDAT" : string.Empty)
+ (Header.DedupeRoms != DedupeType.None ? " - deduped" : string.Empty);
if (!GetBoolean(features, NoAutomaticDateValue))
Header.Description += $" ({Header.Date})";
}
if (string.IsNullOrWhiteSpace(Header.Category) && updateMode != 0)
Header.Category = "DiffDAT";
if (string.IsNullOrWhiteSpace(Header.Author))
Header.Author = "SabreTools";
}
// If no update fields are set, default to Names
if (updateFields == null || updateFields.Count == 0)
updateFields = new List<Field>() { Field.Name };
// Populate the DatData object
DatFile userInputDat = DatFile.Create(Header);
userInputDat.DetermineUpdateType(
Inputs,
GetList(features, BaseDatListValue),
OutputDir,
updateMode,
GetBoolean(features, InplaceValue),
GetBoolean(features, SkipFirstOutputValue),
Filter,
updateFields,
GetBoolean(features, OnlySameValue));
}
}
}

View File

@@ -0,0 +1,91 @@
using System.Collections.Generic;
using SabreTools.Library.Data;
using SabreTools.Library.DatFiles;
using SabreTools.Library.Filtering;
using SabreTools.Library.Help;
using SabreTools.Library.Tools;
namespace SabreTools.Features
{
internal class Verify : BaseFeature
{
public const string Value = "Verify";
public Verify()
{
Name = Value;
Flags = new List<string>() { "-ve", "--verify" };
Description = "Verify a folder against DATs";
_featureType = FeatureType.Flag;
LongDescription = "When used, this will use an input DAT or set of DATs to blindly check against an input folder. The base of the folder is considered the base for the combined DATs and games are either the directories or archives within. This will only do a direct verification of the items within and will create a fixdat afterwards for missing files.";
Features = new Dictionary<string, Feature>();
AddFeature(DatListInput);
AddFeature(DepotFlag);
AddFeature(TempStringInput);
AddFeature(OutputDirStringInput);
AddFeature(HashOnlyFlag);
AddFeature(QuickFlag);
AddFeature(HeaderStringInput);
AddFeature(ChdsAsFilesFlag);
AddFeature(IndividualFlag);
AddInternalSplitFeatures();
AddFilteringFeatures();
}
public override void ProcessFeatures(Dictionary<string, Feature> features)
{
base.ProcessFeatures(features);
// Get a list of files from the input datfiles
var datfiles = GetList(features, DatListValue);
var datfilePaths = DirectoryExtensions.GetFilesOnly(datfiles);
// Get feature flags
bool chdsAsFiles = GetBoolean(features, ChdsAsFilesValue);
bool depot = GetBoolean(features, DepotValue);
bool hashOnly = GetBoolean(features, HashOnlyValue);
bool quickScan = GetBoolean(features, QuickValue);
string headerToCheckAgainst = Header.Header;
// If we are in individual mode, process each DAT on their own
if (GetBoolean(features, IndividualValue))
{
foreach (ParentablePath datfile in datfilePaths)
{
DatFile datdata = DatFile.Create();
datdata.Parse(datfile, 99, keep: true);
Filter.FilterDatFile(datdata, true);
// If we have the depot flag, respect it
if (depot)
datdata.VerifyDepot(Inputs, OutputDir);
else
datdata.VerifyGeneric(Inputs, OutputDir, hashOnly, quickScan, headerToCheckAgainst, chdsAsFiles, Filter);
}
}
// Otherwise, process all DATs into the same output
else
{
InternalStopwatch watch = new InternalStopwatch("Populating internal DAT");
// Add all of the input DATs into one huge internal DAT
DatFile datdata = DatFile.Create();
foreach (ParentablePath datfile in datfilePaths)
{
datdata.Parse(datfile, 99, keep: true);
Filter.FilterDatFile(datdata, true);
}
watch.Stop();
// If we have the depot flag, respect it
if (depot)
datdata.VerifyDepot(Inputs, OutputDir);
else
datdata.VerifyGeneric(Inputs, OutputDir, hashOnly, quickScan, headerToCheckAgainst, chdsAsFiles, Filter);
}
}
}
}

View File

@@ -1,21 +1,20 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using SabreTools.Features;
using SabreTools.Library.Data; using SabreTools.Library.Data;
using SabreTools.Library.Help; using SabreTools.Library.Help;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
namespace SabreTools namespace SabreTools
{ {
/// <summary> public class Program
/// Entry class for the DATabase application
/// </summary>
public partial class SabreTools
{ {
// Private required variables // Private required variables
private static Help _help; private static Help _help;
/// <summary> /// <summary>
/// Entry class for the SabreTools application /// Entry point for the SabreTools application
/// </summary> /// </summary>
/// <param name="args">String array representing command line parameters</param> /// <param name="args">String array representing command line parameters</param>
public static void Main(string[] args) public static void Main(string[] args)
@@ -24,7 +23,7 @@ namespace SabreTools
Globals.Logger = new Logger(true, "sabretools.log"); Globals.Logger = new Logger(true, "sabretools.log");
// Create a new Help object for this program // Create a new Help object for this program
_help = SabreTools.RetrieveHelp(); _help = RetrieveHelp();
// Get the location of the script tag, if it exists // Get the location of the script tag, if it exists
int scriptLocation = (new List<string>(args)).IndexOf("--script"); int scriptLocation = (new List<string>(args)).IndexOf("--script");
@@ -76,10 +75,10 @@ namespace SabreTools
featureName = _help.GetFeatureName(featureName); featureName = _help.GetFeatureName(featureName);
// Get the associated feature // Get the associated feature
SabreToolsFeature feature = _help[featureName] as SabreToolsFeature; BaseFeature feature = _help[featureName] as BaseFeature;
// If we had the help feature first // If we had the help feature first
if (featureName == HelpFeature.Value || featureName == DetailedHelpFeature.Value) if (featureName == DisplayHelp.Value || featureName == DisplayHelpDetailed.Value)
{ {
feature.ProcessArgs(args, _help); feature.ProcessArgs(args, _help);
Globals.Logger.Close(); Globals.Logger.Close();
@@ -98,25 +97,25 @@ namespace SabreTools
switch (featureName) switch (featureName)
{ {
// No-op as these should be caught // No-op as these should be caught
case HelpFeature.Value: case DisplayHelp.Value:
case DetailedHelpFeature.Value: case DisplayHelpDetailed.Value:
case ScriptFeature.Value: case Script.Value:
break; break;
// Require input verification // Require input verification
case DatFromDirFeature.Value: case DatFromDir.Value:
case ExtractFeature.Value: case Extract.Value:
case RestoreFeature.Value: case Restore.Value:
case SplitFeature.Value: case Split.Value:
case StatsFeature.Value: case Stats.Value:
case UpdateFeature.Value: case Update.Value:
case VerifyFeature.Value: case Verify.Value:
VerifyInputs(feature.Inputs, featureName); VerifyInputs(feature.Inputs, featureName);
feature.ProcessFeatures(features); feature.ProcessFeatures(features);
break; break;
// Requires no input verification // Requires no input verification
case SortFeature.Value: case Sort.Value:
feature.ProcessFeatures(features); feature.ProcessFeatures(features);
break; break;
@@ -130,6 +129,46 @@ namespace SabreTools
return; return;
} }
/// <summary>
/// Generate a Help object for this program
/// </summary>
/// <returns></returns>
private static Help RetrieveHelp()
{
// Create and add the header to the Help object
string barrier = "-----------------------------------------";
List<string> helpHeader = new List<string>()
{
"SabreTools - Manipulate, convert, and use DAT files",
barrier,
"Usage: SabreTools [option] [flags] [filename|dirname] ...",
string.Empty
};
// Create the base help object with header
Help help = new Help(helpHeader);
// Add all of the features
help.Add(new DisplayHelp());
help.Add(new DisplayHelpDetailed());
help.Add(new Script());
help.Add(new DatFromDir());
help.Add(new Extract());
help.Add(new Restore());
help.Add(new Sort());
help.Add(new Split());
help.Add(new Stats());
help.Add(new Update());
help.Add(new Verify());
return help;
}
/// <summary>
/// Verify that there are inputs, show help otherwise
/// </summary>
/// <param name="inputs">List of inputs</param>
/// <param name="feature">Name of the current feature</param>
private static void VerifyInputs(List<string> inputs, string feature) private static void VerifyInputs(List<string> inputs, string feature)
{ {
if (inputs.Count == 0) if (inputs.Count == 0)

File diff suppressed because it is too large Load Diff