diff --git a/.gitignore b/.gitignore
index a0c4a6ec..cd820889 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,9 @@
/Deheader/obj
/Deheader/obj/Debug
/Deheader/obj/Release
+/RombaSharp/obj
+/RombaSharp/obj/Debug
+/RombaSharp/obj/Release
/SabreTools/obj
/SabreTools/obj/Debug
/SabreTools/obj/Release
@@ -18,3 +21,5 @@
/SimpleSort/obj/Debug
/SimpleSort/obj/Release
/TGZConvert/obj
+/TGZConvert/obj/Debug
+/TGZConvert/obj/Release
\ No newline at end of file
diff --git a/RombaSharp/App.config b/RombaSharp/App.config
new file mode 100644
index 00000000..88fa4027
--- /dev/null
+++ b/RombaSharp/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RombaSharp/Properties/AssemblyInfo.cs b/RombaSharp/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..56140875
--- /dev/null
+++ b/RombaSharp/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+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("RombaSharp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("RombaSharp")]
+[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("4728d479-8cfb-43e9-8c63-4774c6d73200")]
+
+// 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/RombaSharp/RombaSharp.cs b/RombaSharp/RombaSharp.cs
new file mode 100644
index 00000000..bbd18d03
--- /dev/null
+++ b/RombaSharp/RombaSharp.cs
@@ -0,0 +1,394 @@
+using Mono.Data.Sqlite;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using SabreTools.Helper;
+
+namespace SabreTools
+{
+ ///
+ /// Entry class for the RombaSharp application
+ ///
+ public class RombaSharp
+ {
+ // General settings
+ private int _workers; //Number of parallel threads
+ private string _logdir; //Log folder location
+ private string _tmpdir; //Temp folder location
+ private string _webdir; // Web frontend location
+ private string _baddir; // Fail-to-unpack file folder location
+ private int _verbosity; // Verbosity of the output
+ private int _cores; // Forced CPU cores
+
+ // DatRoot settings
+ private string _dats; // DatRoot folder location
+ private string _db; // Database name
+
+ // Depot settings
+ private Dictionary> _depots; // Folder location, Max size
+
+ // Server settings
+ private int _port; // Web server port
+
+ // Other private variables
+ private string _config = "config.xml";
+ private string _connectionString;
+ private Logger _logger;
+
+ ///
+ /// Create a new RombaSharp object
+ ///
+ /// Logger object for file and console output
+ public RombaSharp(Logger logger)
+ {
+ _logger = logger;
+
+ InitializeConfiguration();
+ InitializeDatabase();
+ }
+
+ public static void Main(string[] args)
+ {
+ }
+
+ ///
+ /// Initialize the Romba application from XML config
+ ///
+ private void InitializeConfiguration()
+ {
+ // Get default values if they're not written
+ int workers = 4,
+ verbosity = 1,
+ cores = 4,
+ port = 4003;
+ string logdir = "logs",
+ tmpdir = "tmp",
+ webdir = "web",
+ baddir = "bad",
+ dats = "dats",
+ db = "db",
+ connectionString = "";
+ Dictionary> depots = new Dictionary>();
+
+ // Get the XML text reader for the configuration file, if possible
+ XmlTextReader xtr = DatTools.GetXmlTextReader(_config, _logger);
+
+ /* XML file structure
+
+
+
+ 4
+ logs
+ tmp
+ web
+ bad
+ 1
+ 4
+
+
+ dats
+ db
+
+
+
+ depot
+ 40000
+ true
+
+
+
+ 4003
+
+
+
+ */
+
+ // Now parse the XML file for settings
+ if (xtr != null)
+ {
+ xtr.MoveToContent();
+ while (!xtr.EOF)
+ {
+ // We only want elements
+ if (xtr.NodeType != XmlNodeType.Element)
+ {
+ xtr.Read();
+ continue;
+ }
+
+ switch (xtr.Name)
+ {
+ case "workers":
+ workers = xtr.ReadElementContentAsInt();
+ break;
+ case "logdir":
+ logdir = xtr.ReadElementContentAsString();
+ break;
+ case "tmpdir":
+ tmpdir = xtr.ReadElementContentAsString();
+ break;
+ case "webdir":
+ webdir = xtr.ReadElementContentAsString();
+ break;
+ case "baddir":
+ baddir = xtr.ReadElementContentAsString();
+ break;
+ case "verbosity":
+ verbosity = xtr.ReadElementContentAsInt();
+ break;
+ case "cores":
+ cores = xtr.ReadElementContentAsInt();
+ break;
+ case "dats":
+ dats = xtr.ReadElementContentAsString();
+ break;
+ case "db":
+ db = xtr.ReadElementContentAsString();
+ break;
+ case "depot":
+ XmlReader subreader = xtr.ReadSubtree();
+ if (subreader != null)
+ {
+ string root = "";
+ long maxsize = -1;
+ bool online = true;
+
+ while (!subreader.EOF)
+ {
+ // We only want elements
+ if (subreader.NodeType != XmlNodeType.Element)
+ {
+ subreader.Read();
+ continue;
+ }
+
+ switch (subreader.Name)
+ {
+ case "root":
+ root = subreader.ReadElementContentAsString();
+ break;
+ case "maxsize":
+ maxsize = subreader.ReadElementContentAsLong();
+ break;
+ case "online":
+ online = subreader.ReadElementContentAsBoolean();
+ break;
+ default:
+ subreader.Read();
+ break;
+ }
+ }
+
+ try
+ {
+ depots.Add(root, new Tuple(maxsize, online));
+ }
+ catch
+ {
+ // Ignore add errors
+ }
+ }
+
+ xtr.Skip();
+ break;
+ case "port":
+ port = xtr.ReadElementContentAsInt();
+ break;
+ default:
+ xtr.Read();
+ break;
+ }
+ }
+ }
+
+ // Now validate the values given
+ if (workers < 1)
+ {
+ workers = 1;
+ }
+ if (workers > 8)
+ {
+ workers = 8;
+ }
+ if (!Directory.Exists(logdir))
+ {
+ Directory.CreateDirectory(logdir);
+ }
+ if (!Directory.Exists(tmpdir))
+ {
+ Directory.CreateDirectory(tmpdir);
+ }
+ if (!Directory.Exists(webdir))
+ {
+ Directory.CreateDirectory(webdir);
+ }
+ if (!Directory.Exists(baddir))
+ {
+ Directory.CreateDirectory(baddir);
+ }
+ if (verbosity < 0)
+ {
+ verbosity = 0;
+ }
+ if (verbosity > 3)
+ {
+ verbosity = 3;
+ }
+ if (cores < 1)
+ {
+ cores = 1;
+ }
+ if (cores > 16)
+ {
+ cores = 16;
+ }
+ if (!Directory.Exists(dats))
+ {
+ Directory.CreateDirectory(dats);
+ }
+ db = Path.GetFileNameWithoutExtension(db) + ".sqlite";
+ connectionString = "Data Source=" + _db + ";Version = 3;";
+ foreach (string key in depots.Keys)
+ {
+ if (!Directory.Exists(key))
+ {
+ Directory.CreateDirectory(key);
+ }
+ }
+ if (port < 0)
+ {
+ port = 0;
+ }
+ if (port > 65535)
+ {
+ port = 65535;
+ }
+
+ // Finally set all of the fields
+ _workers = workers;
+ _logdir = logdir;
+ _tmpdir = tmpdir;
+ _webdir = webdir;
+ _baddir = baddir;
+ _verbosity = verbosity;
+ _cores = cores;
+ _dats = dats;
+ _db = db;
+ _connectionString = connectionString;
+ _depots = depots;
+ _port = port;
+ }
+
+ ///
+ /// Initialize the Romba database
+ ///
+ private void InitializeDatabase()
+ {
+ // Make sure the db is set
+ if (String.IsNullOrEmpty(_db))
+ {
+ _db = "db.sqlite";
+ _connectionString = "Data Source=" + _db + ";Version = 3;";
+ }
+
+ // Make sure the file exists
+ if (!File.Exists(_db))
+ {
+ SqliteConnection.CreateFile(_db);
+ }
+
+ // Connect to the file
+ SqliteConnection dbc = new SqliteConnection(_connectionString);
+ dbc.Open();
+
+ // Initialize the database schema
+ try
+ {
+ string query = @"
+CREATE TABLE IF NOT EXISTS data (
+'id' INTEGER NOT NULL
+'key' TEXT NOT NULL
+'value' TEXT NOT NULL
+)";
+ SqliteCommand slc = new SqliteCommand(query, dbc);
+ slc.ExecuteNonQuery();
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex);
+ }
+ finally
+ {
+ // Close the database connection
+ dbc.Close();
+ }
+ }
+
+ ///
+ /// Populate or refresh the database information
+ ///
+ private void RefreshDatabase()
+ {
+ // Make sure the dats dir is set
+ if (String.IsNullOrEmpty(_dats))
+ {
+ _dats = "dats";
+ }
+
+ // Make sure the folder exists
+ if (!Directory.Exists(_dats))
+ {
+ Directory.CreateDirectory(_dats);
+ }
+
+ // Now parse the directory into an internal Dat then insert
+ foreach (string file in Directory.EnumerateFiles(_dats, "*", SearchOption.AllDirectories))
+ {
+ Dat datdata = new Dat();
+ datdata = DatTools.Parse(file, 0, 0, datdata, _logger);
+ Rom romdata = FileTools.GetSingleFileInfo(file);
+ }
+ }
+
+ ///
+ /// Process a datfile and insert it into the database
+ ///
+ /// Dat object representing the data to insert
+ /// Rom object representing the Dat file itself
+ private void InsertDatIntoDatabase(Dat datdata, Rom romdata)
+ {
+ // Make sure the db is set
+ if (String.IsNullOrEmpty(_db))
+ {
+ _db = "db.sqlite";
+ _connectionString = "Data Source=" + _db + ";Version = 3;";
+ }
+
+ // Make sure the file exists
+ if (!File.Exists(_db))
+ {
+ SqliteConnection.CreateFile(_db);
+ InitializeDatabase();
+ }
+
+ // Open a connection to the database
+ using (SqliteConnection slc = new SqliteConnection(_connectionString))
+ {
+ // For each key
+ foreach (string key in datdata.Files.Keys)
+ {
+ // For each Rom in the list
+ foreach (Rom file in datdata.Files[key])
+ {
+ // Try to find the hash in the set
+
+ // If it exists, see if there's any missing information
+
+ // If it doesn't exist, insert it completely
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/RombaSharp/RombaSharp.csproj b/RombaSharp/RombaSharp.csproj
new file mode 100644
index 00000000..1c368c5a
--- /dev/null
+++ b/RombaSharp/RombaSharp.csproj
@@ -0,0 +1,85 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {4728D479-8CFB-43E9-8C63-4774C6D73200}
+ Exe
+ Properties
+ RombaSharp
+ RombaSharp
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\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}
+ SabreTools.Helper
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RombaSharp/packages.config b/RombaSharp/packages.config
new file mode 100644
index 00000000..2e7f170d
--- /dev/null
+++ b/RombaSharp/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/SabreTools.sln b/SabreTools.sln
index b24c79ac..c77221a3 100644
--- a/SabreTools.sln
+++ b/SabreTools.sln
@@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleSort", "SimpleSort\Si
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TGZConvert", "TGZConvert\TGZConvert.csproj", "{73FBE2C1-39FB-4FFC-93F4-FB4998492429}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RombaSharp", "RombaSharp\RombaSharp.csproj", "{4728D479-8CFB-43E9-8C63-4774C6D73200}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -68,6 +70,14 @@ Global
{73FBE2C1-39FB-4FFC-93F4-FB4998492429}.Release|Any CPU.Build.0 = Release|Any CPU
{73FBE2C1-39FB-4FFC-93F4-FB4998492429}.Release|x64.ActiveCfg = Release|Any CPU
{73FBE2C1-39FB-4FFC-93F4-FB4998492429}.Release|x64.Build.0 = Release|Any CPU
+ {4728D479-8CFB-43E9-8C63-4774C6D73200}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4728D479-8CFB-43E9-8C63-4774C6D73200}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4728D479-8CFB-43E9-8C63-4774C6D73200}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4728D479-8CFB-43E9-8C63-4774C6D73200}.Debug|x64.Build.0 = Debug|Any CPU
+ {4728D479-8CFB-43E9-8C63-4774C6D73200}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4728D479-8CFB-43E9-8C63-4774C6D73200}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4728D479-8CFB-43E9-8C63-4774C6D73200}.Release|x64.ActiveCfg = Release|Any CPU
+ {4728D479-8CFB-43E9-8C63-4774C6D73200}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE