diff --git a/Deheader/HeadererApp.cs b/Deheader/HeadererApp.cs
index cd4ef42f..0ad72f9d 100644
--- a/Deheader/HeadererApp.cs
+++ b/Deheader/HeadererApp.cs
@@ -70,6 +70,7 @@ namespace SabreTools
extract = true;
break;
case "-r":
+ case "-re":
case "--restore":
extract = false;
break;
diff --git a/SabreTools.Helper/README.1ST b/SabreTools.Helper/README.1ST
index f8450333..d08d2a73 100644
--- a/SabreTools.Helper/README.1ST
+++ b/SabreTools.Helper/README.1ST
@@ -410,6 +410,32 @@ Options:
As a holdover from only two output formats, this tool defaults to Logiqx XML
DAT outputs. If this flag is enabled, a clrmamepro DAT will be created instead.
+ -hd, --headerer Backup or restore copier headers from a variety of file types
+ Headerer is formerly a small program that is meant as an intermediary between header
+ skipper files (which, a bit apart from their name, do not just show how to skip
+ copier headers) and rom managers that do not use them.
+
+ By default, 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 Music
+
+ -re, --restore Restore headers to file(s)
+ Instead of the default extraction, this flag enables use of stored copier headers
+ to 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.
+
-hs, --hash-split Split a DAT or folder by best-available hashes
For a DAT, or set of DATs, allow for splitting based on the best available hash for
each file within. The order of preference for the outputted DATs is as follows:
diff --git a/SabreTools/Partials/SabreTools_Inits.cs b/SabreTools/Partials/SabreTools_Inits.cs
index 61765201..8f553def 100644
--- a/SabreTools/Partials/SabreTools_Inits.cs
+++ b/SabreTools/Partials/SabreTools_Inits.cs
@@ -317,13 +317,16 @@ namespace SabreTools
///
/// Wrap extracting and replacing headers
///
- /// Input file or folder name
+ /// Input file or folder names
/// True if we're extracting headers (default), false if we're replacing them
/// Logger object for file and console output
- private static void InitHeaderer(string input, bool extract, Logger logger)
+ private static void InitHeaderer(List inputs, bool extract, Logger logger)
{
- Headerer headerer = new Headerer(input, extract, logger);
- headerer.Process();
+ foreach (string input in inputs)
+ {
+ Headerer headerer = new Headerer(input, extract, logger);
+ headerer.Process();
+ }
}
///
diff --git a/SabreTools/SabreTools.cs b/SabreTools/SabreTools.cs
index 7db3844d..c31dfe23 100644
--- a/SabreTools/SabreTools.cs
+++ b/SabreTools/SabreTools.cs
@@ -93,11 +93,13 @@ namespace SabreTools
datprefix = false,
dedup = false,
enableGzip = false,
+ extract = true,
extsplit = false,
forceunpack = false,
generate = false,
genall = false,
hashsplit = false,
+ headerer = false,
ignore = false,
import = false,
inplace = false,
@@ -273,6 +275,10 @@ namespace SabreTools
case "--gz-files":
enableGzip = true;
break;
+ case "-hd":
+ case "--headerer":
+ headerer = true;
+ break;
case "-hs":
case "--hash-split":
hashsplit = true;
@@ -369,6 +375,10 @@ namespace SabreTools
case "--rev-cascade":
cascade = false;
break;
+ case "-re":
+ case "--restore":
+ extract = false;
+ break;
case "-rm":
case "--remove":
rem = true;
@@ -622,8 +632,8 @@ namespace SabreTools
}
// If more than one switch is enabled, show the help screen
- if (!(add ^ datfromdir ^ datfromdirparallel ^ extsplit ^ generate ^ genall ^ hashsplit ^ import ^ listsrc ^ listsys ^
- (merge || diffMode != 0 || update || outputFormat != 0 || tsv != null|| trim) ^ rem ^ stats ^ typesplit))
+ if (!(add ^ datfromdir ^ datfromdirparallel ^ extsplit ^ generate ^ genall ^ hashsplit ^ headerer ^ import ^ listsrc ^
+ listsys ^ (merge || diffMode != 0 || update || outputFormat != 0 || tsv != null|| trim) ^ rem ^ stats ^ typesplit))
{
_logger.Error("Only one feature switch is allowed at a time");
Build.Help();
@@ -632,8 +642,8 @@ namespace SabreTools
}
// If a switch that requires a filename is set and no file is, show the help screen
- if (inputs.Count == 0 && (update || outputFormat != 0 || tsv != null || extsplit || hashsplit || datfromdir
- || datfromdirparallel || (merge || diffMode != 0) || stats || trim || typesplit))
+ if (inputs.Count == 0 && (datfromdir || datfromdirparallel || extsplit || hashsplit || headerer
+ || (merge || diffMode != 0 || update || outputFormat != 0 || tsv != null) || stats || trim || typesplit))
{
_logger.Error("This feature requires at least one input");
Build.Help();
@@ -643,10 +653,48 @@ namespace SabreTools
// Now take care of each mode in succesion
- // Import a file or folder
- if (import)
+ // Add a source or system
+ if (add)
+ {
+ if (manu != "" && systems != "")
+ {
+ InitAddSystem(manu, systems);
+ }
+ else if (sources != "" && url != "")
+ {
+ InitAddSource(manu, systems);
+ }
+ else
+ {
+ Build.Help();
+ }
+ }
+
+ // Create a DAT from a directory or set of directories
+ else if (datfromdir)
+ {
+ InitDatFromDir(inputs, filename, name, description, category, version, author, forceunpack, outputFormat,
+ romba, superdat, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, tempdir);
+ }
+
+ // Create a DAT from a directory or set of directories in parallel
+ else if (datfromdirparallel)
+ {
+ InitDatFromDirParallel(inputs, filename, name, description, category, version, author, forceunpack, outputFormat,
+ romba, superdat, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, tempdir, maxParallelism);
+ }
+
+ // Split a DAT by extension
+ else if (extsplit)
+ {
+ InitExtSplit(inputs, exta, extb, outdir);
+ }
+
+ // Generate all DATs
+ else if (genall)
{
InitImport(ignore);
+ InitGenerateAll(norename, old);
}
// Generate a DAT
@@ -656,11 +704,22 @@ namespace SabreTools
InitGenerate(systems, norename, old);
}
- // Generate all DATs
- else if (genall)
+ // Split a DAT by available hashes
+ else if (hashsplit)
+ {
+ InitHashSplit(inputs, outdir);
+ }
+
+ // If we're in headerer mode
+ else if (headerer)
+ {
+ InitHeaderer(inputs, extract, _logger);
+ }
+
+ // Import a file or folder
+ else if (import)
{
InitImport(ignore);
- InitGenerateAll(norename, old);
}
// List all available sources
@@ -675,32 +734,6 @@ namespace SabreTools
ListSystems();
}
- // Convert, update, merge, diff, and filter a DAT or folder of DATs
- else if (update || tsv != null || outputFormat != 0 || merge || diffMode != 0)
- {
- InitUpdate(inputs, filename, name, description, rootdir, category, version, date, author, email, homepage, url, comment, header,
- superdat, forcemerge, forcend, forcepack, outputFormat, usegame, prefix,
- postfix, quotes, repext, addext, remext, datprefix, romba, tsv, merge, diffMode, cascade, inplace, skip, bare, gamename, romname,
- romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, outdir, clean, softlist, dedup, maxParallelism);
- }
-
- // Add a source or system
- else if (add)
- {
- if (manu != "" && systems != "")
- {
- InitAddSystem(manu, systems);
- }
- else if (sources != "" && url != "")
- {
- InitAddSource(manu, systems);
- }
- else
- {
- Build.Help();
- }
- }
-
// Remove a source or system
else if (rem)
{
@@ -718,16 +751,10 @@ namespace SabreTools
}
}
- // Split a DAT by extension
- else if (extsplit)
+ // Get statistics on input files
+ else if (stats)
{
- InitExtSplit(inputs, exta, extb, outdir);
- }
-
- // Split a DAT by available hashes
- else if (hashsplit)
- {
- InitHashSplit(inputs, outdir);
+ InitStats(inputs, single);
}
// Split a DAT by item type
@@ -736,24 +763,13 @@ namespace SabreTools
InitTypeSplit(inputs, outdir);
}
- // Get statistics on input files
- else if (stats)
+ // Convert, update, merge, diff, and filter a DAT or folder of DATs
+ else if (update || tsv != null || outputFormat != 0 || merge || diffMode != 0)
{
- InitStats(inputs, single);
- }
-
- // Create a DAT from a directory or set of directories
- else if (datfromdir)
- {
- InitDatFromDir(inputs, filename, name, description, category, version, author, forceunpack, outputFormat,
- romba, superdat, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, tempdir);
- }
-
- // Create a DAT from a directory or set of directories in parallel
- else if (datfromdirparallel)
- {
- InitDatFromDirParallel(inputs, filename, name, description, category, version, author, forceunpack, outputFormat,
- romba, superdat, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, tempdir, maxParallelism);
+ InitUpdate(inputs, filename, name, description, rootdir, category, version, date, author, email, homepage, url, comment, header,
+ superdat, forcemerge, forcend, forcepack, outputFormat, usegame, prefix,
+ postfix, quotes, repext, addext, remext, datprefix, romba, tsv, merge, diffMode, cascade, inplace, skip, bare, gamename, romname,
+ romtype, sgt, slt, seq, crc, md5, sha1, nodump, trim, single, root, outdir, clean, softlist, dedup, maxParallelism);
}
// If nothing is set, show the help