diff --git a/.gitignore b/.gitignore
index 259b6791..c70037b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,9 +2,6 @@
/DATabase/obj
/DATabase/obj/Debug
/DATabase/obj/Release
-/DATabaseTwo/obj
-/DATabaseTwo/obj/Debug
-/DATabaseTwo/obj/Release
/DATFromDir/obj
/DATFromDir/obj/Debug
/DATFromDir/obj/Release
diff --git a/DATabase/DATabase.cs b/DATabase/DATabase.cs
index 7d5017cf..5488acbe 100644
--- a/DATabase/DATabase.cs
+++ b/DATabase/DATabase.cs
@@ -11,13 +11,29 @@ namespace SabreTools
///
/// Entry class for the DATabase application
///
+ ///
+ /// The following features are missing from DATabaseTwo with respect to the original DATabase:
+ /// - Source merging
+ /// - Custom DATs based on a system and a source
+ /// - Multi-source and multi-system DATs
+ ///
+ /// The following features need to (want to) be implemented in DATabaseTwo for further stability
+ /// - Import updating file locations and names when SHA-1 hashes are matched
+ /// - True duplicate DATs being removed from the import folder (SHA-1 matches)
+ /// - Generate All only generating DATs that have been recently updated
+ /// + This requires implementing a "last updated" data point for all DATs and tracking for "last generate" somewhere
+ /// - Impelement a ToSort folder for DATs that will place DATs in the correct subfolder on Import
+ ///
public class DATabase
{
- private static Logger logger;
- private static string _dbName = "DATabase.sqlite";
- //private static string _dbName = "SabreTools.sqlite";
+ // Private required variables
+ private static string _datroot = "DATS";
+ private static string _outroot = "Output";
+ private static string _dbName = "dats.sqlite";
private static string _connectionString = "Data Source=" + _dbName + ";Version = 3;";
+ private static Logger _logger;
+
///
/// Start menu or use supplied parameters
///
@@ -25,8 +41,8 @@ namespace SabreTools
public static void Main(string[] args)
{
// Perform initial setup and verification
- logger = new Logger(true, "database.log");
- logger.Start();
+ _logger = new Logger(true, "database.log");
+ _logger.Start();
DBTools.EnsureDatabase(_dbName, _connectionString);
Remapping.CreateRemappings();
Console.Clear();
@@ -35,7 +51,7 @@ namespace SabreTools
if ((new List(args)).Contains("--credits"))
{
Build.Credits();
- logger.Close();
+ _logger.Close();
return;
}
@@ -43,7 +59,7 @@ namespace SabreTools
if (args.Length == 0)
{
ShowMainMenu();
- logger.Close();
+ _logger.Close();
return;
}
@@ -66,6 +82,7 @@ namespace SabreTools
generate = false,
genall = false,
hashsplit = false,
+ ignore = false,
import = false,
inplace = false,
listsrc = false,
@@ -179,6 +196,10 @@ namespace SabreTools
case "--import":
import = true;
break;
+ case "-ig":
+ case "--ignore":
+ ignore = true;
+ break;
case "-ip":
case "--inplace":
inplace = true;
@@ -321,10 +342,10 @@ namespace SabreTools
}
else
{
- logger.Error("Invalid input detected: " + arg);
+ _logger.Error("Invalid input detected: " + arg);
Console.WriteLine();
Build.Help();
- logger.Close();
+ _logger.Close();
return;
}
break;
@@ -341,9 +362,9 @@ namespace SabreTools
if (help || !(add ^ (convertMiss || romba) ^ convertCMP ^ convertRC ^ convertSD ^ convertXml ^ extsplit ^ generate ^
genall ^ hashsplit ^ import ^ listsrc ^ listsys ^ (merge || diff) ^ rem ^ stats ^ trim))
{
- logger.Error("Only one feature switch is allowed at a time");
+ _logger.Error("Only one feature switch is allowed at a time");
Build.Help();
- logger.Close();
+ _logger.Close();
return;
}
@@ -351,9 +372,9 @@ namespace SabreTools
if (inputs.Count == 0 && ((convertMiss || romba) || convertCMP || convertRC || convertSD
|| convertXml || extsplit || hashsplit || import || (merge || diff) || stats || trim))
{
- logger.Error("This feature requires at least one input");
+ _logger.Error("This feature requires at least one input");
Build.Help();
- logger.Close();
+ _logger.Close();
return;
}
@@ -362,22 +383,21 @@ namespace SabreTools
// Import a file or folder
if (import)
{
- foreach (string input in inputs)
- {
- InitImport(input);
- }
+ InitImport(ignore);
}
// Generate a DAT
else if (generate)
{
- InitGenerate(systems, sources, outdir, norename, old);
+ InitImport(ignore);
+ InitGenerate(systems, norename, old);
}
// Generate all DATs
else if (genall)
{
- InitGenerateAll(outdir, norename, old);
+ InitImport(ignore);
+ InitGenerateAll(norename, old);
}
// List all available sources
@@ -507,7 +527,7 @@ namespace SabreTools
InitStats(inputs, single);
}
- logger.Close();
+ _logger.Close();
return;
}
@@ -529,8 +549,8 @@ namespace SabreTools
Make a selection:
1) Show command line usage
- 2) Import a DAT file or folder
- 3) Generate DAT files
+ 2) Check for new or changed DATs
+ 3) Generate System DATs
4) DAT file tools
5) List all available sources
6) List all available systems
@@ -593,21 +613,33 @@ Make a selection:
private static void ImportMenu()
{
string selection = "";
+ bool ignore = false;
while (selection.ToLowerInvariant() != "b")
{
Console.Clear();
- Build.Start("DATabase");
+ Build.Start("DATabaseTwo");
Console.WriteLine(@"IMPORT MENU
===========================
-Enter the name of a DAT file or folder containing DAT files
-or 'b' to go back to the previous menu:");
+Make a selection:
+
+ 1) " + (ignore ? "Enable new source prompt" : "Disable new source prompt") + @"
+ 2) Begin import process
+ B) Go back to the previous menu
+");
Console.Write("Enter selection: ");
selection = Console.ReadLine();
- if (selection.ToLowerInvariant() != "b")
+ switch (selection)
{
- InitImport(selection);
- Console.Write("\nPress any key to continue...");
- Console.ReadKey();
+ case "1":
+ ignore = !ignore;
+ break;
+ case "2":
+ Console.Clear();
+ InitImport(ignore);
+ Console.Write("\nPress any key to continue...");
+ Console.ReadKey();
+ ignore = false;
+ break;
}
}
return;
@@ -618,23 +650,21 @@ or 'b' to go back to the previous menu:");
///
private static void GenerateMenu()
{
- string selection = "", systems = "", sources = "", outdir = "";
+ string selection = "", system = "";
bool norename = false, old = false;
while (selection.ToLowerInvariant() != "b")
{
Console.Clear();
- Build.Start("DATabase");
+ Build.Start("DATabaseTwo");
Console.WriteLine(@"GENERATE MENU
===========================
Make a selection:
1) " + (norename ? "Enable game renaming" : "Disable game renaming") + @"
2) " + (old ? "Enable XML output" : "Enable ClrMamePro output") + @"
- 3) List of systems to generate from" + (systems != "" ? ": " + systems : "") + @"
- 4) List of sources to generate from" + (sources != "" ? ": " + sources : "") + @"
- 5) Enter an output folder" + (outdir != "" ? ":\n\t" + outdir : "") + @"
- 6) Generate the DAT file
- 7) Generate all available DAT files
+ 3) System ID to generate from" + (system != "" ? ": " + system : "") + @"
+ 4) Generate the DAT file for the specified system
+ 5) Generate all DAT files
B) Go back to the previous menu
");
Console.Write("Enter selection: ");
@@ -650,34 +680,23 @@ Make a selection:
case "3":
Console.Clear();
ListSystems();
- Console.Write("Please enter the systems separated by commas: ");
- systems = Console.ReadLine();
+ Console.Write("Please enter the System ID: ");
+ system = Console.ReadLine();
break;
case "4":
Console.Clear();
- ListSources();
- Console.Write("Please enter the sources separated by commas: ");
- sources = Console.ReadLine();
+ InitGenerate(system, norename, old);
+ Console.Write("\nPress any key to continue...");
+ Console.ReadKey();
+ system = "";
+ norename = false; old = false;
break;
case "5":
Console.Clear();
- Console.Write("Please enter a folder name: ");
- outdir = Console.ReadLine();
- break;
- case "6":
- Console.Clear();
- InitGenerate(systems, sources, outdir, norename, old);
+ InitGenerateAll(norename, old);
Console.Write("\nPress any key to continue...");
Console.ReadKey();
- systems = ""; sources = ""; outdir = "";
- norename = false; old = false;
- break;
- case "7":
- Console.Clear();
- InitGenerateAll(outdir, norename, old);
- Console.Write("\nPress any key to continue...");
- Console.ReadKey();
- systems = ""; sources = ""; outdir = "";
+ system = "";
norename = false; old = false;
break;
}
@@ -1267,7 +1286,7 @@ Make a selection:
break;
case "4":
Console.Clear();
- ListSystems(true);
+ ListSystems();
Console.Write("Please enter the system: ");
InitRemoveSystem(Console.ReadLine());
Console.Write("\nPress any key to continue...");
@@ -1284,73 +1303,38 @@ Make a selection:
#region Init Methods
///
- /// Wrap importing a file or folder into the database
+ /// Wrap importing and updating DATs
///
- /// File or folder to be imported
- private static void InitImport(string filename)
+ ///
+ private static void InitImport(bool ignore)
{
- Console.Clear();
-
- // Drag and drop means quotes; we don't want quotes
- filename = filename.Replace("\"", "");
-
- // Check to see if the second argument is a file that exists
- if (filename != "" && File.Exists(filename))
- {
- logger.User("Beginning import of " + filename);
- IImport imp = new Import(filename, _connectionString, logger);
- bool success = imp.ImportData();
- logger.User(filename + (success ? "" : " not") + " imported!");
- }
- // Check to see if the second argument is a directory that exists
- else if (filename != "" && Directory.Exists(filename))
- {
- foreach (string file in Directory.GetFiles(filename, "*", SearchOption.AllDirectories))
- {
- logger.User("Beginning import of " + file);
- IImport imp = new Import(file, _connectionString, logger);
- bool success = imp.ImportData();
- logger.User(file + (success ? "" : " not") + " imported!");
- }
- }
- else
- {
- logger.Error("I'm sorry but " + filename + " doesn't exist!");
- }
- return;
+ IImport imp = new ImportTwo(_datroot, _connectionString, _logger, ignore);
+ imp.ImportData();
}
///
- /// Wrap generating a DAT from the database
+ /// Wrap generating a DAT from the library
///
- /// Comma-separated list of systems to be included in the DAT (blank means all)
- /// Comma-separated list of sources to be included in the DAT (blank means all)
+ /// System ID to be used in the DAT (blank means all)
/// True if files should not be renamed with system and/or source in merged mode (default false)
/// True if the output file should be in ClrMamePro format (default false)
- private static void InitGenerate(string systems, string sources, string outdir, bool norename, bool old)
+ private static void InitGenerate(string systemid, bool norename, bool old)
{
- IGenerate gen = new Generate(systems, sources, outdir, _connectionString, logger, norename, old);
+ IGenerate gen = new GenerateTwo(systemid, "" /* sourceid */, _datroot, _outroot, _connectionString, _logger, norename, old);
gen.Export();
- return;
}
///
- /// Wrap generating all standard DATs from the database
+ /// Wrap generating all standard DATs from the library
///
- /// True if files should not be renamed with system and/or source in merged mode (default false)
- /// True if the output file should be in ClrMamePro format (default false)
- private static void InitGenerateAll(string outdir, bool norename, bool old)
+ private static void InitGenerateAll(bool norename, bool old)
{
- string actualdir = (outdir == "" ? Environment.CurrentDirectory + Path.DirectorySeparatorChar :
- (!outdir.EndsWith(Path.DirectorySeparatorChar.ToString()) ? outdir + Path.DirectorySeparatorChar : outdir));
- outdir = actualdir + "temp" + Path.DirectorySeparatorChar;
-
- // Generate system-merged
- string query = "SELECT DISTINCT systems.id FROM systems JOIN games ON systems.id=games.system ORDER BY systems.manufacturer, systems.system";
- //string query = "SELECT DISTINCT system.id FROM system JOIN gamesystem ON system.id=gamesystem.systemid ORDER BY system.manufacturer, system.name";
+ List systems = new List();
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
{
dbc.Open();
+
+ string query = "SELECT id FROM system";
using (SqliteCommand slc = new SqliteCommand(query, dbc))
{
using (SqliteDataReader sldr = slc.ExecuteReader())
@@ -1358,103 +1342,24 @@ Make a selection:
// If nothing is found, tell the user and exit
if (!sldr.HasRows)
{
- logger.Error("No systems found! Please add a source and then try again.");
+ _logger.Warning("No systems found! Please add a system and then try again.");
return;
}
while (sldr.Read())
{
- InitGenerate(sldr.GetInt32(0).ToString(), "", outdir, norename, old);
-
- // Generate custom
- string squery = @"SELECT DISTINCT sources.id
- FROM systems
- JOIN games
- ON systems.id=games.system
- JOIN sources
- ON games.source=sources.id
- WHERE systems.id=" + sldr.GetInt32(0).ToString() + @"
- ORDER BY sources.name";
- /*
- string squery = @"SELECT DISTINCT source.id
- FROM system
- JOIN gamesystem
- ON system.id=gamesystem.systemid
- JOIN gamesource
- ON gamesystem.game=gamesource.game
- JOIN source
- ON gamesource.sourceid=source.id
- WHERE system.id=" + sldr.GetInt32(0).ToString() + @"
- ORDER BY source.name";
- */
-
- using (SqliteCommand sslc = new SqliteCommand(squery, dbc))
- {
- using (SqliteDataReader ssldr = sslc.ExecuteReader())
- {
- // If nothing is found, tell the user and exit
- if (!ssldr.HasRows)
- {
- logger.Error("No sources found! Please add a source and then try again.");
- return;
- }
-
- while (ssldr.Read())
- {
- InitGenerate(sldr.GetInt32(0).ToString(), ssldr.GetInt32(0).ToString(), outdir, norename, old);
- }
- }
- }
+ systems.Add(sldr.GetInt32(0).ToString());
}
}
}
- // Generate source-merged
- query = "SELECT DISTINCT sources.id, sources.name FROM sources JOIN games ON sources.id=games.source ORDER BY sources.name";
- //query = "SELECT DISTINCT source.id, source.name FROM source JOIN gamesource ON source.id=gamesource.sourceid ORDER BY source.name";
-
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
+ // Loop through the inputs
+ foreach (string system in systems)
{
- using (SqliteDataReader sldr = slc.ExecuteReader())
- {
- // If nothing is found, tell the user and exit
- if (!sldr.HasRows)
- {
- logger.Error("No sources found! Please add a source and then try again.");
- return;
- }
-
- while (sldr.Read())
- {
- InitGenerate("", sldr.GetInt32(0).ToString(), outdir, norename, old);
- }
- }
+ _logger.User("Generating DAT for system id " + system);
+ InitGenerate(system, norename, old);
}
}
-
- // Generate MEGAMERGED
- InitGenerate("", "", outdir, norename, old);
-
- // Zip up all of the files that were generated
- logger.User("Creating zip archive");
- ZipArchive zip = ZipFile.Open(actualdir + "dats-" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".zip", ZipArchiveMode.Create);
- foreach (String filename in Directory.EnumerateFiles(outdir))
- {
- if (filename.EndsWith(".xml") || filename.EndsWith(".dat"))
- {
- string internalFolder = (filename.Contains("ALL (Merged") ? "" :
- filename.Contains("Merged") ? "merged-system/" :
- filename.Contains("ALL") ? "merged-source/" : "custom/");
- zip.CreateEntryFromFile(filename, internalFolder + Path.GetFileName(filename), CompressionLevel.Optimal);
- }
- }
- zip.Dispose();
- logger.User("Zip archive created!");
-
- // Remove all of the DATs from the folder
- Directory.Delete(outdir, true);
-
- return;
}
///
@@ -1474,13 +1379,13 @@ Make a selection:
if (File.Exists(filename))
{
- logger.User("Converting \"" + Path.GetFileName(filename) + "\"");
+ _logger.User("Converting \"" + Path.GetFileName(filename) + "\"");
DatData datdata = new DatData
{
OutputFormat = outputFormat,
MergeRoms = false,
};
- datdata = RomManipulation.Parse(filename, 0, 0, datdata, logger, true);
+ datdata = RomManipulation.Parse(filename, 0, 0, datdata, _logger, true);
// Sometimes the description doesn't match the filename, change this
if (datdata.Description != Path.GetFileNameWithoutExtension(filename))
@@ -1495,7 +1400,7 @@ Make a selection:
datdata.Description += ".new";
}
- Output.WriteDatfile(datdata, (outdir == "" ? Path.GetDirectoryName(filename) : outdir), logger);
+ Output.WriteDatfile(datdata, (outdir == "" ? Path.GetDirectoryName(filename) : outdir), _logger);
}
else if (Directory.Exists(filename))
{
@@ -1503,13 +1408,13 @@ Make a selection:
foreach (string file in Directory.EnumerateFiles(filename, "*", SearchOption.AllDirectories))
{
- logger.User("Converting \"" + Path.GetFullPath(file).Remove(0, filename.Length) + "\"");
+ _logger.User("Converting \"" + Path.GetFullPath(file).Remove(0, filename.Length) + "\"");
DatData datdata = new DatData
{
OutputFormat = outputFormat,
MergeRoms = false,
};
- datdata = RomManipulation.Parse(file, 0, 0, datdata, logger, true);
+ datdata = RomManipulation.Parse(file, 0, 0, datdata, _logger, true);
// If the extension matches, append ".new" to the filename
string extension = (datdata.OutputFormat == OutputFormat.Xml || datdata.OutputFormat == OutputFormat.SabreDat ? ".xml" : ".dat");
@@ -1518,12 +1423,12 @@ Make a selection:
datdata.FileName += ".new";
}
- Output.WriteDatfile(datdata, (outdir == "" ? Path.GetDirectoryName(file) : outdir + Path.GetDirectoryName(file).Remove(0, filename.Length - 1)), logger);
+ Output.WriteDatfile(datdata, (outdir == "" ? Path.GetDirectoryName(file) : outdir + Path.GetDirectoryName(file).Remove(0, filename.Length - 1)), _logger);
}
}
else
{
- logger.Error("I'm sorry but " + filename + " doesn't exist!");
+ _logger.Error("I'm sorry but " + filename + " doesn't exist!");
}
return;
}
@@ -1554,7 +1459,7 @@ Make a selection:
string name = Path.GetFileNameWithoutExtension(input) + "-miss";
// Read in the roms from the DAT and then write them to the file
- logger.User("Converting " + input);
+ _logger.User("Converting " + input);
DatData datdata = new DatData
{
OutputFormat = OutputFormat.MissFile,
@@ -1568,7 +1473,7 @@ Make a selection:
GameName = gamename,
Romba = romba,
};
- datdata = RomManipulation.Parse(input, 0, 0, datdata, logger);
+ datdata = RomManipulation.Parse(input, 0, 0, datdata, _logger);
datdata.FileName += "-miss";
datdata.Name += "-miss";
datdata.Description += "-miss";
@@ -1577,13 +1482,13 @@ Make a selection:
addext = (addext == "" || addext.StartsWith(".") ? addext : "." + addext);
repext = (repext == "" || repext.StartsWith(".") ? repext : "." + repext);
- Output.WriteDatfile(datdata, Path.GetDirectoryName(input), logger);
- logger.User(input + " converted to: " + name);
+ Output.WriteDatfile(datdata, Path.GetDirectoryName(input), _logger);
+ _logger.User(input + " converted to: " + name);
return;
}
else
{
- logger.Error("I'm sorry but " + input + "doesn't exist!");
+ _logger.Error("I'm sorry but " + input + "doesn't exist!");
}
}
@@ -1601,7 +1506,7 @@ Make a selection:
if (input != "" && (File.Exists(input) || Directory.Exists(input)))
{
- TrimMerge sg = new TrimMerge(input, root, rename, force, logger);
+ TrimMerge sg = new TrimMerge(input, root, rename, force, _logger);
sg.Process();
return;
}
@@ -1641,7 +1546,7 @@ Make a selection:
}
catch (PathTooLongException)
{
- logger.Warning("The path for " + file + " was too long");
+ _logger.Warning("The path for " + file + " was too long");
}
}
}
@@ -1653,12 +1558,12 @@ Make a selection:
}
catch (PathTooLongException)
{
- logger.Warning("The path for " + input.Replace("\"", "") + " was too long");
+ _logger.Warning("The path for " + input.Replace("\"", "") + " was too long");
}
}
}
- MergeDiff md = new MergeDiff(newInputs, name, desc, cat, version, author, diff, dedup, bare, forceunpack, old, superdat, cascade, inplace, outdir, logger);
+ MergeDiff md = new MergeDiff(newInputs, name, desc, cat, version, author, diff, dedup, bare, forceunpack, old, superdat, cascade, inplace, outdir, _logger);
md.Process();
}
@@ -1681,16 +1586,16 @@ Make a selection:
{
if (exta == "" || extb == "")
{
- logger.Warning("Two extensions are needed to split a DAT!");
+ _logger.Warning("Two extensions are needed to split a DAT!");
return;
}
- ExtSplit es = new ExtSplit(input, exta, extb, outdir, logger);
+ ExtSplit es = new ExtSplit(input, exta, extb, outdir, _logger);
es.Split();
return;
}
else
{
- logger.Log("I'm sorry but " + input + "doesn't exist!");
+ _logger.Log("I'm sorry but " + input + "doesn't exist!");
}
}
@@ -1709,7 +1614,7 @@ Make a selection:
{
if (!File.Exists(input.Replace("\"", "")) && !Directory.Exists(input.Replace("\"", "")))
{
- logger.Error(input + " is not a valid file or folder!");
+ _logger.Error(input + " is not a valid file or folder!");
Console.WriteLine();
Build.Help();
return;
@@ -1717,7 +1622,7 @@ Make a selection:
}
// If so, run the program
- HashSplit hs = new HashSplit(inputs, outdir, logger);
+ HashSplit hs = new HashSplit(inputs, outdir, _logger);
hs.Split();
}
@@ -1761,11 +1666,11 @@ Make a selection:
{
if (DBTools.AddSource(name, url, _connectionString))
{
- logger.Log("Source " + name + " added!");
+ _logger.Log("Source " + name + " added!");
}
else
{
- logger.Error("Source " + name + " could not be added!");
+ _logger.Error("Source " + name + " could not be added!");
}
}
@@ -1780,16 +1685,16 @@ Make a selection:
{
if (DBTools.RemoveSource(srcid, _connectionString))
{
- logger.Log("Source '" + srcid + "' removed!");
+ _logger.Log("Source '" + srcid + "' removed!");
}
else
{
- logger.Error("Source with id '" + srcid + "' could not be removed.");
+ _logger.Error("Source with id '" + srcid + "' could not be removed.");
}
}
else
{
- logger.Error("Invalid input");
+ _logger.Error("Invalid input");
}
}
@@ -1802,11 +1707,11 @@ Make a selection:
{
if (DBTools.AddSystem(manufacturer, system, _connectionString))
{
- logger.Log("System " + manufacturer + " - " + system + " added!");
+ _logger.Log("System " + manufacturer + " - " + system + " added!");
}
else
{
- logger.Error("System " + manufacturer + " - " + system + " could not be added!");
+ _logger.Error("System " + manufacturer + " - " + system + " could not be added!");
}
}
@@ -1821,27 +1726,72 @@ Make a selection:
{
if (DBTools.RemoveSystem(sysid, _connectionString))
{
- logger.Log("System '" + sysid + "' removed!");
+ _logger.Log("System '" + sysid + "' removed!");
}
else
{
- logger.Error("System with id '" + sysid + "' could not be removed.");
+ _logger.Error("System with id '" + sysid + "' could not be removed.");
}
}
else
{
- logger.Error("Invalid input");
+ _logger.Error("Invalid input");
}
}
#endregion
- #region Listing Methods
+ #region Helper methods
+
+ ///
+ /// Perform initial setup for the program
+ ///
+ private static void Setup()
+ {
+ Remapping.CreateRemappings();
+ Build.Start("DATabaseTwo");
+
+ // Perform initial database and folder setup
+ if (!Directory.Exists(_datroot))
+ {
+ Directory.CreateDirectory(_datroot);
+ }
+ if (!Directory.Exists(_outroot))
+ {
+ Directory.CreateDirectory(_outroot);
+ }
+ DBTools.EnsureDatabase(_dbName, _connectionString);
+
+ using (SqliteConnection dbc = new SqliteConnection(_connectionString))
+ {
+ dbc.Open();
+
+ string query = "SELECT * FROM system";
+ using (SqliteCommand slc = new SqliteCommand(query, dbc))
+ {
+ using (SqliteDataReader sldr = slc.ExecuteReader())
+ {
+ while (sldr.Read())
+ {
+ int systemid = sldr.GetInt32(0);
+ string system = _datroot + Path.DirectorySeparatorChar + sldr.GetString(1) + " - " + sldr.GetString(2);
+ system = system.Trim();
+
+ if (!Directory.Exists(system))
+ {
+ Directory.CreateDirectory(system);
+ }
+ }
+ }
+ }
+ }
+ }
///
/// List sources in the database
///
/// True to list all sources regardless if there is a game associated or not
+ /// This does not have an analogue in DATabaseTwo
private static void ListSources(bool all = false)
{
string query = @"
@@ -1858,7 +1808,7 @@ ORDER BY sources.name COLLATE NOCASE";
// If nothing is found, tell the user and exit
if (!sldr.HasRows)
{
- logger.Warning("No sources found! Please add a source and then try again.");
+ _logger.Warning("No sources found! Please add a source and then try again.");
return;
}
@@ -1876,13 +1826,12 @@ ORDER BY sources.name COLLATE NOCASE";
///
/// List systems in the database
///
- /// True to list all systems regardless if there is a game associated or not
- private static void ListSystems(bool all = false)
+ private static void ListSystems()
{
string query = @"
-SELECT DISTINCT systems.id, systems.manufacturer, systems.system
-FROM systems " + (!all ? "JOIN games ON systems.id=games.system" : "") + @"
-ORDER BY systems.manufacturer, systems.system";
+SELECT DISTINCT system.id, system.manufacturer, system.name
+FROM system
+ORDER BY system.manufacturer, system.name";
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
{
dbc.Open();
@@ -1893,7 +1842,7 @@ ORDER BY systems.manufacturer, systems.system";
// If nothing is found, tell the user and exit
if (!sldr.HasRows)
{
- logger.Warning("No systems found! Please add a system and then try again.");
+ _logger.Warning("No systems found! Please add a system and then try again.");
return;
}
diff --git a/DATabase/DATabase.csproj b/DATabase/DATabase.csproj
index ee7dd6f9..b138ca68 100644
--- a/DATabase/DATabase.csproj
+++ b/DATabase/DATabase.csproj
@@ -105,10 +105,12 @@
-
+
+
-
+
+
diff --git a/DATabase/Generate.cs b/DATabase/ImportExport/Generate.cs
similarity index 100%
rename from DATabase/Generate.cs
rename to DATabase/ImportExport/Generate.cs
diff --git a/DATabaseTwo/GenerateTwo.cs b/DATabase/ImportExport/GenerateTwo.cs
similarity index 100%
rename from DATabaseTwo/GenerateTwo.cs
rename to DATabase/ImportExport/GenerateTwo.cs
diff --git a/DATabase/Import.cs b/DATabase/ImportExport/Import.cs
similarity index 97%
rename from DATabase/Import.cs
rename to DATabase/ImportExport/Import.cs
index 8c5b1e50..fe7b778c 100644
--- a/DATabase/Import.cs
+++ b/DATabase/ImportExport/Import.cs
@@ -1,653 +1,653 @@
-using System.Collections.Generic;
-using Mono.Data.Sqlite;
-using System.IO;
-using System.Text.RegularExpressions;
-
-using SabreTools.Helper;
-
-namespace SabreTools
-{
- ///
- /// Import data into the database from existing DATs
- ///
- public class Import : IImport
- {
- // Private instance variables
- private string _filepath;
- private string _connectionString;
- private Logger _logger;
-
- ///
- /// Initialize an Import object with the given information
- ///
- /// Path to the file that is going to be imported
- /// Connection string for SQLite
- /// Logger object for file or console output
- public Import(string filepath, string connectionString, Logger logger)
- {
- _filepath = filepath.Replace("\"", "");
- _connectionString = connectionString;
- _logger = logger;
- }
-
- ///
- /// Import the data from file into the database
- ///
- /// True if the data was imported, false otherwise
- public bool ImportData()
- {
- // If file doesn't exist, error and return
- if (!File.Exists(_filepath))
- {
- _logger.Error("File '" + _filepath + "' doesn't exist");
- return false;
- }
-
- // Determine which dattype we have
- string filename = Path.GetFileName(_filepath);
- GroupCollection fileinfo;
- DatType type = DatType.none;
-
- if (Regex.IsMatch(filename, Constants.NonGoodPattern))
- {
- fileinfo = Regex.Match(filename, Constants.NonGoodPattern).Groups;
- type = DatType.NonGood;
- }
- else if (Regex.IsMatch(filename, Constants.NonGoodSpecialPattern))
- {
- fileinfo = Regex.Match(filename, Constants.NonGoodSpecialPattern).Groups;
- type = DatType.NonGood;
- }
- else if (Regex.IsMatch(filename, Constants.GoodPattern))
- {
- fileinfo = Regex.Match(filename, Constants.GoodPattern).Groups;
- type = DatType.Good;
- }
- else if (Regex.IsMatch(filename, Constants.GoodXmlPattern))
- {
- fileinfo = Regex.Match(filename, Constants.GoodXmlPattern).Groups;
- type = DatType.Good;
- }
- else if (Regex.IsMatch(filename, Constants.MaybeIntroPattern))
- {
- fileinfo = Regex.Match(filename, Constants.MaybeIntroPattern).Groups;
- type = DatType.MaybeIntro;
- }
- else if (Regex.IsMatch(filename, Constants.NoIntroPattern))
- {
- fileinfo = Regex.Match(filename, Constants.NoIntroPattern).Groups;
- type = DatType.NoIntro;
- }
- // For numbered DATs only
- else if (Regex.IsMatch(filename, Constants.NoIntroNumberedPattern))
- {
- fileinfo = Regex.Match(filename, Constants.NoIntroNumberedPattern).Groups;
- type = DatType.NoIntro;
- }
- // For N-Gage and Gizmondo only
- else if (Regex.IsMatch(filename, Constants.NoIntroSpecialPattern))
- {
- fileinfo = Regex.Match(filename, Constants.NoIntroSpecialPattern).Groups;
- type = DatType.NoIntro;
- }
- else if (Regex.IsMatch(filename, Constants.RedumpPattern))
- {
- fileinfo = Regex.Match(filename, Constants.RedumpPattern).Groups;
- type = DatType.Redump;
- }
- // For special BIOSes only
- else if (Regex.IsMatch(filename, Constants.RedumpBiosPattern))
- {
- fileinfo = Regex.Match(filename, Constants.RedumpBiosPattern).Groups;
- type = DatType.Redump;
- }
- else if (Regex.IsMatch(filename, Constants.TosecPattern))
- {
- fileinfo = Regex.Match(filename, Constants.TosecPattern).Groups;
- type = DatType.TOSEC;
- }
- else if (Regex.IsMatch(filename, Constants.TruripPattern))
- {
- fileinfo = Regex.Match(filename, Constants.TruripPattern).Groups;
- type = DatType.TruRip;
- }
- else if (Regex.IsMatch(filename, Constants.ZandroPattern))
- {
- filename = "Nintendo - Super Nintendo Entertainment System (Zandro " + File.GetLastWriteTime(_filepath).ToString("yyyyMMddHHmmss") + ").dat";
- fileinfo = Regex.Match(filename, Constants.DefaultPattern).Groups;
- type = DatType.Custom;
- }
- else if (Regex.IsMatch(filename, Constants.DefaultPattern))
- {
- fileinfo = Regex.Match(filename, Constants.DefaultPattern).Groups;
- type = DatType.Custom;
- }
- else if (Regex.IsMatch(filename, Constants.DefaultSpecialPattern))
- {
- fileinfo = Regex.Match(filename, Constants.DefaultSpecialPattern).Groups;
- type = DatType.Custom;
- }
- else if (Regex.IsMatch(filename, Constants.MamePattern))
- {
- fileinfo = Regex.Match(filename, Constants.MamePattern).Groups;
- type = DatType.MAME;
- }
- // If the type is still unmatched, the data can't be imported yet
- else
- {
- _logger.Warning("File " + filename + " cannot be imported at this time because it is not a known pattern.\nPlease try again with an unrenamed version.");
- return false;
- }
-
- _logger.Log("Type detected: " + type.ToString());
-
- // Check for and extract import information from the file name based on type
- string manufacturer = "";
- string system = "";
- string source = "";
- string datestring = "";
- string date = "";
-
- switch (type)
- {
- case DatType.Good:
- if (!Remapping.Good.ContainsKey(fileinfo[1].Value))
- {
- _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
- return false;
- }
- GroupCollection goodInfo = Regex.Match(Remapping.Good[fileinfo[1].Value], Constants.RemappedPattern).Groups;
-
- manufacturer = goodInfo[1].Value;
- system = goodInfo[2].Value;
- source = "Good";
- date = File.GetLastWriteTime(_filepath).ToString("yyyy-MM-dd HH:mm:ss");
- break;
- case DatType.MAME:
- if (!Remapping.MAME.ContainsKey(fileinfo[1].Value))
- {
- _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
- return false;
- }
- GroupCollection mameInfo = Regex.Match(Remapping.MAME[fileinfo[1].Value], Constants.RemappedPattern).Groups;
-
- manufacturer = mameInfo[1].Value;
- system = mameInfo[2].Value;
- source = "MAME";
- date = File.GetLastWriteTime(_filepath).ToString("yyyy-MM-dd HH:mm:ss");
- break;
- case DatType.MaybeIntro:
- if (!Remapping.MaybeIntro.ContainsKey(fileinfo[1].Value))
- {
- _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
- return false;
- }
- GroupCollection maybeIntroInfo = Regex.Match(Remapping.MaybeIntro[fileinfo[1].Value], Constants.RemappedPattern).Groups;
-
- manufacturer = maybeIntroInfo[1].Value;
- system = maybeIntroInfo[2].Value;
- source = "Maybe-Intro";
- datestring = fileinfo[2].Value;
- GroupCollection miDateInfo = Regex.Match(datestring, Constants.NoIntroSpecialDatePattern).Groups;
- date = miDateInfo[1].Value + "-" + miDateInfo[2].Value + "-" + miDateInfo[3].Value + " 00:00:00";
- break;
- case DatType.NoIntro:
- if (!Remapping.NoIntro.ContainsKey(fileinfo[1].Value))
- {
- _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
- return false;
- }
- GroupCollection nointroInfo = Regex.Match(Remapping.NoIntro[fileinfo[1].Value], Constants.RemappedPattern).Groups;
-
- manufacturer = nointroInfo[1].Value;
- system = nointroInfo[2].Value;
- source = "no-Intro";
- if (fileinfo.Count < 2)
- {
- date = File.GetLastWriteTime(_filepath).ToString("yyyy-MM-dd HH:mm:ss");
- }
- else if (Regex.IsMatch(fileinfo[2].Value, Constants.NoIntroDatePattern))
- {
- datestring = fileinfo[2].Value;
- GroupCollection niDateInfo = Regex.Match(datestring, Constants.NoIntroDatePattern).Groups;
- date = niDateInfo[1].Value + "-" + niDateInfo[2].Value + "-" + niDateInfo[3].Value + " " +
- niDateInfo[4].Value + ":" + niDateInfo[5].Value + ":" + niDateInfo[6].Value;
- }
- else
- {
- datestring = fileinfo[2].Value;
- GroupCollection niDateInfo = Regex.Match(datestring, Constants.NoIntroSpecialDatePattern).Groups;
- date = niDateInfo[1].Value + "-" + niDateInfo[2].Value + "-" + niDateInfo[3].Value + " 00:00:00";
- }
- break;
- case DatType.NonGood:
- if (!Remapping.NonGood.ContainsKey(fileinfo[1].Value))
- {
- _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
- return false;
- }
- GroupCollection nonGoodInfo = Regex.Match(Remapping.NonGood[fileinfo[1].Value], Constants.RemappedPattern).Groups;
-
- manufacturer = nonGoodInfo[1].Value;
- system = nonGoodInfo[2].Value;
- source = "NonGood";
- date = File.GetLastWriteTime(_filepath).ToString("yyyy-MM-dd HH:mm:ss");
- break;
- case DatType.Redump:
- if (!Remapping.Redump.ContainsKey(fileinfo[1].Value))
- {
- // Handle special case mappings found only in Redump
- fileinfo = Regex.Match(filename, Constants.RedumpBiosPattern).Groups;
-
- if (!Remapping.Redump.ContainsKey(fileinfo[1].Value))
- {
- _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
- return false;
- }
- }
- GroupCollection redumpInfo = Regex.Match(Remapping.Redump[fileinfo[1].Value], Constants.RemappedPattern).Groups;
-
- manufacturer = redumpInfo[1].Value;
- system = redumpInfo[2].Value;
- source = "Redump";
- datestring = fileinfo[2].Value;
- if (Regex.IsMatch(datestring, Constants.RedumpDatePattern))
- {
- GroupCollection rdDateInfo = Regex.Match(datestring, Constants.RedumpDatePattern).Groups;
- date = rdDateInfo[1].Value + "-" + rdDateInfo[2].Value + "-" + rdDateInfo[3].Value + " " +
- rdDateInfo[4].Value + ":" + rdDateInfo[5].Value + ":" + rdDateInfo[6].Value;
- }
- else
- {
- GroupCollection rdDateInfo = Regex.Match(datestring, Constants.TosecDatePattern).Groups;
- date = rdDateInfo[1].Value + "-" + rdDateInfo[2].Value + "-" + rdDateInfo[3].Value + " 00:00:00";
- }
-
- break;
- case DatType.TOSEC:
- if (!Remapping.TOSEC.ContainsKey(fileinfo[1].Value))
- {
- // Handle special case mappings found only in TOSEC
- fileinfo = Regex.Match(filename, Constants.TosecSpecialPatternA).Groups;
-
- if (!Remapping.TOSEC.ContainsKey(fileinfo[1].Value))
- {
- fileinfo = Regex.Match(filename, Constants.TosecSpecialPatternB).Groups;
-
- if (!Remapping.TOSEC.ContainsKey(fileinfo[1].Value))
- {
- _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
- return false;
- }
- }
- }
- GroupCollection tosecInfo = Regex.Match(Remapping.TOSEC[fileinfo[1].Value], Constants.RemappedPattern).Groups;
-
- manufacturer = tosecInfo[1].Value;
- system = tosecInfo[2].Value;
- source = "TOSEC";
- datestring = fileinfo[2].Value;
- GroupCollection toDateInfo = Regex.Match(datestring, Constants.TosecDatePattern).Groups;
- date = toDateInfo[1].Value + "-" + toDateInfo[2].Value + "-" + toDateInfo[3].Value + " 00:00:00";
- break;
- case DatType.TruRip:
- if (!Remapping.TruRip.ContainsKey(fileinfo[1].Value))
- {
- _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
- return false;
- }
- GroupCollection truripInfo = Regex.Match(Remapping.TruRip[fileinfo[1].Value], Constants.RemappedPattern).Groups;
-
- manufacturer = truripInfo[1].Value;
- system = truripInfo[2].Value;
- source = "trurip";
- date = File.GetLastWriteTime(_filepath).ToString("yyyy-MM-dd HH:mm:ss");
- break;
- case DatType.Custom:
- default:
- manufacturer = fileinfo[1].Value;
- system = fileinfo[2].Value;
- source = fileinfo[3].Value;
- datestring = fileinfo[4].Value;
-
- GroupCollection cDateInfo = Regex.Match(datestring, Constants.DefaultDatePattern).Groups;
- date = cDateInfo[1].Value + "-" + cDateInfo[2].Value + "-" + cDateInfo[3].Value + " " +
- cDateInfo[4].Value + ":" + cDateInfo[5].Value + ":" + cDateInfo[6].Value;
- break;
- }
-
- // Check to make sure that the manufacturer and system are valid according to the database
- int sysid = -1;
- string query = "SELECT id FROM systems WHERE manufacturer='" + manufacturer + "' AND system='" + system +"'";
- //string query = "SELECT id FROM system WHERE manufacturer='" + manufacturer + "' AND name='" + system + "'";
- using (SqliteConnection dbc = new SqliteConnection(_connectionString))
- {
- dbc.Open();
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
- {
- using (SqliteDataReader sldr = slc.ExecuteReader())
- {
- // If nothing is found, tell the user and exit
- if (!sldr.HasRows)
- {
- _logger.Error("No suitable system for '" + filename + "' (" + manufacturer + " " + system + ") found! Please add the system and then try again.");
- return false;
- }
-
- // Set the system ID from the first found value
- sldr.Read();
- sysid = sldr.GetInt32(0);
- }
- }
- }
-
- // Check to make sure that the source is valid according to the database
- int srcid = -1;
- query = "SELECT id FROM sources WHERE name='" + source + "'";
- //query = "SELECT id FROM source WHERE name='" + source + "'";
- using (SqliteConnection dbc = new SqliteConnection(_connectionString))
- {
- dbc.Open();
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
- {
- using (SqliteDataReader sldr = slc.ExecuteReader())
- {
- // If nothing is found, tell the user and exit
- if (!sldr.HasRows)
- {
- _logger.Error("No suitable source for '" + filename + "' found! Please add the source and then try again.");
- return false;
- }
-
- // Set the source ID from the first found value
- sldr.Read();
- srcid = sldr.GetInt32(0);
- }
- }
- }
-
- // Get all roms that are found in the DAT to see what needs to be added
- DatData datdata = new DatData();
- datdata = RomManipulation.Parse(_filepath, sysid, srcid, datdata, _logger);
-
- // Sort inputted roms into games
- SortedDictionary> sortable = new SortedDictionary>();
- long count = 0;
- foreach (List roms in datdata.Roms.Values)
- {
- List newroms = roms;
- if (datdata.MergeRoms)
- {
- newroms = RomManipulation.Merge(newroms);
- }
-
- foreach (RomData rom in newroms)
- {
- count++;
- string key = rom.SystemID.ToString().PadLeft(10, '0') + "-" + rom.SourceID.ToString().PadLeft(10, '0') + "-" + rom.Game.ToLowerInvariant();
- if (sortable.ContainsKey(key))
- {
- sortable[key].Add(rom);
- }
- else
- {
- List temp = new List();
- temp.Add(rom);
- sortable.Add(key, temp);
- }
- }
- }
-
- // Loop over all roms, checking for adds
- foreach (string key in sortable.Keys)
- {
- List roms = sortable[key];
- RomManipulation.Sort(roms, true);
-
- long gameid = -1;
- using (SqliteConnection dbc = new SqliteConnection(_connectionString))
- {
- dbc.Open();
-
- // For each game, check for a new ID
- gameid = AddGame(sysid, roms[0].Game, srcid, dbc);
-
- foreach (RomData rom in roms)
- {
- // BEGIN COMMENT
- // Try to add the rom with the game information
- AddRom(rom, gameid, date, dbc);
- // END COMMENT
-
- /*
- // Try to add the romdata
- AddHash(rom, sysid, srcid, date, dbc);
- */
- }
- }
- }
-
- return true;
- }
-
- ///
- /// Add a game to the database if it doesn't already exist
- ///
- /// System ID for the game to be added with
- /// Name of the game to be added
- /// Source ID for the game to be added with
- /// SQLite database connection to use
- /// Game ID of the inserted (or found) game, -1 on error
- private long AddGame(int sysid, string machinename, int srcid, SqliteConnection dbc)
- {
- // WoD gets rid of anything past the first "(" or "[" as the name, we will do the same
- string stripPattern = @"(([[(].*[\)\]] )?([^([]+))";
- Regex stripRegex = new Regex(stripPattern);
- Match stripMatch = stripRegex.Match(machinename);
- machinename = stripMatch.Groups[1].Value;
-
- // Run the name through the filters to make sure that it's correct
- machinename = Style.NormalizeChars(machinename);
- machinename = Style.RussianToLatin(machinename);
- machinename = Style.SearchPattern(machinename);
- machinename = machinename.Trim();
-
- long gameid = -1;
- string query = "SELECT id FROM games WHERE system=" + sysid +
- " AND name='" + machinename.Replace("'", "''") + "'" +
- " AND source=" + srcid;
-
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
- {
- using (SqliteDataReader sldr = slc.ExecuteReader())
- {
- // If nothing is found, add the game and get the insert ID
- if (!sldr.HasRows)
- {
- query = "INSERT INTO games (system, name, source)" +
- " VALUES (" + sysid + ", '" + machinename.Replace("'", "''") + "', " + srcid + ")";
-
- using (SqliteCommand slc2 = new SqliteCommand(query, dbc))
- {
- slc2.ExecuteNonQuery();
- }
-
- query = "SELECT last_insertConstants.Rowid()";
- using (SqliteCommand slc2 = new SqliteCommand(query, dbc))
- {
- gameid = (long)slc2.ExecuteScalar();
- }
- }
- // Otherwise, retrieve the ID
- else
- {
- sldr.Read();
- gameid = sldr.GetInt64(0);
- }
- }
- }
-
- return gameid;
- }
-
- ///
- /// Add a file to the database if it doesn't already exist
- ///
- /// RomData object representing the rom
- /// ID of the parent game to be mapped to
- /// Last updated date
- /// SQLite database connection to use
- /// True if the file exists or could be added, false on error
- private bool AddRom(RomData rom, long gameid, string date, SqliteConnection dbc)
- {
- // WOD origninally stripped out any subdirs from the imported files, we do the same
- rom.Name = Path.GetFileName(rom.Name);
-
- // Run the name through the filters to make sure that it's correct
- rom.Name = Style.NormalizeChars(rom.Name);
- rom.Name = Style.RussianToLatin(rom.Name);
- rom.Name = Regex.Replace(rom.Name, @"(.*) \.(.*)", "$1.$2");
-
- if (rom.Type != "rom" && rom.Type != "disk")
- {
- rom.Type = "rom";
- }
-
- // Check to see if this exact file is in the database already
- string query = @"
-SELECT files.id FROM files
- JOIN checksums
- ON files.id=checksums.file
- WHERE files.name='" + rom.Name.Replace("'", "''") + @"'
- AND files.type='" + rom.Type + @"'
- AND files.setid=" + gameid +
- " AND checksums.size=" + rom.Size +
- " AND checksums.crc='" + rom.CRC + "'" +
- " AND checksums.md5='" + rom.MD5 + "'" +
- " AND checksums.sha1='" + rom.SHA1 + "'";
-
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
- {
- using (SqliteDataReader sldr = slc.ExecuteReader())
- {
- // If the file doesn't exist, add it with its checksums
- if (!sldr.HasRows)
- {
- query = @"BEGIN;
-INSERT INTO files (setid, name, type, lastupdated)
-VALUES (" + gameid + ", '" + rom.Name.Replace("'", "''") + "', '" + rom.Type + "', '" + date + @"');
-INSERT INTO checksums (file, size, crc, md5, sha1)
-VALUES ((SELECT last_insertConstants.Rowid()), " + rom.Size + ", '" + rom.CRC + "'" + ", '" + rom.MD5 + "'" + ", '" + rom.SHA1 + @"');
-COMMIT;";
- using (SqliteCommand slc2 = new SqliteCommand(query, dbc))
- {
- int affected = slc2.ExecuteNonQuery();
-
- // If the insert was unsuccessful, something bad happened
- if (affected < 1)
- {
- _logger.Error("There was an error adding " + rom.Name + " to the database!");
- return false;
- }
- }
- }
- }
- }
-
- return true;
- }
-
- ///
- /// Add a hash to the database if it doesn't exist already
- ///
- /// RomData object representing the rom
- /// System ID for the game to be added with
- /// Source ID for the game to be added with
- /// Last updated date
- /// SQLite database connection to use
- /// True if the hash exists or could be added, false on error
- /// This is currently unused. It is a test method for the new SabreTools DB schema
- private bool AddHash(RomData rom, int sysid, int srcid, string date, SqliteConnection dbc)
- {
- // Process the game name
-
- // WoD gets rid of anything past the first "(" or "[" as the name, we will do the same
- string stripPattern = @"(([[(].*[\)\]] )?([^([]+))";
- Regex stripRegex = new Regex(stripPattern);
- Match stripMatch = stripRegex.Match(rom.Game);
- rom.Game = stripMatch.Groups[1].Value;
-
- // Run the name through the filters to make sure that it's correct
- rom.Game = Style.NormalizeChars(rom.Game);
- rom.Game = Style.RussianToLatin(rom.Game);
- rom.Game = Style.SearchPattern(rom.Game);
- rom.Game = rom.Game.Trim();
-
- // Process the rom name
-
- // WOD origninally stripped out any subdirs from the imported files, we do the same
- rom.Name = Path.GetFileName(rom.Name);
-
- // Run the name through the filters to make sure that it's correct
- rom.Name = Style.NormalizeChars(rom.Name);
- rom.Name = Style.RussianToLatin(rom.Name);
- rom.Name = Regex.Replace(rom.Name, @"(.*) \.(.*)", "$1.$2");
-
- // Retrieve or insert the hash
- long hashid = -1;
- string query = "SELECT id FROM hash WHERE size=" + rom.Size + " AND crc='" + rom.CRC + "' AND md5='" + rom.MD5 + "' AND sha1='" + rom.SHA1 + "'";
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
- {
- using (SqliteDataReader sldr = slc.ExecuteReader())
- {
- // If nothing is found, add the hash and get the insert ID
- if (!sldr.HasRows)
- {
- query = "INSERT INTO hash (size, crc, md5, sha1)" +
- " VALUES (" + rom.Size + ", '" + rom.CRC + "', '" + rom.MD5 + "', '" + rom.SHA1 + "')";
-
- using (SqliteCommand slc2 = new SqliteCommand(query, dbc))
- {
- slc2.ExecuteNonQuery();
- }
-
- query = "SELECT last_insertConstants.Rowid()";
- using (SqliteCommand slc2 = new SqliteCommand(query, dbc))
- {
- hashid = (long)slc2.ExecuteScalar();
- }
- }
- // Otherwise, retrieve the ID
- else
- {
- sldr.Read();
- hashid = sldr.GetInt64(0);
- }
- }
- }
-
- // Ignore or insert the file and game
- query = @"BEGIN;
-INSERT OR IGNORE INTO hashdata (hashid, key, value) VALUES " +
- "(" + hashid + ", 'name', '" + rom.Name.Replace("'", "''") + "'), " +
- "(" + hashid + ", 'game', '" + rom.Game.Replace("'", "''") + "'), " +
- "(" + hashid + ", 'type', '" + rom.Type + "'), " +
- "(" + hashid + ", 'lastupdated', '" + date + @"');
-INSERT OR IGNORE INTO gamesystem (game, systemid) VALUES ('" + rom.Game.Replace("'", "''") + "', " + sysid + @");
-INSERT OR IGNORE INTO gamesource (game, sourceid) VALUES ('" + rom.Game.Replace("'", "''") + "', " + srcid + @");
-COMMIT;";
-
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
- {
- int ret = slc.ExecuteNonQuery();
- if ((SQLiteErrorCode)ret == SQLiteErrorCode.Error)
- {
- _logger.Error("A SQLite error has occurred: " + ((SQLiteErrorCode)ret).ToString());
- return false;
- }
- }
-
- return true;
- }
- }
-}
+using System.Collections.Generic;
+using Mono.Data.Sqlite;
+using System.IO;
+using System.Text.RegularExpressions;
+
+using SabreTools.Helper;
+
+namespace SabreTools
+{
+ ///
+ /// Import data into the database from existing DATs
+ ///
+ public class Import : IImport
+ {
+ // Private instance variables
+ private string _filepath;
+ private string _connectionString;
+ private Logger _logger;
+
+ ///
+ /// Initialize an Import object with the given information
+ ///
+ /// Path to the file that is going to be imported
+ /// Connection string for SQLite
+ /// Logger object for file or console output
+ public Import(string filepath, string connectionString, Logger logger)
+ {
+ _filepath = filepath.Replace("\"", "");
+ _connectionString = connectionString;
+ _logger = logger;
+ }
+
+ ///
+ /// Import the data from file into the database
+ ///
+ /// True if the data was imported, false otherwise
+ public bool ImportData()
+ {
+ // If file doesn't exist, error and return
+ if (!File.Exists(_filepath))
+ {
+ _logger.Error("File '" + _filepath + "' doesn't exist");
+ return false;
+ }
+
+ // Determine which dattype we have
+ string filename = Path.GetFileName(_filepath);
+ GroupCollection fileinfo;
+ DatType type = DatType.none;
+
+ if (Regex.IsMatch(filename, Constants.NonGoodPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.NonGoodPattern).Groups;
+ type = DatType.NonGood;
+ }
+ else if (Regex.IsMatch(filename, Constants.NonGoodSpecialPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.NonGoodSpecialPattern).Groups;
+ type = DatType.NonGood;
+ }
+ else if (Regex.IsMatch(filename, Constants.GoodPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.GoodPattern).Groups;
+ type = DatType.Good;
+ }
+ else if (Regex.IsMatch(filename, Constants.GoodXmlPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.GoodXmlPattern).Groups;
+ type = DatType.Good;
+ }
+ else if (Regex.IsMatch(filename, Constants.MaybeIntroPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.MaybeIntroPattern).Groups;
+ type = DatType.MaybeIntro;
+ }
+ else if (Regex.IsMatch(filename, Constants.NoIntroPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.NoIntroPattern).Groups;
+ type = DatType.NoIntro;
+ }
+ // For numbered DATs only
+ else if (Regex.IsMatch(filename, Constants.NoIntroNumberedPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.NoIntroNumberedPattern).Groups;
+ type = DatType.NoIntro;
+ }
+ // For N-Gage and Gizmondo only
+ else if (Regex.IsMatch(filename, Constants.NoIntroSpecialPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.NoIntroSpecialPattern).Groups;
+ type = DatType.NoIntro;
+ }
+ else if (Regex.IsMatch(filename, Constants.RedumpPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.RedumpPattern).Groups;
+ type = DatType.Redump;
+ }
+ // For special BIOSes only
+ else if (Regex.IsMatch(filename, Constants.RedumpBiosPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.RedumpBiosPattern).Groups;
+ type = DatType.Redump;
+ }
+ else if (Regex.IsMatch(filename, Constants.TosecPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.TosecPattern).Groups;
+ type = DatType.TOSEC;
+ }
+ else if (Regex.IsMatch(filename, Constants.TruripPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.TruripPattern).Groups;
+ type = DatType.TruRip;
+ }
+ else if (Regex.IsMatch(filename, Constants.ZandroPattern))
+ {
+ filename = "Nintendo - Super Nintendo Entertainment System (Zandro " + File.GetLastWriteTime(_filepath).ToString("yyyyMMddHHmmss") + ").dat";
+ fileinfo = Regex.Match(filename, Constants.DefaultPattern).Groups;
+ type = DatType.Custom;
+ }
+ else if (Regex.IsMatch(filename, Constants.DefaultPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.DefaultPattern).Groups;
+ type = DatType.Custom;
+ }
+ else if (Regex.IsMatch(filename, Constants.DefaultSpecialPattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.DefaultSpecialPattern).Groups;
+ type = DatType.Custom;
+ }
+ else if (Regex.IsMatch(filename, Constants.MamePattern))
+ {
+ fileinfo = Regex.Match(filename, Constants.MamePattern).Groups;
+ type = DatType.MAME;
+ }
+ // If the type is still unmatched, the data can't be imported yet
+ else
+ {
+ _logger.Warning("File " + filename + " cannot be imported at this time because it is not a known pattern.\nPlease try again with an unrenamed version.");
+ return false;
+ }
+
+ _logger.Log("Type detected: " + type.ToString());
+
+ // Check for and extract import information from the file name based on type
+ string manufacturer = "";
+ string system = "";
+ string source = "";
+ string datestring = "";
+ string date = "";
+
+ switch (type)
+ {
+ case DatType.Good:
+ if (!Remapping.Good.ContainsKey(fileinfo[1].Value))
+ {
+ _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
+ return false;
+ }
+ GroupCollection goodInfo = Regex.Match(Remapping.Good[fileinfo[1].Value], Constants.RemappedPattern).Groups;
+
+ manufacturer = goodInfo[1].Value;
+ system = goodInfo[2].Value;
+ source = "Good";
+ date = File.GetLastWriteTime(_filepath).ToString("yyyy-MM-dd HH:mm:ss");
+ break;
+ case DatType.MAME:
+ if (!Remapping.MAME.ContainsKey(fileinfo[1].Value))
+ {
+ _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
+ return false;
+ }
+ GroupCollection mameInfo = Regex.Match(Remapping.MAME[fileinfo[1].Value], Constants.RemappedPattern).Groups;
+
+ manufacturer = mameInfo[1].Value;
+ system = mameInfo[2].Value;
+ source = "MAME";
+ date = File.GetLastWriteTime(_filepath).ToString("yyyy-MM-dd HH:mm:ss");
+ break;
+ case DatType.MaybeIntro:
+ if (!Remapping.MaybeIntro.ContainsKey(fileinfo[1].Value))
+ {
+ _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
+ return false;
+ }
+ GroupCollection maybeIntroInfo = Regex.Match(Remapping.MaybeIntro[fileinfo[1].Value], Constants.RemappedPattern).Groups;
+
+ manufacturer = maybeIntroInfo[1].Value;
+ system = maybeIntroInfo[2].Value;
+ source = "Maybe-Intro";
+ datestring = fileinfo[2].Value;
+ GroupCollection miDateInfo = Regex.Match(datestring, Constants.NoIntroSpecialDatePattern).Groups;
+ date = miDateInfo[1].Value + "-" + miDateInfo[2].Value + "-" + miDateInfo[3].Value + " 00:00:00";
+ break;
+ case DatType.NoIntro:
+ if (!Remapping.NoIntro.ContainsKey(fileinfo[1].Value))
+ {
+ _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
+ return false;
+ }
+ GroupCollection nointroInfo = Regex.Match(Remapping.NoIntro[fileinfo[1].Value], Constants.RemappedPattern).Groups;
+
+ manufacturer = nointroInfo[1].Value;
+ system = nointroInfo[2].Value;
+ source = "no-Intro";
+ if (fileinfo.Count < 2)
+ {
+ date = File.GetLastWriteTime(_filepath).ToString("yyyy-MM-dd HH:mm:ss");
+ }
+ else if (Regex.IsMatch(fileinfo[2].Value, Constants.NoIntroDatePattern))
+ {
+ datestring = fileinfo[2].Value;
+ GroupCollection niDateInfo = Regex.Match(datestring, Constants.NoIntroDatePattern).Groups;
+ date = niDateInfo[1].Value + "-" + niDateInfo[2].Value + "-" + niDateInfo[3].Value + " " +
+ niDateInfo[4].Value + ":" + niDateInfo[5].Value + ":" + niDateInfo[6].Value;
+ }
+ else
+ {
+ datestring = fileinfo[2].Value;
+ GroupCollection niDateInfo = Regex.Match(datestring, Constants.NoIntroSpecialDatePattern).Groups;
+ date = niDateInfo[1].Value + "-" + niDateInfo[2].Value + "-" + niDateInfo[3].Value + " 00:00:00";
+ }
+ break;
+ case DatType.NonGood:
+ if (!Remapping.NonGood.ContainsKey(fileinfo[1].Value))
+ {
+ _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
+ return false;
+ }
+ GroupCollection nonGoodInfo = Regex.Match(Remapping.NonGood[fileinfo[1].Value], Constants.RemappedPattern).Groups;
+
+ manufacturer = nonGoodInfo[1].Value;
+ system = nonGoodInfo[2].Value;
+ source = "NonGood";
+ date = File.GetLastWriteTime(_filepath).ToString("yyyy-MM-dd HH:mm:ss");
+ break;
+ case DatType.Redump:
+ if (!Remapping.Redump.ContainsKey(fileinfo[1].Value))
+ {
+ // Handle special case mappings found only in Redump
+ fileinfo = Regex.Match(filename, Constants.RedumpBiosPattern).Groups;
+
+ if (!Remapping.Redump.ContainsKey(fileinfo[1].Value))
+ {
+ _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
+ return false;
+ }
+ }
+ GroupCollection redumpInfo = Regex.Match(Remapping.Redump[fileinfo[1].Value], Constants.RemappedPattern).Groups;
+
+ manufacturer = redumpInfo[1].Value;
+ system = redumpInfo[2].Value;
+ source = "Redump";
+ datestring = fileinfo[2].Value;
+ if (Regex.IsMatch(datestring, Constants.RedumpDatePattern))
+ {
+ GroupCollection rdDateInfo = Regex.Match(datestring, Constants.RedumpDatePattern).Groups;
+ date = rdDateInfo[1].Value + "-" + rdDateInfo[2].Value + "-" + rdDateInfo[3].Value + " " +
+ rdDateInfo[4].Value + ":" + rdDateInfo[5].Value + ":" + rdDateInfo[6].Value;
+ }
+ else
+ {
+ GroupCollection rdDateInfo = Regex.Match(datestring, Constants.TosecDatePattern).Groups;
+ date = rdDateInfo[1].Value + "-" + rdDateInfo[2].Value + "-" + rdDateInfo[3].Value + " 00:00:00";
+ }
+
+ break;
+ case DatType.TOSEC:
+ if (!Remapping.TOSEC.ContainsKey(fileinfo[1].Value))
+ {
+ // Handle special case mappings found only in TOSEC
+ fileinfo = Regex.Match(filename, Constants.TosecSpecialPatternA).Groups;
+
+ if (!Remapping.TOSEC.ContainsKey(fileinfo[1].Value))
+ {
+ fileinfo = Regex.Match(filename, Constants.TosecSpecialPatternB).Groups;
+
+ if (!Remapping.TOSEC.ContainsKey(fileinfo[1].Value))
+ {
+ _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
+ return false;
+ }
+ }
+ }
+ GroupCollection tosecInfo = Regex.Match(Remapping.TOSEC[fileinfo[1].Value], Constants.RemappedPattern).Groups;
+
+ manufacturer = tosecInfo[1].Value;
+ system = tosecInfo[2].Value;
+ source = "TOSEC";
+ datestring = fileinfo[2].Value;
+ GroupCollection toDateInfo = Regex.Match(datestring, Constants.TosecDatePattern).Groups;
+ date = toDateInfo[1].Value + "-" + toDateInfo[2].Value + "-" + toDateInfo[3].Value + " 00:00:00";
+ break;
+ case DatType.TruRip:
+ if (!Remapping.TruRip.ContainsKey(fileinfo[1].Value))
+ {
+ _logger.Warning("The filename " + fileinfo[1].Value + " could not be mapped! Please check the mappings and try again");
+ return false;
+ }
+ GroupCollection truripInfo = Regex.Match(Remapping.TruRip[fileinfo[1].Value], Constants.RemappedPattern).Groups;
+
+ manufacturer = truripInfo[1].Value;
+ system = truripInfo[2].Value;
+ source = "trurip";
+ date = File.GetLastWriteTime(_filepath).ToString("yyyy-MM-dd HH:mm:ss");
+ break;
+ case DatType.Custom:
+ default:
+ manufacturer = fileinfo[1].Value;
+ system = fileinfo[2].Value;
+ source = fileinfo[3].Value;
+ datestring = fileinfo[4].Value;
+
+ GroupCollection cDateInfo = Regex.Match(datestring, Constants.DefaultDatePattern).Groups;
+ date = cDateInfo[1].Value + "-" + cDateInfo[2].Value + "-" + cDateInfo[3].Value + " " +
+ cDateInfo[4].Value + ":" + cDateInfo[5].Value + ":" + cDateInfo[6].Value;
+ break;
+ }
+
+ // Check to make sure that the manufacturer and system are valid according to the database
+ int sysid = -1;
+ string query = "SELECT id FROM systems WHERE manufacturer='" + manufacturer + "' AND system='" + system +"'";
+ //string query = "SELECT id FROM system WHERE manufacturer='" + manufacturer + "' AND name='" + system + "'";
+ using (SqliteConnection dbc = new SqliteConnection(_connectionString))
+ {
+ dbc.Open();
+ using (SqliteCommand slc = new SqliteCommand(query, dbc))
+ {
+ using (SqliteDataReader sldr = slc.ExecuteReader())
+ {
+ // If nothing is found, tell the user and exit
+ if (!sldr.HasRows)
+ {
+ _logger.Error("No suitable system for '" + filename + "' (" + manufacturer + " " + system + ") found! Please add the system and then try again.");
+ return false;
+ }
+
+ // Set the system ID from the first found value
+ sldr.Read();
+ sysid = sldr.GetInt32(0);
+ }
+ }
+ }
+
+ // Check to make sure that the source is valid according to the database
+ int srcid = -1;
+ query = "SELECT id FROM sources WHERE name='" + source + "'";
+ //query = "SELECT id FROM source WHERE name='" + source + "'";
+ using (SqliteConnection dbc = new SqliteConnection(_connectionString))
+ {
+ dbc.Open();
+ using (SqliteCommand slc = new SqliteCommand(query, dbc))
+ {
+ using (SqliteDataReader sldr = slc.ExecuteReader())
+ {
+ // If nothing is found, tell the user and exit
+ if (!sldr.HasRows)
+ {
+ _logger.Error("No suitable source for '" + filename + "' found! Please add the source and then try again.");
+ return false;
+ }
+
+ // Set the source ID from the first found value
+ sldr.Read();
+ srcid = sldr.GetInt32(0);
+ }
+ }
+ }
+
+ // Get all roms that are found in the DAT to see what needs to be added
+ DatData datdata = new DatData();
+ datdata = RomManipulation.Parse(_filepath, sysid, srcid, datdata, _logger);
+
+ // Sort inputted roms into games
+ SortedDictionary> sortable = new SortedDictionary>();
+ long count = 0;
+ foreach (List roms in datdata.Roms.Values)
+ {
+ List newroms = roms;
+ if (datdata.MergeRoms)
+ {
+ newroms = RomManipulation.Merge(newroms);
+ }
+
+ foreach (RomData rom in newroms)
+ {
+ count++;
+ string key = rom.SystemID.ToString().PadLeft(10, '0') + "-" + rom.SourceID.ToString().PadLeft(10, '0') + "-" + rom.Game.ToLowerInvariant();
+ if (sortable.ContainsKey(key))
+ {
+ sortable[key].Add(rom);
+ }
+ else
+ {
+ List temp = new List();
+ temp.Add(rom);
+ sortable.Add(key, temp);
+ }
+ }
+ }
+
+ // Loop over all roms, checking for adds
+ foreach (string key in sortable.Keys)
+ {
+ List roms = sortable[key];
+ RomManipulation.Sort(roms, true);
+
+ long gameid = -1;
+ using (SqliteConnection dbc = new SqliteConnection(_connectionString))
+ {
+ dbc.Open();
+
+ // For each game, check for a new ID
+ gameid = AddGame(sysid, roms[0].Game, srcid, dbc);
+
+ foreach (RomData rom in roms)
+ {
+ // BEGIN COMMENT
+ // Try to add the rom with the game information
+ AddRom(rom, gameid, date, dbc);
+ // END COMMENT
+
+ /*
+ // Try to add the romdata
+ AddHash(rom, sysid, srcid, date, dbc);
+ */
+ }
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// Add a game to the database if it doesn't already exist
+ ///
+ /// System ID for the game to be added with
+ /// Name of the game to be added
+ /// Source ID for the game to be added with
+ /// SQLite database connection to use
+ /// Game ID of the inserted (or found) game, -1 on error
+ private long AddGame(int sysid, string machinename, int srcid, SqliteConnection dbc)
+ {
+ // WoD gets rid of anything past the first "(" or "[" as the name, we will do the same
+ string stripPattern = @"(([[(].*[\)\]] )?([^([]+))";
+ Regex stripRegex = new Regex(stripPattern);
+ Match stripMatch = stripRegex.Match(machinename);
+ machinename = stripMatch.Groups[1].Value;
+
+ // Run the name through the filters to make sure that it's correct
+ machinename = Style.NormalizeChars(machinename);
+ machinename = Style.RussianToLatin(machinename);
+ machinename = Style.SearchPattern(machinename);
+ machinename = machinename.Trim();
+
+ long gameid = -1;
+ string query = "SELECT id FROM games WHERE system=" + sysid +
+ " AND name='" + machinename.Replace("'", "''") + "'" +
+ " AND source=" + srcid;
+
+ using (SqliteCommand slc = new SqliteCommand(query, dbc))
+ {
+ using (SqliteDataReader sldr = slc.ExecuteReader())
+ {
+ // If nothing is found, add the game and get the insert ID
+ if (!sldr.HasRows)
+ {
+ query = "INSERT INTO games (system, name, source)" +
+ " VALUES (" + sysid + ", '" + machinename.Replace("'", "''") + "', " + srcid + ")";
+
+ using (SqliteCommand slc2 = new SqliteCommand(query, dbc))
+ {
+ slc2.ExecuteNonQuery();
+ }
+
+ query = "SELECT last_insertConstants.Rowid()";
+ using (SqliteCommand slc2 = new SqliteCommand(query, dbc))
+ {
+ gameid = (long)slc2.ExecuteScalar();
+ }
+ }
+ // Otherwise, retrieve the ID
+ else
+ {
+ sldr.Read();
+ gameid = sldr.GetInt64(0);
+ }
+ }
+ }
+
+ return gameid;
+ }
+
+ ///
+ /// Add a file to the database if it doesn't already exist
+ ///
+ /// RomData object representing the rom
+ /// ID of the parent game to be mapped to
+ /// Last updated date
+ /// SQLite database connection to use
+ /// True if the file exists or could be added, false on error
+ private bool AddRom(RomData rom, long gameid, string date, SqliteConnection dbc)
+ {
+ // WOD origninally stripped out any subdirs from the imported files, we do the same
+ rom.Name = Path.GetFileName(rom.Name);
+
+ // Run the name through the filters to make sure that it's correct
+ rom.Name = Style.NormalizeChars(rom.Name);
+ rom.Name = Style.RussianToLatin(rom.Name);
+ rom.Name = Regex.Replace(rom.Name, @"(.*) \.(.*)", "$1.$2");
+
+ if (rom.Type != "rom" && rom.Type != "disk")
+ {
+ rom.Type = "rom";
+ }
+
+ // Check to see if this exact file is in the database already
+ string query = @"
+SELECT files.id FROM files
+ JOIN checksums
+ ON files.id=checksums.file
+ WHERE files.name='" + rom.Name.Replace("'", "''") + @"'
+ AND files.type='" + rom.Type + @"'
+ AND files.setid=" + gameid +
+ " AND checksums.size=" + rom.Size +
+ " AND checksums.crc='" + rom.CRC + "'" +
+ " AND checksums.md5='" + rom.MD5 + "'" +
+ " AND checksums.sha1='" + rom.SHA1 + "'";
+
+ using (SqliteCommand slc = new SqliteCommand(query, dbc))
+ {
+ using (SqliteDataReader sldr = slc.ExecuteReader())
+ {
+ // If the file doesn't exist, add it with its checksums
+ if (!sldr.HasRows)
+ {
+ query = @"BEGIN;
+INSERT INTO files (setid, name, type, lastupdated)
+VALUES (" + gameid + ", '" + rom.Name.Replace("'", "''") + "', '" + rom.Type + "', '" + date + @"');
+INSERT INTO checksums (file, size, crc, md5, sha1)
+VALUES ((SELECT last_insertConstants.Rowid()), " + rom.Size + ", '" + rom.CRC + "'" + ", '" + rom.MD5 + "'" + ", '" + rom.SHA1 + @"');
+COMMIT;";
+ using (SqliteCommand slc2 = new SqliteCommand(query, dbc))
+ {
+ int affected = slc2.ExecuteNonQuery();
+
+ // If the insert was unsuccessful, something bad happened
+ if (affected < 1)
+ {
+ _logger.Error("There was an error adding " + rom.Name + " to the database!");
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// Add a hash to the database if it doesn't exist already
+ ///
+ /// RomData object representing the rom
+ /// System ID for the game to be added with
+ /// Source ID for the game to be added with
+ /// Last updated date
+ /// SQLite database connection to use
+ /// True if the hash exists or could be added, false on error
+ /// This is currently unused. It is a test method for the new SabreTools DB schema
+ private bool AddHash(RomData rom, int sysid, int srcid, string date, SqliteConnection dbc)
+ {
+ // Process the game name
+
+ // WoD gets rid of anything past the first "(" or "[" as the name, we will do the same
+ string stripPattern = @"(([[(].*[\)\]] )?([^([]+))";
+ Regex stripRegex = new Regex(stripPattern);
+ Match stripMatch = stripRegex.Match(rom.Game);
+ rom.Game = stripMatch.Groups[1].Value;
+
+ // Run the name through the filters to make sure that it's correct
+ rom.Game = Style.NormalizeChars(rom.Game);
+ rom.Game = Style.RussianToLatin(rom.Game);
+ rom.Game = Style.SearchPattern(rom.Game);
+ rom.Game = rom.Game.Trim();
+
+ // Process the rom name
+
+ // WOD origninally stripped out any subdirs from the imported files, we do the same
+ rom.Name = Path.GetFileName(rom.Name);
+
+ // Run the name through the filters to make sure that it's correct
+ rom.Name = Style.NormalizeChars(rom.Name);
+ rom.Name = Style.RussianToLatin(rom.Name);
+ rom.Name = Regex.Replace(rom.Name, @"(.*) \.(.*)", "$1.$2");
+
+ // Retrieve or insert the hash
+ long hashid = -1;
+ string query = "SELECT id FROM hash WHERE size=" + rom.Size + " AND crc='" + rom.CRC + "' AND md5='" + rom.MD5 + "' AND sha1='" + rom.SHA1 + "'";
+ using (SqliteCommand slc = new SqliteCommand(query, dbc))
+ {
+ using (SqliteDataReader sldr = slc.ExecuteReader())
+ {
+ // If nothing is found, add the hash and get the insert ID
+ if (!sldr.HasRows)
+ {
+ query = "INSERT INTO hash (size, crc, md5, sha1)" +
+ " VALUES (" + rom.Size + ", '" + rom.CRC + "', '" + rom.MD5 + "', '" + rom.SHA1 + "')";
+
+ using (SqliteCommand slc2 = new SqliteCommand(query, dbc))
+ {
+ slc2.ExecuteNonQuery();
+ }
+
+ query = "SELECT last_insertConstants.Rowid()";
+ using (SqliteCommand slc2 = new SqliteCommand(query, dbc))
+ {
+ hashid = (long)slc2.ExecuteScalar();
+ }
+ }
+ // Otherwise, retrieve the ID
+ else
+ {
+ sldr.Read();
+ hashid = sldr.GetInt64(0);
+ }
+ }
+ }
+
+ // Ignore or insert the file and game
+ query = @"BEGIN;
+INSERT OR IGNORE INTO hashdata (hashid, key, value) VALUES " +
+ "(" + hashid + ", 'name', '" + rom.Name.Replace("'", "''") + "'), " +
+ "(" + hashid + ", 'game', '" + rom.Game.Replace("'", "''") + "'), " +
+ "(" + hashid + ", 'type', '" + rom.Type + "'), " +
+ "(" + hashid + ", 'lastupdated', '" + date + @"');
+INSERT OR IGNORE INTO gamesystem (game, systemid) VALUES ('" + rom.Game.Replace("'", "''") + "', " + sysid + @");
+INSERT OR IGNORE INTO gamesource (game, sourceid) VALUES ('" + rom.Game.Replace("'", "''") + "', " + srcid + @");
+COMMIT;";
+
+ using (SqliteCommand slc = new SqliteCommand(query, dbc))
+ {
+ int ret = slc.ExecuteNonQuery();
+ if ((SQLiteErrorCode)ret == SQLiteErrorCode.Error)
+ {
+ _logger.Error("A SQLite error has occurred: " + ((SQLiteErrorCode)ret).ToString());
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/DATabaseTwo/ImportTwo.cs b/DATabase/ImportExport/ImportTwo.cs
similarity index 100%
rename from DATabaseTwo/ImportTwo.cs
rename to DATabase/ImportExport/ImportTwo.cs
diff --git a/DATabaseTwo/App.config b/DATabaseTwo/App.config
deleted file mode 100644
index 88fa4027..00000000
--- a/DATabaseTwo/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/DATabaseTwo/DATabaseTwo.cs b/DATabaseTwo/DATabaseTwo.cs
deleted file mode 100644
index 0a89f4fa..00000000
--- a/DATabaseTwo/DATabaseTwo.cs
+++ /dev/null
@@ -1,452 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Mono.Data.Sqlite;
-using System.IO;
-
-using SabreTools.Helper;
-
-namespace SabreTools
-{
- ///
- /// The following features are missing from DATabaseTwo with respect to the original DATabase:
- /// - Source merging
- /// - Custom DATs based on a system and a source
- /// - Multi-source and multi-system DATs
- ///
- /// The following features need to (want to) be implemented in DATabaseTwo for further stability
- /// - Import updating file locations and names when SHA-1 hashes are matched
- /// - True duplicate DATs being removed from the import folder (SHA-1 matches)
- /// - Generate All only generating DATs that have been recently updated
- /// + This requires implementing a "last updated" data point for all DATs and tracking for "last generate" somewhere
- /// - Impelement a ToSort folder for DATs that will place DATs in the correct subfolder on Import
- ///
- public class DATabaseTwo
- {
- // Private required variables
- private static string _datroot = "DATS";
- private static string _outroot = "Output";
- private static string _dbName = "dats.sqlite";
- private static string _connectionString = "Data Source=" + _dbName + ";Version = 3;";
- private static Logger _logger;
-
- public static void Main(string[] args)
- {
- Console.Clear();
-
- // Credits take precidence over all
- if ((new List(args)).Contains("--credits"))
- {
- Build.Credits();
- return;
- }
-
- _logger = new Logger(true, "database2.log");
- _logger.Start();
-
- // Perform initial setup
- Setup();
-
- // If there's no arguments, show the menu
- if (args.Length == 0)
- {
- _logger.ToFile = true;
- ShowMainMenu();
- _logger.Close();
- return;
- }
-
- // Set all default values
- bool help = false,
- gen = false,
- genall = false,
- ignore = false,
- listsys = false,
- norename = false,
- old = false;
- string system = "";
-
- // Determine which switches are enabled (with values if necessary)
- foreach (string arg in args)
- {
- switch (arg)
- {
- case "-?":
- case "-h":
- case "--help":
- help = true;
- break;
- case "-g":
- case "--generate":
- gen = true;
- break;
- case "-ga":
- case "--generate-all":
- genall = true;
- break;
- case "-i":
- case "--ignore":
- ignore = true;
- break;
- case "-lsy":
- case "--list-systems":
- listsys = true;
- break;
- case "-nr":
- case "--no-rename":
- norename = true;
- break;
- case "-o":
- case "--old":
- old = true;
- break;
- default:
- if (arg.StartsWith("-sys=") || arg.StartsWith("--system="))
- {
- system = arg.Split('=')[1];
- }
- else
- {
- _logger.Warning("Invalid input detected: " + arg);
- Console.WriteLine();
- Build.Help();
- _logger.Close();
- return;
- }
- break;
- }
- }
-
- // If help is set or system is blank, show the help screen
- if (help || (system == "" && !listsys))
- {
- Build.Help();
- _logger.Close();
- return;
- }
-
- // If we want a list of systems
- if (listsys)
- {
- ListSystems();
- }
-
- // If we want to generate all DATs
- else if (genall)
- {
- InitImport(ignore);
- InitGenerateAll(norename, old);
- }
-
- // If we want to generate a DAT
- else if (gen)
- {
- InitImport(ignore);
- InitGenerate(system, norename, old);
- }
-
- _logger.Close();
- }
-
- #region Menus
-
- ///
- /// Show the text-based main menu
- ///
- private static void ShowMainMenu()
- {
- string selection = "";
- while (selection.ToLowerInvariant() != "x")
- {
- Console.Clear();
- Build.Start("DATabaseTwo");
- Console.WriteLine(@"MAIN MENU
-===========================
-Make a selection:
-
- 1) Show command line usage
- 2) Check for new or changed DATs
- 3) Generate System DATs
- 4) List all available systems
- 5) Show credits
- X) Exit Program
-");
- Console.Write("Enter selection: ");
- selection = Console.ReadLine();
-
- switch (selection)
- {
- case "1":
- Console.Clear();
- Build.Help();
- Console.Write("\nPress any key to continue...");
- Console.ReadKey();
- break;
- case "2":
- ImportMenu();
- break;
- case "3":
- GenerateMenu();
- break;
- case "4":
- Console.Clear();
- Build.Start("DATabaseTwo");
- ListSystems();
- Console.Write("\nPress any key to continue...");
- Console.ReadKey();
- break;
- case "5":
- Console.Clear();
- Build.Credits();
- Console.Write("\nPress any key to continue...");
- Console.ReadKey();
- break;
- }
- }
- }
-
- ///
- /// Show the text-based import menu
- ///
- private static void ImportMenu()
- {
- string selection = "";
- bool ignore = false;
- while (selection.ToLowerInvariant() != "b")
- {
- Console.Clear();
- Build.Start("DATabaseTwo");
- Console.WriteLine(@"IMPORT MENU
-===========================
-Make a selection:
-
- 1) " + (ignore ? "Enable new source prompt" : "Disable new source prompt") + @"
- 2) Begin import process
- B) Go back to the previous menu
-");
- Console.Write("Enter selection: ");
- selection = Console.ReadLine();
- switch (selection)
- {
- case "1":
- ignore = !ignore;
- break;
- case "2":
- Console.Clear();
- InitImport(ignore);
- Console.Write("\nPress any key to continue...");
- Console.ReadKey();
- ignore = false;
- break;
- }
- }
- return;
- }
-
- ///
- /// Show the text-based generate menu
- ///
- private static void GenerateMenu()
- {
- string selection = "", system = "";
- bool norename = false, old = false;
- while (selection.ToLowerInvariant() != "b")
- {
- Console.Clear();
- Build.Start("DATabaseTwo");
- Console.WriteLine(@"GENERATE MENU
-===========================
-Make a selection:
-
- 1) " + (norename ? "Enable game renaming" : "Disable game renaming") + @"
- 2) " + (old ? "Enable XML output" : "Enable ClrMamePro output") + @"
- 3) System ID to generate from" + (system != "" ? ": " + system : "") + @"
- 4) Generate the DAT file for the specified system
- 5) Generate all DAT files
- B) Go back to the previous menu
-");
- Console.Write("Enter selection: ");
- selection = Console.ReadLine();
- switch (selection)
- {
- case "1":
- norename = !norename;
- break;
- case "2":
- old = !old;
- break;
- case "3":
- Console.Clear();
- ListSystems();
- Console.Write("Please enter the System ID: ");
- system = Console.ReadLine();
- break;
- case "4":
- Console.Clear();
- InitGenerate(system, norename, old);
- Console.Write("\nPress any key to continue...");
- Console.ReadKey();
- system = "";
- norename = false; old = false;
- break;
- case "5":
- Console.Clear();
- InitGenerateAll(norename, old);
- Console.Write("\nPress any key to continue...");
- Console.ReadKey();
- system = "";
- norename = false; old = false;
- break;
- }
- }
- return;
- }
-
- #endregion
-
- #region Function Methods
-
- ///
- /// Wrap importing and updating DATs
- ///
- ///
- private static void InitImport(bool ignore)
- {
- Import imp = new Import(_datroot, _connectionString, _logger, ignore);
- imp.ImportData();
- }
-
- ///
- /// Wrap generating a DAT from the library
- ///
- /// System ID to be used in the DAT (blank means all)
- /// True if files should not be renamed with system and/or source in merged mode (default false)
- /// True if the output file should be in ClrMamePro format (default false)
- private static void InitGenerate(string systemid, bool norename, bool old)
- {
- Generate gen = new Generate(systemid, "" /* sourceid */, _datroot, _outroot, _connectionString, _logger, norename, old);
- gen.Export();
- }
-
- ///
- /// Wrap generating all standard DATs from the library
- ///
- private static void InitGenerateAll(bool norename, bool old)
- {
- List systems = new List();
- using (SqliteConnection dbc = new SqliteConnection(_connectionString))
- {
- dbc.Open();
-
- string query = "SELECT id FROM system";
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
- {
- using (SqliteDataReader sldr = slc.ExecuteReader())
- {
- // If nothing is found, tell the user and exit
- if (!sldr.HasRows)
- {
- _logger.Warning("No systems found! Please add a system and then try again.");
- return;
- }
-
- while (sldr.Read())
- {
- systems.Add(sldr.GetInt32(0).ToString());
- }
- }
- }
-
- // Loop through the inputs
- foreach (string system in systems)
- {
- _logger.User("Generating DAT for system id " + system);
- InitGenerate(system, norename, old);
- }
- }
- }
-
- ///
- /// List systems in the database
- ///
- private static void ListSystems()
- {
- string query = @"
-SELECT DISTINCT system.id, system.manufacturer, system.name
-FROM system
-ORDER BY system.manufacturer, system.name";
- using (SqliteConnection dbc = new SqliteConnection(_connectionString))
- {
- dbc.Open();
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
- {
- using (SqliteDataReader sldr = slc.ExecuteReader())
- {
- // If nothing is found, tell the user and exit
- if (!sldr.HasRows)
- {
- _logger.Warning("No systems found! Please add a system and then try again.");
- return;
- }
-
- Console.WriteLine("Available Systems (id <= name):\n");
- while (sldr.Read())
- {
- Console.WriteLine(sldr.GetInt32(0) + "\t<=\t" + sldr.GetString(1) + " - " + sldr.GetString(2));
- }
- }
- }
- }
- return;
- }
-
- #endregion
-
- #region Helper Methods
-
- ///
- /// Perform initial setup for the program
- ///
- private static void Setup()
- {
- Remapping.CreateRemappings();
- Build.Start("DATabaseTwo");
-
- // Perform initial database and folder setup
- if (!Directory.Exists(_datroot))
- {
- Directory.CreateDirectory(_datroot);
- }
- if (!Directory.Exists(_outroot))
- {
- Directory.CreateDirectory(_outroot);
- }
- DBTools.EnsureDatabase(_dbName, _connectionString);
-
- using (SqliteConnection dbc = new SqliteConnection(_connectionString))
- {
- dbc.Open();
-
- string query = "SELECT * FROM system";
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
- {
- using (SqliteDataReader sldr = slc.ExecuteReader())
- {
- while (sldr.Read())
- {
- int systemid = sldr.GetInt32(0);
- string system = _datroot + Path.DirectorySeparatorChar + sldr.GetString(1) + " - " + sldr.GetString(2);
- system = system.Trim();
-
- if (!Directory.Exists(system))
- {
- Directory.CreateDirectory(system);
- }
- }
- }
- }
- }
- }
-
- #endregion
- }
-}
diff --git a/DATabaseTwo/DATabaseTwo.csproj b/DATabaseTwo/DATabaseTwo.csproj
deleted file mode 100644
index 0be5871c..00000000
--- a/DATabaseTwo/DATabaseTwo.csproj
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {C7732A05-1F96-43ED-AC8C-0E388F37EBC1}
- Exe
- Properties
- DATabaseTwo
- DATabaseTwo
- v4.5.2
- 512
- true
-
-
- AnyCPU
- true
- full
- false
- ..\..\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- ..\..\Release\
- TRACE
- prompt
- 4
-
-
- true
- ..\..\Debug-x64\
- DEBUG;TRACE
- full
- x64
- prompt
- MinimumRecommendedRules.ruleset
- true
-
-
- ..\..\Release-x64\
- TRACE
- true
- pdbonly
- x64
- prompt
- MinimumRecommendedRules.ruleset
- true
-
-
-
- ..\packages\Mono.Data.Sqlite.Portable.1.0.3.5\lib\net4\Mono.Data.Sqlite.dll
- True
-
-
-
-
- ..\packages\Mono.Data.Sqlite.Portable.1.0.3.5\lib\net4\System.Data.Portable.dll
- True
-
-
-
- ..\packages\Mono.Data.Sqlite.Portable.1.0.3.5\lib\net4\System.Transactions.Portable.dll
- True
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {225a1afd-0890-44e8-b779-7502665c23a5}
- SabreHelper
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/DATabaseTwo/Properties/AssemblyInfo.cs b/DATabaseTwo/Properties/AssemblyInfo.cs
deleted file mode 100644
index 6a28bc87..00000000
--- a/DATabaseTwo/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("DATabaseTwo")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("DATabaseTwo")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("c7732a05-1f96-43ed-ac8c-0e388f37ebc1")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/DATabaseTwo/packages.config b/DATabaseTwo/packages.config
deleted file mode 100644
index 2e7f170d..00000000
--- a/DATabaseTwo/packages.config
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/SabreHelper/Data/Build.cs b/SabreHelper/Data/Build.cs
index 4ad47e34..fd18c4fb 100644
--- a/SabreHelper/Data/Build.cs
+++ b/SabreHelper/Data/Build.cs
@@ -99,18 +99,16 @@ Options:
-extb= Second extension to split by
-out= Output directory
-g, --generate Start tool in generate mode
- -system= Comma-separated list of system IDs
- -source= Comma-separated list of source IDs
- -out= Output directory
+ -system= System ID to generate from
-nr, --no-rename Don't auto-rename games
-o, --old Output DAT in CMP format instead of XML
-ga, --generate-all Start tool in generate all mode
- -out= Output directory
-nr, --no-rename Don't auto-rename games
-o, --old Output DAT in CMP format instead of XML
-hs, --hash-split Split a DAT or folder by best-available hashes
-out= Output directory
-i, --import Start tool in import mode
+ -ig, --ignore Don't prompt for new sources
-lso, --list-sources List all sources (id <= name)
-lsy, --list-systems List all systems (id <= name)
-m, --merge Merge one or more DATs
@@ -195,22 +193,6 @@ This program will output the following DATs:
(d) Have - (NewComplete)-(New Missing)
OR (Complete or NewComplete)-(Missing) if one is missing");
break;
- case "DATabaseTwo":
- Console.WriteLine(@"DATabaseTwo - Catalog and merge DATs by system
------------------------------------------
-Usage: DATabaseTwo [options]
-
-Options:
- -h, -?, --help Show this help dialog
- -g, --generate Start tool in generate mode
- -ga, --generate-all Start tool in generate all mode
- -i, --ignore Don't prompt for new sources
- -lsy, --list-systems List all systems (id <= name)
- -nr, --no-rename Don't auto-rename games by source/system
- -o, --old Output DAT in CMP format instead of XML
- -sys=, --system= System ID to generate from
-");
- break;
case "Filter":
Console.WriteLine(@"Filter - Filter DATs by inputted criteria
-----------------------------------------
diff --git a/SabreTools.sln b/SabreTools.sln
index a95a0a87..eb7d263d 100644
--- a/SabreTools.sln
+++ b/SabreTools.sln
@@ -15,8 +15,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DATFromDir", "DATFromDir\DA
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OfflineMerge", "OfflineMerge\OfflineMerge.csproj", "{88310DB9-3B64-4268-AD48-2E0358D4CA5F}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DATabaseTwo", "DATabaseTwo\DATabaseTwo.csproj", "{C7732A05-1F96-43ED-AC8C-0E388F37EBC1}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Filter", "Filter\Filter.csproj", "{136AA0D0-9234-4680-B593-A32C0762972E}"
EndProject
Global
@@ -76,14 +74,6 @@ Global
{88310DB9-3B64-4268-AD48-2E0358D4CA5F}.Release|Any CPU.Build.0 = Release|Any CPU
{88310DB9-3B64-4268-AD48-2E0358D4CA5F}.Release|x64.ActiveCfg = Release|x64
{88310DB9-3B64-4268-AD48-2E0358D4CA5F}.Release|x64.Build.0 = Release|x64
- {C7732A05-1F96-43ED-AC8C-0E388F37EBC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C7732A05-1F96-43ED-AC8C-0E388F37EBC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C7732A05-1F96-43ED-AC8C-0E388F37EBC1}.Debug|x64.ActiveCfg = Debug|x64
- {C7732A05-1F96-43ED-AC8C-0E388F37EBC1}.Debug|x64.Build.0 = Debug|x64
- {C7732A05-1F96-43ED-AC8C-0E388F37EBC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C7732A05-1F96-43ED-AC8C-0E388F37EBC1}.Release|Any CPU.Build.0 = Release|Any CPU
- {C7732A05-1F96-43ED-AC8C-0E388F37EBC1}.Release|x64.ActiveCfg = Release|x64
- {C7732A05-1F96-43ED-AC8C-0E388F37EBC1}.Release|x64.Build.0 = Release|x64
{136AA0D0-9234-4680-B593-A32C0762972E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{136AA0D0-9234-4680-B593-A32C0762972E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{136AA0D0-9234-4680-B593-A32C0762972E}.Debug|x64.ActiveCfg = Debug|x64