mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
[DatFile] Move Convert/Rebuild/Verify to DatFile, overhaul Rebuild
This commit is contained in:
@@ -188,7 +188,7 @@ namespace SabreTools
|
|||||||
|
|
||||||
// Create the sorting object to use and rebuild the needed files
|
// Create the sorting object to use and rebuild the needed files
|
||||||
ArchiveScanLevel asl = ArchiveTools.GetArchiveScanLevelFromNumbers((onlyNeeded ? 0 : 1), (onlyNeeded ? 0 : 1), (onlyNeeded ? 0 : 1), (onlyNeeded ? 0 : 1));
|
ArchiveScanLevel asl = ArchiveTools.GetArchiveScanLevelFromNumbers((onlyNeeded ? 0 : 1), (onlyNeeded ? 0 : 1), (onlyNeeded ? 0 : 1), (onlyNeeded ? 0 : 1));
|
||||||
FileTools.RebuildToOutput(need, onlyDirs, _depots.Keys.ToList()[0], _tmpdir, false, false, false, false, true, true, asl, false, null, 4, _logger);
|
need.RebuildToOutput(onlyDirs, _depots.Keys.ToList()[0], _tmpdir, false, false, false, false, true, true, asl, false, null, 4, _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -226,7 +226,7 @@ namespace SabreTools
|
|||||||
|
|
||||||
// Now scan all of those depots and rebuild
|
// Now scan all of those depots and rebuild
|
||||||
ArchiveScanLevel asl = ArchiveTools.GetArchiveScanLevelFromNumbers(1, 1, 1, 1);
|
ArchiveScanLevel asl = ArchiveTools.GetArchiveScanLevelFromNumbers(1, 1, 1, 1);
|
||||||
FileTools.RebuildToOutput(datFile, onlineDepots, outputFolder, _tmpdir, true, false, false, false, copy, copy, asl, false, null, 4, _logger);
|
datFile.RebuildToOutput(onlineDepots, outputFolder, _tmpdir, true, false, false, false, copy, copy, asl, false, null, 4, _logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1590,13 +1590,17 @@ namespace SabreTools.Helper.Dats
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Then populate it with information
|
// Then populate it with information
|
||||||
item.Machine.Name = tempgamename;
|
item.Machine = new Machine
|
||||||
item.Machine.Description = gamedesc;
|
{
|
||||||
item.Machine.CloneOf = cloneof;
|
Name = tempgamename,
|
||||||
item.Machine.RomOf = romof;
|
Description = gamedesc,
|
||||||
item.Machine.SampleOf = sampleof;
|
CloneOf = cloneof,
|
||||||
item.Machine.Manufacturer = manufacturer;
|
RomOf = romof,
|
||||||
item.Machine.Year = year;
|
SampleOf = sampleof,
|
||||||
|
Manufacturer = manufacturer,
|
||||||
|
Year = year,
|
||||||
|
};
|
||||||
|
|
||||||
item.SystemID = sysid;
|
item.SystemID = sysid;
|
||||||
item.SourceID = srcid;
|
item.SourceID = srcid;
|
||||||
|
|
||||||
@@ -4266,6 +4270,601 @@ namespace SabreTools.Helper.Dats
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Rebuilding and Verifying
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process inputs and convert to TorrentZip or TorrentGZ, optionally converting to Romba format
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputs">List of inputs to convert over to TorrentZip or TorrentGZ</param>
|
||||||
|
/// <param name="outDir">Output folder to rebuild to, blank is the current directory</param>
|
||||||
|
/// <param name="tempDir">Temporary directory to use in file extraction</param>
|
||||||
|
/// <param name="tgz">True if files should be output in TorrentGZ format, false for TorrentZip</param>
|
||||||
|
/// <param name="romba">True if TorrentGZ files should be output in romba depot format, false otherwise</param>
|
||||||
|
/// <param name="delete">True if input files should be deleted, false otherwise</param>
|
||||||
|
/// <param name="archiveScanLevel">ArchiveScanLevel representing how files should be treated</param>
|
||||||
|
/// <param name="logger">Logger object for file and console output</param>
|
||||||
|
/// <returns>True if processing was a success, false otherwise</returns>
|
||||||
|
public bool ConvertFiles(List<string> inputs, string outDir, string tempDir, bool tgz,
|
||||||
|
bool romba, bool delete, ArchiveScanLevel archiveScanLevel, Logger logger)
|
||||||
|
{
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
// First, check that the output directory exists
|
||||||
|
if (!Directory.Exists(outDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(outDir);
|
||||||
|
outDir = Path.GetFullPath(outDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then create or clean the temp directory
|
||||||
|
if (!Directory.Exists(tempDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(tempDir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileTools.CleanDirectory(tempDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now process all of the inputs
|
||||||
|
foreach (string input in inputs)
|
||||||
|
{
|
||||||
|
logger.User("Examining file " + input);
|
||||||
|
|
||||||
|
// Get if the file should be scanned internally and externally
|
||||||
|
bool shouldExternalProcess, shouldInternalProcess;
|
||||||
|
ArchiveTools.GetInternalExternalProcess(input, archiveScanLevel, logger, out shouldExternalProcess, out shouldInternalProcess);
|
||||||
|
|
||||||
|
// Do an external scan of the file, if necessary
|
||||||
|
if (shouldExternalProcess)
|
||||||
|
{
|
||||||
|
// If a DAT is defined, we want to make sure that this file is not in there
|
||||||
|
Rom rom = FileTools.GetFileInfo(input, logger);
|
||||||
|
if (this != null && Files.Count > 0)
|
||||||
|
{
|
||||||
|
if (rom.HasDuplicates(this, logger))
|
||||||
|
{
|
||||||
|
logger.User("File '" + input + "' existed in the DAT, skipping...");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.User("Processing file " + input);
|
||||||
|
|
||||||
|
if (tgz)
|
||||||
|
{
|
||||||
|
success &= ArchiveTools.WriteTorrentGZ(input, outDir, romba, logger);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success &= ArchiveTools.WriteToArchive(input, outDir, rom, logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the file as an archive, if necessary
|
||||||
|
if (shouldInternalProcess)
|
||||||
|
{
|
||||||
|
// Now, if the file is a supported archive type, also run on all files within
|
||||||
|
bool encounteredErrors = ArchiveTools.ExtractArchive(input, tempDir, archiveScanLevel, logger);
|
||||||
|
|
||||||
|
// If no errors were encountered, we loop through the temp directory
|
||||||
|
if (!encounteredErrors)
|
||||||
|
{
|
||||||
|
logger.Verbose("Archive found! Successfully extracted");
|
||||||
|
foreach (string file in Directory.EnumerateFiles(tempDir, "*", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
// If a DAT is defined, we want to make sure that this file is not in there
|
||||||
|
Rom rom = FileTools.GetFileInfo(file, logger);
|
||||||
|
if (this != null && Files.Count > 0)
|
||||||
|
{
|
||||||
|
if (rom.HasDuplicates(this, logger))
|
||||||
|
{
|
||||||
|
logger.User("File '" + file + "' existed in the DAT, skipping...");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.User("Processing file " + input);
|
||||||
|
|
||||||
|
if (tgz)
|
||||||
|
{
|
||||||
|
success &= ArchiveTools.WriteTorrentGZ(file, outDir, romba, logger);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success &= ArchiveTools.WriteToArchive(file, outDir, rom, logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileTools.CleanDirectory(tempDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the source file if we're supposed to
|
||||||
|
if (delete)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.User("Attempting to delete " + input);
|
||||||
|
File.Delete(input);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.Error(ex.ToString());
|
||||||
|
success &= false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now one final delete of the temp directory
|
||||||
|
while (Directory.Exists(tempDir))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.Delete(tempDir, true);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're in romba mode and the size file doesn't exist, create it
|
||||||
|
if (romba && !File.Exists(Path.Combine(outDir, ".romba_size")))
|
||||||
|
{
|
||||||
|
// Get the size of all of the files in the output folder
|
||||||
|
long size = 0;
|
||||||
|
foreach (string file in Directory.EnumerateFiles(outDir, "*", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
FileInfo tempinfo = new FileInfo(file);
|
||||||
|
size += tempinfo.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out the value to each of the romba depot files
|
||||||
|
StreamWriter tw = new StreamWriter(File.Open(Path.Combine(outDir, ".romba_size"), FileMode.Create, FileAccess.Write));
|
||||||
|
StreamWriter twb = new StreamWriter(File.Open(Path.Combine(outDir, ".romba_size.backup"), FileMode.Create, FileAccess.Write));
|
||||||
|
|
||||||
|
tw.Write(size);
|
||||||
|
twb.Write(size);
|
||||||
|
|
||||||
|
tw.Dispose();
|
||||||
|
twb.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process the DAT and find all matches in input files and folders
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputs">List of input files/folders to check</param>
|
||||||
|
/// <param name="outDir">Output directory to use to build to</param>
|
||||||
|
/// <param name="tempDir">Temporary directory for archive extraction</param>
|
||||||
|
/// <param name="quickScan">True to enable external scanning of archives, false otherwise</param>
|
||||||
|
/// <param name="date">True if the date from the DAT should be used if available, false otherwise</param>
|
||||||
|
/// <param name="toFolder">True if files should be output to folder, false otherwise</param>
|
||||||
|
/// <param name="delete">True if input files should be deleted, false otherwise</param>
|
||||||
|
/// <param name="tgz">True if output files should be written to TorrentGZ instead of TorrentZip</param>
|
||||||
|
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
|
||||||
|
/// <param name="archiveScanLevel">ArchiveScanLevel representing the archive handling levels</param>
|
||||||
|
/// <param name="updateDat">True if the updated DAT should be output, false otherwise</param>
|
||||||
|
/// <param name="headerToCheckAgainst">Populated string representing the name of the skipper to use, a blank string to use the first available checker, null otherwise</param>
|
||||||
|
/// <param name="logger">Logger object for file and console output</param>
|
||||||
|
/// <returns>True if rebuilding was a success, false otherwise</returns>
|
||||||
|
public bool RebuildToOutput(List<string> inputs, string outDir, string tempDir, bool quickScan, bool date,
|
||||||
|
bool toFolder, bool delete, bool tgz, bool romba, ArchiveScanLevel archiveScanLevel, bool updateDat, string headerToCheckAgainst,
|
||||||
|
int maxDegreeOfParallelism, Logger logger)
|
||||||
|
{
|
||||||
|
// First, check that the output directory exists
|
||||||
|
if (!Directory.Exists(outDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(outDir);
|
||||||
|
outDir = Path.GetFullPath(outDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the temp directory
|
||||||
|
if (String.IsNullOrEmpty(tempDir))
|
||||||
|
{
|
||||||
|
tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then create or clean the temp directory
|
||||||
|
if (!Directory.Exists(tempDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(tempDir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileTools.CleanDirectory(tempDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = true;
|
||||||
|
DatFile matched = new DatFile();
|
||||||
|
List<string> files = new List<string>();
|
||||||
|
|
||||||
|
#region Retrieve a list of all files
|
||||||
|
|
||||||
|
logger.User("Retrieving list all files from input");
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
|
||||||
|
// Create a list of just files from inputs
|
||||||
|
Parallel.ForEach(inputs,
|
||||||
|
new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism, },
|
||||||
|
input => {
|
||||||
|
if (File.Exists(input))
|
||||||
|
{
|
||||||
|
logger.Verbose("File found: '" + input + "'");
|
||||||
|
files.Add(Path.GetFullPath(input));
|
||||||
|
}
|
||||||
|
else if (Directory.Exists(input))
|
||||||
|
{
|
||||||
|
logger.Verbose("Directory found: '" + input + "'");
|
||||||
|
Parallel.ForEach(Directory.EnumerateFiles(input, "*", SearchOption.AllDirectories),
|
||||||
|
new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism, },
|
||||||
|
file =>
|
||||||
|
{
|
||||||
|
logger.Verbose("File found: '" + file + "'");
|
||||||
|
files.Add(Path.GetFullPath(file));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.Error("'" + input + "' is not a file or directory!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
logger.User("Retrieving complete in: " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
DatFile current = new DatFile();
|
||||||
|
|
||||||
|
#region Create a dat from input files
|
||||||
|
|
||||||
|
logger.User("Getting hash information for all input files");
|
||||||
|
start = DateTime.Now;
|
||||||
|
|
||||||
|
// Now that we have a list of just files, we get a DAT from the input files
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
// Define the temporary directory
|
||||||
|
string tempSubDir = Path.GetFullPath(Path.Combine(tempDir, Path.GetRandomFileName())) + Path.DirectorySeparatorChar;
|
||||||
|
|
||||||
|
// Get the required scanning level for the file
|
||||||
|
bool shouldExternalProcess = false;
|
||||||
|
bool shouldInternalProcess = false;
|
||||||
|
ArchiveTools.GetInternalExternalProcess(file, archiveScanLevel, logger, out shouldExternalProcess, out shouldInternalProcess);
|
||||||
|
|
||||||
|
// If we're supposed to scan the file externally
|
||||||
|
if (shouldExternalProcess)
|
||||||
|
{
|
||||||
|
Rom rom = FileTools.GetFileInfo(file, logger, noMD5: quickScan, noSHA1: quickScan, header: headerToCheckAgainst);
|
||||||
|
rom.Name = Path.GetFullPath(file);
|
||||||
|
|
||||||
|
string key = rom.Size + "-" + rom.CRC;
|
||||||
|
if (current.Files.ContainsKey(key))
|
||||||
|
{
|
||||||
|
current.Files[key].Add(rom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<DatItem> temp = new List<DatItem>();
|
||||||
|
temp.Add(rom);
|
||||||
|
current.Files.Add(key, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're supposed to scan the file internally
|
||||||
|
if (shouldInternalProcess)
|
||||||
|
{
|
||||||
|
// If quickscan is set, do so
|
||||||
|
if (quickScan)
|
||||||
|
{
|
||||||
|
List<Rom> extracted = ArchiveTools.GetArchiveFileInfo(file, logger);
|
||||||
|
|
||||||
|
foreach (Rom rom in extracted)
|
||||||
|
{
|
||||||
|
Rom newrom = rom;
|
||||||
|
newrom.Machine = new Machine(Path.GetFullPath(file), "");
|
||||||
|
|
||||||
|
string key = rom.Size + "-" + rom.CRC;
|
||||||
|
if (current.Files.ContainsKey(key))
|
||||||
|
{
|
||||||
|
current.Files[key].Add(newrom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<DatItem> temp = new List<DatItem>();
|
||||||
|
temp.Add(newrom);
|
||||||
|
current.Files.Add(key, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise, attempt to extract the files to the temporary directory
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool encounteredErrors = ArchiveTools.ExtractArchive(file, tempSubDir, archiveScanLevel, logger);
|
||||||
|
|
||||||
|
// If the file was an archive and was extracted successfully, check it
|
||||||
|
if (!encounteredErrors)
|
||||||
|
{
|
||||||
|
logger.Verbose(Path.GetFileName(file) + " treated like an archive");
|
||||||
|
List<string> extracted = Directory.EnumerateFiles(tempSubDir, "*", SearchOption.AllDirectories).ToList();
|
||||||
|
Parallel.ForEach(extracted,
|
||||||
|
new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism },
|
||||||
|
entry =>
|
||||||
|
{
|
||||||
|
Rom rom = FileTools.GetFileInfo(entry, logger, noMD5: quickScan, noSHA1: quickScan, header: headerToCheckAgainst);
|
||||||
|
rom.Machine = new Machine(Path.GetFullPath(file), "");
|
||||||
|
|
||||||
|
string key = rom.Size + "-" + rom.CRC;
|
||||||
|
if (current.Files.ContainsKey(key))
|
||||||
|
{
|
||||||
|
current.Files[key].Add(rom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<DatItem> temp = new List<DatItem>();
|
||||||
|
temp.Add(rom);
|
||||||
|
current.Files.Add(key, temp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Otherwise, just get the info on the file itself
|
||||||
|
else if (File.Exists(file))
|
||||||
|
{
|
||||||
|
Rom rom = FileTools.GetFileInfo(file, logger, noMD5: quickScan, noSHA1: quickScan, header: headerToCheckAgainst);
|
||||||
|
rom.Name = Path.GetFullPath(file);
|
||||||
|
|
||||||
|
string key = rom.Size + "-" + rom.CRC;
|
||||||
|
if (current.Files.ContainsKey(key))
|
||||||
|
{
|
||||||
|
current.Files[key].Add(rom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<DatItem> temp = new List<DatItem>();
|
||||||
|
temp.Add(rom);
|
||||||
|
current.Files.Add(key, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now delete the temp directory
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.Delete(tempSubDir, true);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.User("Getting hash information complete in: " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// Create a mapping from destination file to source file
|
||||||
|
Dictionary<DatItem, DatItem> toFromMap = new Dictionary<DatItem, DatItem>();
|
||||||
|
|
||||||
|
#region Find all required files for rebuild
|
||||||
|
|
||||||
|
logger.User("Determining files to rebuild");
|
||||||
|
start = DateTime.Now;
|
||||||
|
|
||||||
|
// Order the DATs by hash first to make things easier
|
||||||
|
BucketByCRC(false, logger, output: false);
|
||||||
|
current.BucketByCRC(false, logger, output: false);
|
||||||
|
|
||||||
|
// Now loop over and find all files that need to be rebuilt
|
||||||
|
List<string> keys = current.Files.Keys.ToList();
|
||||||
|
foreach (string key in keys)
|
||||||
|
{
|
||||||
|
// If the input DAT doesn't have the key, then nothing from the current DAT are there
|
||||||
|
if (!Files.ContainsKey(key))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we try to find duplicates
|
||||||
|
List<DatItem> datItems = current.Files[key];
|
||||||
|
foreach (Rom rom in datItems)
|
||||||
|
{
|
||||||
|
List<DatItem> found = rom.GetDuplicates(this, logger, false);
|
||||||
|
|
||||||
|
// Now add all of the duplicates mapped to the current file
|
||||||
|
foreach (Rom mid in found)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toFromMap.Add(mid, rom);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.User("Determining complete in: " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// Now bucket the list of keys by game so that we can rebuild properly
|
||||||
|
SortedDictionary<string, List<DatItem>> keysGroupedByGame = DatFile.BucketListByGame(toFromMap.Keys.ToList(), false, true, logger, output: false);
|
||||||
|
|
||||||
|
#region Rebuild games in order
|
||||||
|
|
||||||
|
logger.User("Rebuilding all files to " + (toFolder ? "directory" : (tgz ? "TorrentGZ" : "TorrentZip")));
|
||||||
|
start = DateTime.Now;
|
||||||
|
|
||||||
|
// Now loop through the keys and create the correct output items
|
||||||
|
List<string> games = keysGroupedByGame.Keys.ToList();
|
||||||
|
foreach (string game in games)
|
||||||
|
{
|
||||||
|
// Define the temporary directory
|
||||||
|
string tempSubDir = Path.GetFullPath(Path.Combine(tempDir, Path.GetRandomFileName())) + Path.DirectorySeparatorChar;
|
||||||
|
|
||||||
|
// Create an empty list for getting paths for rebuilding
|
||||||
|
List<string> pathsToFiles = new List<string>();
|
||||||
|
|
||||||
|
// Loop through all of the matched items in the game
|
||||||
|
List<DatItem> itemsInGame = keysGroupedByGame[game];
|
||||||
|
List<Rom> romsInGame = new List<Rom>();
|
||||||
|
foreach (Rom rom in itemsInGame)
|
||||||
|
{
|
||||||
|
// Get the rom that's mapped to this item
|
||||||
|
Rom source = (Rom)toFromMap[rom];
|
||||||
|
|
||||||
|
// If the file is in an archive, we need to treat it specially
|
||||||
|
string machinename = source.Machine.Name.ToLowerInvariant();
|
||||||
|
if (machinename.EndsWith(".7z")
|
||||||
|
|| machinename.EndsWith(".gz")
|
||||||
|
|| machinename.EndsWith(".rar")
|
||||||
|
|| machinename.EndsWith(".zip"))
|
||||||
|
{
|
||||||
|
pathsToFiles.Add(ArchiveTools.ExtractItem(source.Machine.Name, Path.GetFileName(source.Name), tempSubDir, logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we want to just add the full path
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pathsToFiles.Add(source.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now add the rom to the output list
|
||||||
|
romsInGame.Add(rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// And now rebuild accordingly
|
||||||
|
if (toFolder)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < romsInGame.Count; i++)
|
||||||
|
{
|
||||||
|
string infile = pathsToFiles[i];
|
||||||
|
Rom outrom = romsInGame[i];
|
||||||
|
string outfile = Path.Combine(outDir, outrom.Machine.Name, outrom.Machine.Name);
|
||||||
|
|
||||||
|
// Make sure the output folder is created
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(outfile));
|
||||||
|
|
||||||
|
// Now copy the file over
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Copy(infile, outfile);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tgz)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < itemsInGame.Count; i++)
|
||||||
|
{
|
||||||
|
string infile = pathsToFiles[i];
|
||||||
|
Rom outrom = romsInGame[i];
|
||||||
|
ArchiveTools.WriteTorrentGZ(infile, outDir, romba, logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ArchiveTools.WriteToArchive(pathsToFiles, outDir, romsInGame, logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
// And now clear the temp folder to get rid of any transient files
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.Delete(tempSubDir, true);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.User("Rebuilding complete in: " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process the DAT and verify the output directory
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="datFile">DAT to use to verify the directory</param>
|
||||||
|
/// <param name="inputs">List of input directories to compare against</param>
|
||||||
|
/// <param name="tempDir">Temporary directory for archive extraction</param>
|
||||||
|
/// <param name="headerToCheckAgainst">Populated string representing the name of the skipper to use, a blank string to use the first available checker, null otherwise</param>
|
||||||
|
/// <param name="logger">Logger object for file and console output</param>
|
||||||
|
/// <returns>True if verification was a success, false otherwise</returns>
|
||||||
|
public bool VerifyDirectory(List<string> inputs, string tempDir, string headerToCheckAgainst, Logger logger)
|
||||||
|
{
|
||||||
|
// First create or clean the temp directory
|
||||||
|
if (!Directory.Exists(tempDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(tempDir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileTools.CleanDirectory(tempDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We want the cross section of what's the folder and what's in the DAT. Right now, it just has what's in the DAT that's not in the folder
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Then, loop through and check each of the inputs
|
||||||
|
logger.User("Processing files:\n");
|
||||||
|
foreach (string input in inputs)
|
||||||
|
{
|
||||||
|
PopulateDatFromDir(input, false /* noMD5 */, false /* noSHA1 */, true /* bare */, false /* archivesAsFiles */,
|
||||||
|
true /* enableGzip */, false /* addBlanks */, false /* addDate */, tempDir /* tempDir */, false /* copyFiles */,
|
||||||
|
headerToCheckAgainst, 4 /* maxDegreeOfParallelism */, logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the fixdat
|
||||||
|
DatFile matched = (DatFile)CloneHeader();
|
||||||
|
matched.Files = new SortedDictionary<string, List<DatItem>>();
|
||||||
|
matched.FileName = "fixDat_" + matched.FileName;
|
||||||
|
matched.Name = "fixDat_" + matched.Name;
|
||||||
|
matched.Description = "fixDat_" + matched.Description;
|
||||||
|
matched.OutputFormat = OutputFormat.Logiqx;
|
||||||
|
|
||||||
|
// Now that all files are parsed, get only files found in directory
|
||||||
|
bool found = false;
|
||||||
|
foreach (List<DatItem> roms in Files.Values)
|
||||||
|
{
|
||||||
|
List<DatItem> newroms = DatItem.Merge(roms, logger);
|
||||||
|
foreach (Rom rom in newroms)
|
||||||
|
{
|
||||||
|
if (rom.SourceID == 99)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
string key = rom.Size + "-" + rom.CRC;
|
||||||
|
if (matched.Files.ContainsKey(key))
|
||||||
|
{
|
||||||
|
matched.Files[key].Add(rom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<DatItem> temp = new List<DatItem>();
|
||||||
|
temp.Add(rom);
|
||||||
|
matched.Files.Add(key, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now output the fixdat to the main folder
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
matched.WriteToFile("", logger, stats: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.User("No fixDat needed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Splitting
|
#region Splitting
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -845,16 +845,16 @@ namespace SabreTools.Helper.Dats
|
|||||||
/// <returns>True if it sorted correctly, false otherwise</returns>
|
/// <returns>True if it sorted correctly, false otherwise</returns>
|
||||||
public static bool Sort(ref List<DatItem> roms, bool norename)
|
public static bool Sort(ref List<DatItem> roms, bool norename)
|
||||||
{
|
{
|
||||||
try
|
roms.Sort(delegate (DatItem x, DatItem y)
|
||||||
{
|
{
|
||||||
roms.Sort(delegate (DatItem x, DatItem y)
|
try
|
||||||
{
|
{
|
||||||
NaturalComparer nc = new NaturalComparer();
|
NaturalComparer nc = new NaturalComparer();
|
||||||
if (x.SystemID == y.SystemID)
|
if (x.SystemID == y.SystemID)
|
||||||
{
|
{
|
||||||
if (x.SourceID == y.SourceID)
|
if (x.SourceID == y.SourceID)
|
||||||
{
|
{
|
||||||
if (x.Machine.Name == y.Machine.Name)
|
if (x.Machine != null && y.Machine != null && x.Machine.Name == y.Machine.Name)
|
||||||
{
|
{
|
||||||
if ((x.Type == ItemType.Rom || x.Type == ItemType.Disk) && (y.Type == ItemType.Rom || y.Type == ItemType.Disk))
|
if ((x.Type == ItemType.Rom || x.Type == ItemType.Disk) && (y.Type == ItemType.Rom || y.Type == ItemType.Disk))
|
||||||
{
|
{
|
||||||
@@ -886,14 +886,15 @@ namespace SabreTools.Helper.Dats
|
|||||||
return (norename ? nc.Compare(x.Machine.Name, y.Machine.Name) : x.SourceID - y.SourceID);
|
return (norename ? nc.Compare(x.Machine.Name, y.Machine.Name) : x.SourceID - y.SourceID);
|
||||||
}
|
}
|
||||||
return (norename ? nc.Compare(x.Machine.Name, y.Machine.Name) : x.SystemID - y.SystemID);
|
return (norename ? nc.Compare(x.Machine.Name, y.Machine.Name) : x.SystemID - y.SystemID);
|
||||||
});
|
}
|
||||||
return true;
|
catch (Exception)
|
||||||
}
|
{
|
||||||
catch (Exception)
|
// Absorb the error
|
||||||
{
|
return 0;
|
||||||
// Absorb the error
|
}
|
||||||
return false;
|
});
|
||||||
}
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ namespace SabreTools.Helper.Tools
|
|||||||
string realEntry = "";
|
string realEntry = "";
|
||||||
Stream ms = ExtractStream(input, entryName, out realEntry, logger);
|
Stream ms = ExtractStream(input, entryName, out realEntry, logger);
|
||||||
|
|
||||||
realEntry = Path.GetFullPath(Path.Combine(tempDir, realEntry));
|
realEntry = Path.Combine(Path.GetFullPath(tempDir), realEntry);
|
||||||
if (!Directory.Exists(Path.GetDirectoryName(realEntry)))
|
if (!Directory.Exists(Path.GetDirectoryName(realEntry)))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(realEntry));
|
Directory.CreateDirectory(Path.GetDirectoryName(realEntry));
|
||||||
@@ -217,6 +217,7 @@ namespace SabreTools.Helper.Tools
|
|||||||
int ilen;
|
int ilen;
|
||||||
while ((ilen = ms.Read(ibuffer, 0, _bufferSize)) > 0)
|
while ((ilen = ms.Read(ibuffer, 0, _bufferSize)) > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
fs.Write(ibuffer, 0, ilen);
|
fs.Write(ibuffer, 0, ilen);
|
||||||
fs.Flush();
|
fs.Flush();
|
||||||
}
|
}
|
||||||
@@ -786,7 +787,7 @@ namespace SabreTools.Helper.Tools
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the output archive name from the first rebuild rom
|
// Get the output archive name from the first rebuild rom
|
||||||
string archiveFileName = Path.Combine(outDir, roms[0].Machine.Name + ".zip");
|
string archiveFileName = Path.Combine(outDir, roms[0].Machine.Name + (roms[0].Machine.Name.EndsWith(".zip") ? "" : ".zip"));
|
||||||
|
|
||||||
// Set internal variables
|
// Set internal variables
|
||||||
Stream writeStream = null;
|
Stream writeStream = null;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -64,7 +64,7 @@ namespace SabreTools
|
|||||||
}
|
}
|
||||||
_logger.User("Organizing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
_logger.User("Organizing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
||||||
|
|
||||||
return FileTools.ConvertFiles(datdata, inputs, outDir, tempDir, tgz, romba, delete, asl, _logger);
|
return datdata.ConvertFiles(inputs, outDir, tempDir, tgz, romba, delete, asl, _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -336,7 +336,7 @@ namespace SabreTools
|
|||||||
}
|
}
|
||||||
_logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
_logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
||||||
|
|
||||||
FileTools.RebuildToOutput(datdata, inputs, outDir, tempDir, quickScan, date, toFolder, delete, tgz, romba, asl,
|
datdata.RebuildToOutput(inputs, outDir, tempDir, quickScan, date, toFolder, delete, tgz, romba, asl,
|
||||||
updateDat, headerToCheckAgainst, maxDegreeOfParallelism, _logger);
|
updateDat, headerToCheckAgainst, maxDegreeOfParallelism, _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,7 +686,7 @@ namespace SabreTools
|
|||||||
}
|
}
|
||||||
_logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
_logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
||||||
|
|
||||||
FileTools.VerifyDirectory(datdata, inputs, tempDir, headerToCheckAgainst, _logger);
|
datdata.VerifyDirectory(inputs, tempDir, headerToCheckAgainst, _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace SabreTools
|
|||||||
gz = 2,
|
gz = 2,
|
||||||
rar = 2,
|
rar = 2,
|
||||||
zip = 0;
|
zip = 0;
|
||||||
string header = "",
|
string header = null,
|
||||||
outDir = "",
|
outDir = "",
|
||||||
tempDir = "";
|
tempDir = "";
|
||||||
List<string> datfiles = new List<string>();
|
List<string> datfiles = new List<string>();
|
||||||
@@ -390,7 +390,7 @@ namespace SabreTools
|
|||||||
}
|
}
|
||||||
logger.User("Organizing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
logger.User("Organizing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
||||||
|
|
||||||
return FileTools.ConvertFiles(datdata, inputs, outDir, tempDir, tgz, romba, delete, asl, logger);
|
return datdata.ConvertFiles(inputs, outDir, tempDir, tgz, romba, delete, asl, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -430,7 +430,7 @@ namespace SabreTools
|
|||||||
}
|
}
|
||||||
logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
||||||
|
|
||||||
FileTools.RebuildToOutput(datdata, inputs, outDir, tempDir, quickScan, date, toFolder, delete, tgz, romba, asl, updateDat, headerToCheckAgainst, 4, logger);
|
datdata.RebuildToOutput(inputs, outDir, tempDir, quickScan, date, toFolder, delete, tgz, romba, asl, updateDat, headerToCheckAgainst, 4, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -457,7 +457,7 @@ namespace SabreTools
|
|||||||
}
|
}
|
||||||
logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
|
||||||
|
|
||||||
FileTools.VerifyDirectory(datdata, inputs, tempDir, headerToCheckAgainst, logger);
|
datdata.VerifyDirectory(inputs, tempDir, headerToCheckAgainst, logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user