Enable on-the-fly DAT writing for DATFromDir

This commit is contained in:
Matt Nadareski
2016-05-23 15:57:09 -07:00
parent 9184aa824e
commit 92d5337ac9
3 changed files with 142 additions and 87 deletions

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using SabreTools.Helper; using SabreTools.Helper;
@@ -213,10 +214,37 @@ namespace SabreTools
/// <remarks>Try to get the hashing multithreaded (either on a per-hash or per-file level)</remarks> /// <remarks>Try to get the hashing multithreaded (either on a per-hash or per-file level)</remarks>
public bool Start() public bool Start()
{ {
// Create an output dictionary for all found items // Double check to see what it needs to be named
_datdata.Roms = new Dictionary<string, List<RomData>>(); _basePath = (_inputs.Count > 0 ? (File.Exists(_inputs[0]) ? _inputs[0] : _inputs[0] + Path.DirectorySeparatorChar) : "");
_basePath = (_basePath != "" ? Path.GetFullPath(_basePath) : "");
if (_datdata.Name == "")
{
if (_inputs.Count > 1)
{
_datdata.Name = Environment.CurrentDirectory.Split(Path.DirectorySeparatorChar).Last();
}
else
{
if (_basePath.EndsWith(Path.DirectorySeparatorChar.ToString()))
{
_basePath = _basePath.Substring(0, _basePath.Length - 1);
}
_datdata.Name = _basePath.Split(Path.DirectorySeparatorChar).Last();
}
}
_datdata.Name = (_datdata.Name == "" ? "Default" : _datdata.Name);
_datdata.Description = (_datdata.Description == "" ? _datdata.Name + (_bare ? "" : " (" + _datdata.Date + ")") : _datdata.Description);
// Create and open the output file for writing
FileStream fs = File.Create(Style.CreateOutfileName(Environment.CurrentDirectory, _datdata));
StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
sw.AutoFlush = true;
// Write out the initial file header
Output.WriteHeader(sw, _datdata, _logger);
// Loop over each of the found paths, if any // Loop over each of the found paths, if any
string lastparent = null;
foreach (string path in _inputs) foreach (string path in _inputs)
{ {
// Set local paths and vars // Set local paths and vars
@@ -226,7 +254,7 @@ namespace SabreTools
// This is where the main loop would go // This is where the main loop would go
if (File.Exists(_basePath)) if (File.Exists(_basePath))
{ {
ProcessFile(_basePath); lastparent = ProcessFile(_basePath, sw);
} }
else if (Directory.Exists(_basePath)) else if (Directory.Exists(_basePath))
{ {
@@ -235,7 +263,7 @@ namespace SabreTools
// Process the files in the base folder first // Process the files in the base folder first
foreach (string item in Directory.EnumerateFiles(_basePath, "*", SearchOption.TopDirectoryOnly)) foreach (string item in Directory.EnumerateFiles(_basePath, "*", SearchOption.TopDirectoryOnly))
{ {
ProcessFile(item); lastparent = ProcessFile(item, sw, lastparent);
} }
// Then process each of the subfolders themselves // Then process each of the subfolders themselves
@@ -252,16 +280,21 @@ namespace SabreTools
foreach (string subitem in Directory.EnumerateFiles(item, "*", SearchOption.AllDirectories)) foreach (string subitem in Directory.EnumerateFiles(item, "*", SearchOption.AllDirectories))
{ {
items = true; items = true;
ProcessFile(subitem); lastparent = ProcessFile(subitem, sw, item);
} }
// If there were no subitems, add a "blank" game to to the set // If there were no subitems, add a "blank" game to to the set
if (!items) if (!items)
{ {
string actualroot = item.Remove(0, basePathBackup.Length);
RomData rom = new RomData RomData rom = new RomData
{ {
Name = "null", Name = "null",
Game = item.Remove(0, basePathBackup.Length), Game = (_datdata.Type == "SuperDAT" ?
_datdata.Name + (actualroot != "" && !actualroot.StartsWith(Path.DirectorySeparatorChar.ToString()) ?
Path.DirectorySeparatorChar.ToString() :
"") + actualroot :
actualroot),
Size = -1, Size = -1,
CRC = "null", CRC = "null",
MD5 = "null", MD5 = "null",
@@ -286,10 +319,15 @@ namespace SabreTools
{ {
if (Directory.EnumerateFiles(subdir, "*", SearchOption.AllDirectories).Count() == 0) if (Directory.EnumerateFiles(subdir, "*", SearchOption.AllDirectories).Count() == 0)
{ {
string actualroot = subdir.Remove(0, basePathBackup.Length);
RomData rom = new RomData RomData rom = new RomData
{ {
Name = "null", Name = "null",
Game = subdir.Remove(0, basePathBackup.Length), Game = (_datdata.Type == "SuperDAT" ?
_datdata.Name + (actualroot != "" && !actualroot.StartsWith(Path.DirectorySeparatorChar.ToString()) ?
Path.DirectorySeparatorChar.ToString() :
"") + actualroot :
actualroot),
Size = -1, Size = -1,
CRC = "null", CRC = "null",
MD5 = "null", MD5 = "null",
@@ -319,54 +357,50 @@ namespace SabreTools
} }
} }
// If we found nothing (error state), exit // Now output any empties to the stream
if (_datdata.Roms.Count == 0) foreach (List<RomData> roms in _datdata.Roms.Values)
{ {
return false; for (int i = 0; i < roms.Count; i++)
} {
RomData rom = roms[i];
// Double check to see what it needs to be named // If we're in a mode that doesn't allow for actual empty folders, add the blank info
if (_datdata.Name == "") if (_datdata.OutputFormat != OutputFormat.SabreDat && _datdata.OutputFormat != OutputFormat.MissFile)
{
if (_inputs.Count > 1)
{
_datdata.Name = Environment.CurrentDirectory.Split(Path.DirectorySeparatorChar).Last();
}
else
{
if (_basePath.EndsWith(Path.DirectorySeparatorChar.ToString()))
{ {
_basePath = _basePath.Substring(0, _basePath.Length - 1); rom.Type = "rom";
rom.Name = "-";
rom.Size = Constants.SizeZero;
rom.CRC = Constants.CRCZero;
rom.MD5 = Constants.MD5Zero;
rom.SHA1 = Constants.SHA1Zero;
} }
_datdata.Name = _basePath.Split(Path.DirectorySeparatorChar).Last();
}
}
_datdata.Name = (_datdata.Name == "" ? "Default" : _datdata.Name);
// If we're in a superdat, append the folder name to all game names // If we have a different game and we're not at the start of the list, output the end of last item
if (_datdata.Type == "SuperDAT") int last = 0;
{ if (lastparent != null && lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
List<string> keys = _datdata.Roms.Keys.ToList();
foreach (string key in keys)
{
List<RomData> newroms = new List<RomData>();
foreach (RomData rom in _datdata.Roms[key])
{ {
RomData newrom = rom; Output.WriteEndGame(sw, rom, new List<string>(), new List<string>(), lastparent, _datdata, 0, out last, _logger);
newrom.Game = _datdata.Name + (newrom.Game != "" &&
!newrom.Game.StartsWith(Path.DirectorySeparatorChar.ToString()) ? Path.DirectorySeparatorChar.ToString() : "") + newrom.Game;
newroms.Add(newrom);
} }
_datdata.Roms[key] = newroms;
}
_datdata.Name = _datdata.Name += " - SuperDAT"; // If we have a new game, output the beginning of the new item
if (lastparent == null || lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
{
Output.WriteStartGame(sw, rom, new List<string>(), lastparent, _datdata, 0, last, _logger);
}
// Write out the rom data
if (_datdata.OutputFormat != OutputFormat.SabreDat && _datdata.OutputFormat != OutputFormat.MissFile)
{
Output.WriteRomData(sw, rom, lastparent, _datdata, 0, _logger);
}
lastparent = rom.Game;
}
} }
_datdata.Description = (_datdata.Description == "" ? _datdata.Name + (_bare ? "" : " (" + _datdata.Date + ")") : _datdata.Description); // Now write the final piece and close the output stream
Output.WriteFooter(sw, _datdata, 0, _logger);
// Now write it all out as a DAT sw.Close();
Output.WriteDatfile(_datdata, Environment.CurrentDirectory, _logger);
return true; return true;
} }
@@ -375,7 +409,8 @@ namespace SabreTools
/// Check a given file for hashes, based on current settings /// Check a given file for hashes, based on current settings
/// </summary> /// </summary>
/// <param name="item">Filename of the item to be checked</param> /// <param name="item">Filename of the item to be checked</param>
private void ProcessFile(string item) /// <param name="sw">StreamWriter representing the output file</param>
private string ProcessFile(string item, StreamWriter sw, string lastparent = "")
{ {
// Special case for if we are in Romba mode (all names are supposed to be SHA-1 hashes) // Special case for if we are in Romba mode (all names are supposed to be SHA-1 hashes)
if (_datdata.Romba) if (_datdata.Romba)
@@ -386,7 +421,7 @@ namespace SabreTools
if (!Regex.IsMatch(datum, @"^[0-9a-f]{40}")) if (!Regex.IsMatch(datum, @"^[0-9a-f]{40}"))
{ {
_logger.Warning("Non SHA-1 filename found, skipping: '" + datum + "'"); _logger.Warning("Non SHA-1 filename found, skipping: '" + datum + "'");
return; return "";
} }
RomData rom = new RomData RomData rom = new RomData
@@ -398,20 +433,13 @@ namespace SabreTools
SHA1 = Path.GetFileNameWithoutExtension(item), SHA1 = Path.GetFileNameWithoutExtension(item),
}; };
string key = datum; int last = 0;
if (_datdata.Roms.ContainsKey(key)) Output.WriteStartGame(sw, rom, new List<string>(), "", _datdata, 0, 0, _logger);
{ Output.WriteRomData(sw, rom, "", _datdata, 0, _logger);
_datdata.Roms[key].Add(rom); Output.WriteEndGame(sw, rom, new List<string>(), new List<string>(), "", _datdata, 0, out last, _logger);
}
else
{
List<RomData> temp = new List<RomData>();
temp.Add(rom);
_datdata.Roms.Add(key, temp);
}
_logger.Log("File added: " + Path.GetFileNameWithoutExtension(item) + Environment.NewLine); _logger.Log("File added: " + Path.GetFileNameWithoutExtension(item) + Environment.NewLine);
return; return "";
} }
// Create the temporary output directory // Create the temporary output directory
@@ -480,6 +508,9 @@ namespace SabreTools
// If the file was an archive and was extracted successfully, check it // If the file was an archive and was extracted successfully, check it
if (!encounteredErrors) if (!encounteredErrors)
{ {
string lastgame = null;
int last = 0;
_logger.Log(Path.GetFileName(item) + " treated like an archive"); _logger.Log(Path.GetFileName(item) + " treated like an archive");
foreach (string entry in Directory.EnumerateFiles(_tempDir, "*", SearchOption.AllDirectories)) foreach (string entry in Directory.EnumerateFiles(_tempDir, "*", SearchOption.AllDirectories))
{ {
@@ -541,7 +572,11 @@ namespace SabreTools
RomData rom = new RomData RomData rom = new RomData
{ {
Type = "rom", Type = "rom",
Game = actualroot, Game = (_datdata.Type == "SuperDAT" ?
_datdata.Name + (actualroot != "" && !actualroot.StartsWith(Path.DirectorySeparatorChar.ToString()) ?
Path.DirectorySeparatorChar.ToString() :
"") + actualroot :
actualroot),
Name = actualitem, Name = actualitem,
Size = (new FileInfo(entry)).Length, Size = (new FileInfo(entry)).Length,
CRC = fileCRC, CRC = fileCRC,
@@ -549,19 +584,28 @@ namespace SabreTools
SHA1 = fileSHA1, SHA1 = fileSHA1,
}; };
string key = rom.Size + "-" + rom.CRC; // If we have a different game and we're not at the start of the list, output the end of last item
if (_datdata.Roms.ContainsKey(key)) if (lastgame != null && lastgame.ToLowerInvariant() != rom.Game.ToLowerInvariant())
{ {
_datdata.Roms[key].Add(rom); Output.WriteEndGame(sw, rom, new List<string>(), new List<string>(), lastgame, _datdata, 0, out last, _logger);
} }
else // If we have a different game and we're not at the start of the list, output the end of the last item
else if (lastparent != null && lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
{ {
List<RomData> temp = new List<RomData>(); Output.WriteEndGame(sw, rom, new List<string>(), new List<string>(), lastparent, _datdata, 0, out last, _logger);
temp.Add(rom);
_datdata.Roms.Add(key, temp);
} }
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.Game.ToLowerInvariant())
{
Output.WriteStartGame(sw, rom, new List<string>(), lastgame, _datdata, 0, last, _logger);
}
// Write out the rom data
Output.WriteRomData(sw, rom, lastgame, _datdata, 0, _logger);
_logger.User("File added: " + entry + Environment.NewLine); _logger.User("File added: " + entry + Environment.NewLine);
lastgame = rom.Game;
} }
// Delete the temp directory // Delete the temp directory
@@ -631,7 +675,11 @@ namespace SabreTools
RomData rom = new RomData RomData rom = new RomData
{ {
Type = "rom", Type = "rom",
Game = actualroot, Game = (_datdata.Type == "SuperDAT" ?
_datdata.Name + (actualroot != "" && !actualroot.StartsWith(Path.DirectorySeparatorChar.ToString()) ?
Path.DirectorySeparatorChar.ToString() :
"") + actualroot :
actualroot),
Name = actualitem, Name = actualitem,
Size = (new FileInfo(item)).Length, Size = (new FileInfo(item)).Length,
CRC = fileCRC, CRC = fileCRC,
@@ -639,25 +687,32 @@ namespace SabreTools
SHA1 = fileSHA1, SHA1 = fileSHA1,
}; };
string key = rom.Size + "-" + rom.CRC; // If we have a different game and we're not at the start of the list, output the end of last item
if (_datdata.Roms.ContainsKey(key)) int last = 0;
if (lastparent != null && lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
{ {
_datdata.Roms[key].Add(rom); Output.WriteEndGame(sw, rom, new List<string>(), new List<string>(), lastparent, _datdata, 0, out last, _logger);
}
else
{
List<RomData> temp = new List<RomData>();
temp.Add(rom);
_datdata.Roms.Add(key, temp);
} }
// If we have a new game, output the beginning of the new item
if (lastparent == null || lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
{
Output.WriteStartGame(sw, rom, new List<string>(), lastparent, _datdata, 0, last, _logger);
}
// Write out the rom data
Output.WriteRomData(sw, rom, lastparent, _datdata, 0, _logger);
_logger.User("File added: " + actualitem + Environment.NewLine); _logger.User("File added: " + actualitem + Environment.NewLine);
return rom.Game;
} }
catch (IOException ex) catch (IOException ex)
{ {
_logger.Error(ex.ToString()); _logger.Error(ex.ToString());
return null;
} }
} }
return "";
} }
} }
} }

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Mono.Data.Sqlite;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -35,12 +34,6 @@ namespace SabreTools.Helper
outDir = Environment.CurrentDirectory; outDir = Environment.CurrentDirectory;
} }
// Double check the outdir for the end delim
if (!outDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
{
outDir += Path.DirectorySeparatorChar;
}
// Create the output directory if it doesn't already exist // Create the output directory if it doesn't already exist
Directory.CreateDirectory(outDir); Directory.CreateDirectory(outDir);
@@ -66,8 +59,6 @@ namespace SabreTools.Helper
for (int index = 0; index < roms.Count; index++) for (int index = 0; index < roms.Count; index++)
{ {
RomData rom = roms[index]; RomData rom = roms[index];
string state = "";
List<string> newsplit = rom.Game.Split('\\').ToList(); List<string> newsplit = rom.Game.Split('\\').ToList();
// If we have a different game and we're not at the start of the list, output the end of last item // If we have a different game and we're not at the start of the list, output the end of last item

View File

@@ -1,4 +1,5 @@
using System.IO; using System;
using System.IO;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Xml; using System.Xml;
@@ -141,11 +142,19 @@ namespace SabreTools.Helper
public static string CreateOutfileName(string outDir, DatData datdata) public static string CreateOutfileName(string outDir, DatData datdata)
{ {
// Double check the outdir for the end delim
if (!outDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
{
outDir += Path.DirectorySeparatorChar;
}
string outfile = outDir + datdata.Description + (datdata.OutputFormat == OutputFormat.Xml || datdata.OutputFormat == OutputFormat.SabreDat ? ".xml" : ".dat"); string outfile = outDir + datdata.Description + (datdata.OutputFormat == OutputFormat.Xml || datdata.OutputFormat == OutputFormat.SabreDat ? ".xml" : ".dat");
outfile = (outfile.Contains(Path.DirectorySeparatorChar.ToString() + Path.DirectorySeparatorChar.ToString()) ? outfile = (outfile.Contains(Path.DirectorySeparatorChar.ToString() + Path.DirectorySeparatorChar.ToString()) ?
outfile.Replace(Path.DirectorySeparatorChar.ToString() + Path.DirectorySeparatorChar.ToString(), Path.DirectorySeparatorChar.ToString()) : outfile.Replace(Path.DirectorySeparatorChar.ToString() + Path.DirectorySeparatorChar.ToString(), Path.DirectorySeparatorChar.ToString()) :
outfile); outfile);
Console.WriteLine(outfile);
return outfile; return outfile;
} }
} }