mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
[ALL] Cleanup
This is a purge of dead and unused code. The major thing with this is the removal of all original DATabase features. They might be resurrected in the future but , for now, it would need a full rewrite to make sense. Nobody uses it either, so it shouldn't be missed.
This commit is contained in:
@@ -13,12 +13,12 @@ For the most complete set of information, see the <a href="https://raw.githubuse
|
||||
The main tool of the SabreTools suite. Performs the majority of the core features of the parent project, including the following (sorted by the original standalone executable, if any):
|
||||
<ul>
|
||||
<li><i>Convert/DATToMiss</i>: Converting DATs from any format to ClrMamePro, Logiqx XML, SabreDAT XML, and to missfile (last part requested by Obiwantje)</li>
|
||||
<li><i>DATabase/DATabaseTwo</i>: Importing and Generating DAT files in ClrMamePro and XML formats
|
||||
<!-- <li><i>DATabase/DATabaseTwo</i>: Importing and Generating DAT files in ClrMamePro and XML formats
|
||||
<ul>
|
||||
<li>Add and remove sources and systems from the database</li>
|
||||
<li>Retrieve a list of all sources and systems that are available</li>
|
||||
</ul>
|
||||
</li>
|
||||
</li> -->
|
||||
<li><i>DATFromDir/DATFromDirParallel</i>: Create a DAT from a file, a folder, or a set of either</li>
|
||||
<li><i>DatSplit</i>: Split a DAT using two different file extensions within the DAT</li>
|
||||
<li><i>Filter</i>: Filter a DAT by any criteria that the user chooses including wildcard searches (requested by Obiwantje and others)</li>
|
||||
|
||||
@@ -105,11 +105,6 @@ namespace SabreTools.Helper
|
||||
helptext.Add("");
|
||||
helptext.Add("Options:");
|
||||
helptext.Add(" -?, -h, --help Show this help");
|
||||
helptext.Add(" -a, --add Add a new system or source to the database");
|
||||
helptext.Add(" -manu= Manufacturer name (system only)");
|
||||
helptext.Add(" -system= System name (system only)");
|
||||
helptext.Add(" -source= Source name (source only)");
|
||||
helptext.Add(" -url= URL (source only)");
|
||||
helptext.Add(" -d, --dfd Create a DAT from an input directory");
|
||||
helptext.Add(" -nm, --noMD5 Don't include MD5 in output");
|
||||
helptext.Add(" -ns, --noSHA1 Don't include SHA1 in output");
|
||||
@@ -141,25 +136,11 @@ namespace SabreTools.Helper
|
||||
helptext.Add(" -exta= First set of extensions (comma-separated)");
|
||||
helptext.Add(" -extb= Second set of extensions (comma-separated)");
|
||||
helptext.Add(" -out= Output directory");
|
||||
helptext.Add(" -g, --generate Start tool in generate mode");
|
||||
helptext.Add(" -system= System ID to generate from");
|
||||
helptext.Add(" -nr, --no-rename Don't auto-rename games");
|
||||
helptext.Add(" -o, --old Output DAT in CMP format instead of XML");
|
||||
helptext.Add(" -ga, --generate-all Start tool in generate all mode");
|
||||
helptext.Add(" -nr, --no-rename Don't auto-rename games");
|
||||
helptext.Add(" -o, --old Output DAT in CMP format instead of XML");
|
||||
helptext.Add(" -he, --headerer Extract and remove copier headers");
|
||||
helptext.Add(" -r, --restore Restore header to file based on SHA-1 instead");
|
||||
helptext.Add(" -out= Output directory");
|
||||
helptext.Add(" -hs, --hash-split Split a DAT or folder by best-available hashes");
|
||||
helptext.Add(" -out= Output directory");
|
||||
helptext.Add(" -i, --import Start tool in import mode");
|
||||
helptext.Add(" -ig, --ignore Don't prompt for new sources");
|
||||
helptext.Add(" -lso, --list-sources List all sources (id <= name)");
|
||||
helptext.Add(" -lsy, --list-systems List all systems (id <= name)");
|
||||
helptext.Add(" -rm, --remove Remove a system or source from the database");
|
||||
helptext.Add(" -system= System ID");
|
||||
helptext.Add(" -source= Source ID");
|
||||
helptext.Add(" -st, --stats Get statistics on all input DATs");
|
||||
helptext.Add(" -si, --single Show individual statistics");
|
||||
helptext.Add(" -ts, --type-split Split a DAT or folder by file types (rom/disk)");
|
||||
|
||||
@@ -185,9 +185,6 @@ namespace SabreTools.Helper
|
||||
|
||||
#region Database schema
|
||||
|
||||
public const string DATabaseDbSchema = "dats";
|
||||
public const string DATabaseFileName = "dats.sqlite";
|
||||
public const string DATabaseConnectionString = "Data Source=" + DATabaseFileName + ";Version = 3;";
|
||||
public const string HeadererDbSchema = "Headerer";
|
||||
public const string HeadererFileName = "Headerer.sqlite";
|
||||
public const string HeadererConnectionString = "Data Source=" + HeadererFileName + ";Version = 3;";
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace SabreTools.Helper
|
||||
{
|
||||
public interface IGenerate
|
||||
{
|
||||
bool Export();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace SabreTools.Helper
|
||||
{
|
||||
public interface IImport
|
||||
{
|
||||
bool UpdateDatabase();
|
||||
}
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
using Mono.Data.Sqlite;
|
||||
using SabreTools.Helper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace SabreTools
|
||||
{
|
||||
public class GenerateTwo : IGenerate
|
||||
{
|
||||
// Private instance variables
|
||||
private string _systemid;
|
||||
private string _sourceid;
|
||||
private string _datroot;
|
||||
private string _outroot;
|
||||
private string _connectionString;
|
||||
private bool _norename;
|
||||
private bool _old;
|
||||
|
||||
// Private required variables
|
||||
private Logger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a Generate object with the given information
|
||||
/// </summary>
|
||||
/// <param name="systemid">String representing the system id (blank means all)</param>
|
||||
/// <param name="sourceid">String representing the source id (blank means all) [CURRENTLY UNUSED]</param>
|
||||
/// <param name="datroot">Root directory where all DAT files are held</param>
|
||||
/// <param name="outroot">Root directory where new DAT files are output</param>
|
||||
/// <param name="connectionString">Connection string for SQLite</param>
|
||||
/// <param name="logger">Logger object for file or console output</param>
|
||||
/// <param name="norename">True if files should not be renamed with system and/or source in merged mode (default false)</param>
|
||||
/// <param name="old">True if the output file should be in ClrMamePro format (default false)</param>
|
||||
public GenerateTwo(string systemid, string sourceid, string datroot, string outroot, string connectionString, Logger logger, bool norename = false, bool old = false)
|
||||
{
|
||||
_systemid = systemid;
|
||||
_sourceid = sourceid;
|
||||
_datroot = datroot;
|
||||
_outroot = outroot;
|
||||
_connectionString = connectionString;
|
||||
_logger = logger;
|
||||
_norename = norename;
|
||||
_old = old;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a DAT file that is represented by the data in the Generate object.
|
||||
/// </summary>
|
||||
/// <returns>True if the file could be created, false otherwise</returns>
|
||||
public bool Export()
|
||||
{
|
||||
string name = "";
|
||||
string path = _datroot;
|
||||
|
||||
// If the System ID isn't set, then we will merge everything
|
||||
if (_systemid != "")
|
||||
{
|
||||
string system = "";
|
||||
|
||||
// First get the name of the system, if possible
|
||||
string query = "SELECT manufacturer, name FROM system WHERE id=" + _systemid;
|
||||
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
||||
{
|
||||
dbc.Open();
|
||||
|
||||
using (SqliteCommand slc = new SqliteCommand(query, dbc))
|
||||
{
|
||||
using (SqliteDataReader sldr = slc.ExecuteReader())
|
||||
{
|
||||
if (sldr.Read())
|
||||
{
|
||||
system = sldr.GetString(0) + " - " + sldr.GetString(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find anything, then return
|
||||
if (system == "")
|
||||
{
|
||||
_logger.Warning("No system could be found with id " + _systemid);
|
||||
return false;
|
||||
}
|
||||
|
||||
name = system.Trim();
|
||||
path = Path.Combine(path, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "ALL";
|
||||
}
|
||||
|
||||
// Get the rest of the info as well
|
||||
string date = DateTime.Now.ToString("yyyyMMddHHmmss");
|
||||
string description = name + " (merged " + date + ")";
|
||||
name += " (merged)";
|
||||
|
||||
// For good measure, get all sources
|
||||
Dictionary<int, string> sources = new Dictionary<int, string>();
|
||||
sources.Add(0, "Default");
|
||||
|
||||
string squery = "SELECT id, name FROM source";
|
||||
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
||||
{
|
||||
dbc.Open();
|
||||
|
||||
using (SqliteCommand slc = new SqliteCommand(squery, dbc))
|
||||
{
|
||||
using (SqliteDataReader sldr = slc.ExecuteReader())
|
||||
{
|
||||
while (sldr.Read())
|
||||
{
|
||||
sources.Add(sldr.GetInt32(0), sldr.GetString(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get a list of files to sourceid mappings
|
||||
Dictionary<string, string> sourcemap = new Dictionary<string, string>();
|
||||
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
||||
{
|
||||
dbc.Open();
|
||||
|
||||
string tquery = "SELECT DISTINCT dats.sha1, datsdata.value FROM dats JOIN datsdata ON dats.id=datsdata.id WHERE key='source'";
|
||||
using (SqliteCommand slc = new SqliteCommand(tquery, dbc))
|
||||
{
|
||||
using (SqliteDataReader sldr = slc.ExecuteReader())
|
||||
{
|
||||
while (sldr.Read())
|
||||
{
|
||||
string tempsha1 = sldr.GetString(0);
|
||||
string tempval = sldr.GetString(1);
|
||||
if (!sourcemap.ContainsKey(tempsha1))
|
||||
{
|
||||
sourcemap.Add(tempsha1, tempval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the output DatData object
|
||||
DatFile datdata = new DatFile
|
||||
{
|
||||
FileName = description,
|
||||
Name = name,
|
||||
Description = description,
|
||||
Version = "",
|
||||
Date = date,
|
||||
Category = "SabreTools",
|
||||
Author = "SabreTools",
|
||||
ForcePacking = ForcePacking.None,
|
||||
OutputFormat = (_old ? OutputFormat.ClrMamePro : OutputFormat.Xml),
|
||||
MergeRoms = true,
|
||||
};
|
||||
|
||||
// Now read in all of the files
|
||||
SHA1 sha1 = SHA1.Create();
|
||||
foreach (string file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
string hash = "";
|
||||
using (FileStream fs = File.Open(file, FileMode.Open))
|
||||
{
|
||||
hash = BitConverter.ToString(sha1.ComputeHash(fs)).Replace("-", "");
|
||||
}
|
||||
|
||||
int tempSrcId = 0;
|
||||
if (sourcemap.ContainsKey(hash))
|
||||
{
|
||||
Int32.TryParse(sourcemap[hash], out tempSrcId);
|
||||
}
|
||||
DatFile.Parse(file, 0, tempSrcId, ref datdata, _logger);
|
||||
}
|
||||
|
||||
// If the dictionary is empty for any reason, tell the user and exit
|
||||
if (datdata.Files.Keys.Count == 0 || datdata.Files.Count == 0)
|
||||
{
|
||||
_logger.Log("No roms found for system ID " + _systemid);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now process all of the roms
|
||||
_logger.User("Cleaning rom data");
|
||||
List<string> keys = datdata.Files.Keys.ToList();
|
||||
foreach (string key in keys)
|
||||
{
|
||||
List<DatItem> temp = new List<DatItem>();
|
||||
List<DatItem> newroms = datdata.Files[key];
|
||||
for (int i = 0; i < newroms.Count; i++)
|
||||
{
|
||||
Rom rom = (Rom)newroms[i];
|
||||
|
||||
// In the case that the RomData is incomplete, skip it
|
||||
if (rom.Name == null || rom.MachineName == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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");
|
||||
|
||||
// Run the name through the filters to make sure that it's correct
|
||||
rom.MachineName = Style.NormalizeChars(rom.MachineName);
|
||||
rom.MachineName = Style.RussianToLatin(rom.MachineName);
|
||||
rom.MachineName = Style.SearchPattern(rom.MachineName);
|
||||
|
||||
// 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.MachineName);
|
||||
rom.MachineName = stripMatch.Groups[1].Value;
|
||||
|
||||
rom.MachineName = rom.MachineName.TrimEnd().TrimStart();
|
||||
|
||||
if (!_norename)
|
||||
{
|
||||
rom.MachineName += " [" + sources[rom.SourceID] + "]";
|
||||
}
|
||||
|
||||
// If a game has source "0" it's Default. Make this Int32.MaxValue for sorting purposes
|
||||
if (rom.SourceID == 0)
|
||||
{
|
||||
rom.SourceID = Int32.MaxValue;
|
||||
}
|
||||
|
||||
temp.Add(rom);
|
||||
}
|
||||
datdata.Files[key] = temp;
|
||||
}
|
||||
|
||||
// Then write out the file
|
||||
DatFile.WriteDatfile(datdata, _outroot, _logger, _norename);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,455 +0,0 @@
|
||||
using Mono.Data.Sqlite;
|
||||
using SabreTools.Helper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace SabreTools
|
||||
{
|
||||
public class ImportTwo : IImport
|
||||
{
|
||||
// Private instance variables
|
||||
private string _datroot;
|
||||
private string _connectionString;
|
||||
private Logger _logger;
|
||||
private bool _ignore;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize an Import object with the given information
|
||||
/// </summary>
|
||||
/// <param name="datroot">Root directory where all DAT files are held</param>
|
||||
/// <param name="connectionString">Connection string for SQLite</param>
|
||||
/// <param name="logger">Logger object for file or console output</param>
|
||||
/// <param name="ignore">False if each DAT that has no defined source asks for user input (default), true otherwise</param>
|
||||
public ImportTwo(string datroot, string connectionString, Logger logger, bool ignore = false)
|
||||
{
|
||||
_datroot = datroot;
|
||||
_connectionString = connectionString;
|
||||
_logger = logger;
|
||||
_ignore = ignore;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform initial or incremental import of DATs in the root folder
|
||||
/// </summary>
|
||||
/// <returns>True if the data could be inserted or updated correctly, false otherwise</returns>
|
||||
public bool UpdateDatabase()
|
||||
{
|
||||
_logger.User("Beginning import/update process");
|
||||
|
||||
Dictionary<Tuple<long, string, string>, int> missing = ImportData();
|
||||
bool success = RemoveData(missing);
|
||||
|
||||
_logger.User("Import/update process complete!");
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Import data into the database and return all files not found in the list
|
||||
/// </summary>
|
||||
/// <returns>List of files that were not found in the audit</returns>
|
||||
private Dictionary<Tuple<long, string, string>, int> ImportData()
|
||||
{
|
||||
// Create the empty dictionary for file filtering and output
|
||||
Dictionary<Tuple<long, string, string>, int> dbfiles = new Dictionary<Tuple<long, string, string>, int>();
|
||||
|
||||
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
||||
{
|
||||
dbc.Open();
|
||||
_logger.User("Populating reference objects");
|
||||
|
||||
// Populate the list of files in the database with Tuples (size, sha1, name)
|
||||
string query = "SELECT id, size, sha1, name FROM dats";
|
||||
using (SqliteCommand slc = new SqliteCommand(query, dbc))
|
||||
{
|
||||
using (SqliteDataReader sldr = slc.ExecuteReader())
|
||||
{
|
||||
while (sldr.Read())
|
||||
{
|
||||
dbfiles.Add(Tuple.Create(sldr.GetInt64(1), sldr.GetString(2), sldr.GetString(3)), sldr.GetInt32(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate the list of systems
|
||||
Dictionary<string, int> systems = new Dictionary<string, int>();
|
||||
query = "SELECT id, manufacturer, name FROM system";
|
||||
using (SqliteCommand slc = new SqliteCommand(query, dbc))
|
||||
{
|
||||
using (SqliteDataReader sldr = slc.ExecuteReader())
|
||||
{
|
||||
while (sldr.Read())
|
||||
{
|
||||
systems.Add(sldr.GetString(1) + " - " + sldr.GetString(2), sldr.GetInt32(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate the list of sources (initial)
|
||||
SortedDictionary<string, int> sources = new SortedDictionary<string, int>();
|
||||
sources.Add("default", 0);
|
||||
query = "SELECT name, id FROM source";
|
||||
using (SqliteCommand sslc = new SqliteCommand(query, dbc))
|
||||
{
|
||||
using (SqliteDataReader ssldr = sslc.ExecuteReader())
|
||||
{
|
||||
while (ssldr.Read())
|
||||
{
|
||||
sources.Add(ssldr.GetString(0).ToLowerInvariant(), ssldr.GetInt32(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Interate through each system and check files
|
||||
SHA1 sha1 = SHA1.Create();
|
||||
foreach (KeyValuePair<string, int> kv in systems)
|
||||
{
|
||||
_logger.User("Processing DATs for system: '" + kv.Key + "'");
|
||||
|
||||
// Set the folder to iterate through based on the DAT root
|
||||
string folder = Path.Combine(_datroot, kv.Key.Trim());
|
||||
|
||||
// Audit all files in the folder
|
||||
foreach (string file in Directory.EnumerateFiles(folder, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
// First get the file information for comparison
|
||||
long size = (new FileInfo(file)).Length;
|
||||
string hash = "";
|
||||
using (FileStream fs = File.Open(file, FileMode.Open))
|
||||
{
|
||||
hash = BitConverter.ToString(sha1.ComputeHash(fs)).Replace("-", "");
|
||||
}
|
||||
|
||||
// If it's not in the list of known files, add it
|
||||
if (!dbfiles.ContainsKey(Tuple.Create(size, hash, file)))
|
||||
{
|
||||
// First add the information to the database as is and return the new insert ID
|
||||
_logger.Log("Adding file information for " + Path.GetFileName(file));
|
||||
|
||||
int hashid = -1;
|
||||
query = @"INSERT INTO dats (size, sha1, name)
|
||||
VALUES (" + (new FileInfo(file)).Length + ", '" + hash + "', '" + file.Replace("'", "''") + @"')";
|
||||
using (SqliteCommand slc = new SqliteCommand(query, dbc))
|
||||
{
|
||||
slc.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
query = "SELECT last_insert_rowid()";
|
||||
using (SqliteCommand slc = new SqliteCommand(query, dbc))
|
||||
{
|
||||
using (SqliteDataReader sldr = slc.ExecuteReader())
|
||||
{
|
||||
if (sldr.Read())
|
||||
{
|
||||
hashid = sldr.GetInt32(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Next we try to figure out the source ID from the name
|
||||
string possiblesource = GetSourceFromFileName(Path.GetFileName(file));
|
||||
|
||||
// Try to get the source ID from the name
|
||||
int sourceid = (sources.ContainsKey(possiblesource.ToLowerInvariant()) ? sources[possiblesource] : 0);
|
||||
|
||||
// If we have a "default" ID and we're not ignoring new sources, prompt for a source input
|
||||
if (!_ignore && sourceid <= 1)
|
||||
{
|
||||
// We want to reset "Default" at this point, just in case
|
||||
if (possiblesource.ToLowerInvariant() == "default")
|
||||
{
|
||||
possiblesource = "";
|
||||
}
|
||||
|
||||
// If the source is blank, ask the user to supply one
|
||||
while (possiblesource == "" && sourceid == 0)
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabaseTwo");
|
||||
|
||||
Console.WriteLine("Sources:");
|
||||
foreach (KeyValuePair<string, int> pair in sources)
|
||||
{
|
||||
Console.WriteLine(" " + pair.Value + " - " + Style.SentenceCase(pair.Key));
|
||||
}
|
||||
Console.WriteLine("\nFor file name: " + Path.GetFileName(file));
|
||||
Console.Write("Select a source above or enter a new one: ");
|
||||
possiblesource = Console.ReadLine();
|
||||
|
||||
Int32.TryParse(possiblesource, out sourceid);
|
||||
|
||||
// If the value could be parsed, reset the source string
|
||||
if (sourceid != 0)
|
||||
{
|
||||
possiblesource = "";
|
||||
}
|
||||
|
||||
// If the source ID is set check to see if it's valid
|
||||
if (sourceid != 0 && !sources.ContainsValue(sourceid))
|
||||
{
|
||||
Console.WriteLine("Invalid selection: " + sourceid);
|
||||
Console.ReadLine();
|
||||
sourceid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a non-empty possible source and it's in the database, get the id
|
||||
if (possiblesource != "" && sources.ContainsKey(possiblesource.ToLowerInvariant()))
|
||||
{
|
||||
sourceid = sources[possiblesource.ToLowerInvariant()];
|
||||
}
|
||||
|
||||
// If we have a non-empty possible source and it's not in the database, insert and get the id
|
||||
else if (possiblesource != "" && !sources.ContainsKey(possiblesource.ToLowerInvariant()))
|
||||
{
|
||||
query = @"BEGIN;
|
||||
INSERT INTO source (name, url)
|
||||
VALUES ('" + possiblesource + @"', '');
|
||||
SELECT last_insertConstants.Rowid();
|
||||
COMMIT;";
|
||||
using (SqliteCommand slc = new SqliteCommand(query, dbc))
|
||||
{
|
||||
using (SqliteDataReader sldr = slc.ExecuteReader())
|
||||
{
|
||||
if (sldr.Read())
|
||||
{
|
||||
sourceid = sldr.GetInt32(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new source to the current dictionary
|
||||
sources.Add(possiblesource.ToLowerInvariant(), sourceid);
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have a source ID, we can add the mappings for system and source to the database
|
||||
query = @"INSERT OR IGNORE INTO datsdata (id, key, value)
|
||||
VALUES (" + hashid + ", 'source', '" + sourceid + @"'),
|
||||
(" + hashid + ", 'system', '" + kv.Value + "')";
|
||||
using (SqliteCommand slc = new SqliteCommand(query, dbc))
|
||||
{
|
||||
slc.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, remove it from the list of found items
|
||||
else
|
||||
{
|
||||
dbfiles.Remove(Tuple.Create(size, hash, file));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dbfiles;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all data associated with various files
|
||||
/// </summary>
|
||||
/// <param name="missing">List of file identifiers to remove from the database</param>
|
||||
/// <returns>True if everything went well, false otherwise</returns>
|
||||
private bool RemoveData(Dictionary<Tuple<long, string, string>, int> missing)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
||||
{
|
||||
dbc.Open();
|
||||
|
||||
// Get a comma-separated list of IDs from the input files
|
||||
string idlist = String.Join(",", missing.Values);
|
||||
|
||||
// Now remove all of the files from the database
|
||||
string query = @"BEGIN;
|
||||
DELETE FROM datsdata WHERE id IN (" + idlist + @");
|
||||
DELETE FROM dats WHERE id IN (" + idlist + @");
|
||||
COMMIT;";
|
||||
using (SqliteCommand slc = new SqliteCommand(query, dbc))
|
||||
{
|
||||
slc.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the source name from the file name, if possible
|
||||
/// </summary>
|
||||
/// <param name="filename">The name of the file to be checked</param>
|
||||
/// <returns>The name of the source if determined, blank otherwise</returns>
|
||||
private string GetSourceFromFileName(string filename)
|
||||
{
|
||||
string source = "Default";
|
||||
|
||||
// Determine which dattype we have
|
||||
GroupCollection fileinfo;
|
||||
|
||||
if (Regex.IsMatch(filename, Constants.NonGoodPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.NonGoodPattern).Groups;
|
||||
if (!Mappings.DatMaps["NonGood"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as NonGood but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "NonGood";
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.NonGoodSpecialPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.NonGoodSpecialPattern).Groups;
|
||||
if (!Mappings.DatMaps["NonGood"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as NonGood but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "NonGood";
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.GoodPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.GoodPattern).Groups;
|
||||
if (!Mappings.DatMaps["Good"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as Good but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "Good";
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.GoodXmlPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.GoodXmlPattern).Groups;
|
||||
if (!Mappings.DatMaps["Good"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as Good but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "Good";
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.MaybeIntroPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.MaybeIntroPattern).Groups;
|
||||
if (!Mappings.DatMaps["MaybeIntro"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as Maybe-Intro but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "Maybe-Intro";
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.NoIntroPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.NoIntroPattern).Groups;
|
||||
if (!Mappings.DatMaps["NoIntro"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as No-Intro but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "no-Intro";
|
||||
}
|
||||
// For numbered DATs only
|
||||
else if (Regex.IsMatch(filename, Constants.NoIntroNumberedPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.NoIntroNumberedPattern).Groups;
|
||||
if (!Mappings.DatMaps["NoIntro"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as No-Intro but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "no-Intro";
|
||||
}
|
||||
// For N-Gage and Gizmondo only
|
||||
else if (Regex.IsMatch(filename, Constants.NoIntroSpecialPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.NoIntroSpecialPattern).Groups;
|
||||
if (!Mappings.DatMaps["NoIntro"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as No-Intro but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "no-Intro";
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.RedumpPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.RedumpPattern).Groups;
|
||||
if (!Mappings.DatMaps["Redump"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as Redump but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "Redump";
|
||||
}
|
||||
// For special BIOSes only
|
||||
else if (Regex.IsMatch(filename, Constants.RedumpBiosPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.RedumpBiosPattern).Groups;
|
||||
if (!Mappings.DatMaps["Redump"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as Redump but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "Redump";
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.TosecPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.TosecPattern).Groups;
|
||||
if (!Mappings.DatMaps["TOSEC"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
// Handle special case mappings found only in TOSEC
|
||||
fileinfo = Regex.Match(filename, Constants.TosecSpecialPatternA).Groups;
|
||||
|
||||
if (!Mappings.DatMaps["TOSEC"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.TosecSpecialPatternB).Groups;
|
||||
|
||||
if (!Mappings.DatMaps["TOSEC"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as TOSEC but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
}
|
||||
}
|
||||
source = "TOSEC";
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.TruripPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.TruripPattern).Groups;
|
||||
if (!Mappings.DatMaps["TruRip"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as TruRip but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "trurip";
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.ZandroPattern))
|
||||
{
|
||||
source = "Zandro";
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.DefaultPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.DefaultPattern).Groups;
|
||||
source = fileinfo[3].Value;
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.DefaultSpecialPattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.DefaultSpecialPattern).Groups;
|
||||
source = fileinfo[3].Value;
|
||||
}
|
||||
else if (Regex.IsMatch(filename, Constants.MamePattern))
|
||||
{
|
||||
fileinfo = Regex.Match(filename, Constants.MamePattern).Groups;
|
||||
if (!Mappings.DatMaps["MAME"].ContainsKey(fileinfo[1].Value))
|
||||
{
|
||||
_logger.Warning("The filename " + fileinfo[1].Value + " was matched as MAME but could not be mapped.");
|
||||
return source;
|
||||
}
|
||||
source = "MAME";
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,8 +114,6 @@ from.
|
||||
|
||||
Included within this tool are a few former standalone executables:
|
||||
- Convert/DATToMiss: Convert an arbitrary input DAT to a different format
|
||||
- DATabase/DATabaseTwo: A managed DAT tool that allows for creating automatically merged
|
||||
DATs based on one or more systems, sources, or a combination thereof
|
||||
- DATFromDir: Create a DAT file from a folder or file, sometimes called dir2dat
|
||||
- DatSplit: Split a DAT based on 2 different file extensions
|
||||
- Filter: Filter a DAT based on various user-defined criteria, optionally using wildcards
|
||||
@@ -126,6 +124,10 @@ Included within this tool are a few former standalone executables:
|
||||
- UncompressedSize: Get statistics from one or more input DATs, including number of
|
||||
roms, disks, files with available hash, and size
|
||||
|
||||
Formerly included within this tool is a former standalone executable:
|
||||
- DATabase/DATabaseTwo: A managed DAT tool that allows for creating automatically merged
|
||||
DATs based on one or more systems, sources, or a combination thereof
|
||||
|
||||
Usage:
|
||||
SabreTools.exe [options] [filename|dirname] ...
|
||||
|
||||
@@ -133,21 +135,6 @@ Options:
|
||||
-?, -h, --help Show the built-in help text
|
||||
Built-in to most of the programs is a basic help text
|
||||
|
||||
-a, --add Add a new system or source to the database
|
||||
Add a new system or source to the DAT database, including additional information.
|
||||
|
||||
-manu= Manufacturer name
|
||||
Used only when adding a system to the database
|
||||
|
||||
-system= System name
|
||||
Used only when adding a system to the database
|
||||
|
||||
-source= Source name
|
||||
Used only when adding a source to the database
|
||||
|
||||
-url= Source URL
|
||||
Used only when adding a source to the database
|
||||
|
||||
-d, --dfd Create a DAT from each input directory
|
||||
Create a DAT file from an input directory or set of files. By default, this will
|
||||
output a DAT named based on the input directory and the current date. It will also
|
||||
@@ -268,35 +255,6 @@ Options:
|
||||
This sets an output folder to be used when the files are created. If a path
|
||||
is not defined, the application directory is used instead.
|
||||
|
||||
-g, --generate Start tool in generate mode
|
||||
This starts the tool in DATabase generate mode. This will allow for creation of
|
||||
managed DATs based on the inputted systems and sources as defined by other flags.
|
||||
|
||||
-system= System ID to generate from
|
||||
Set the system ID to be used to create an output DAT
|
||||
|
||||
-nr, --no-rename Don't auto-rename games
|
||||
By default, games are automatically renamed with the source (for system-derived
|
||||
DATs), system (for source-derived DATs), or both (for the complete merged DAT).
|
||||
This flag disables the automatic renaming and uses the game names as they are.
|
||||
|
||||
-o, --old Output DAT in CMP format instead of XML
|
||||
As a holdover from only two output formats, this tool defaults to Logiqx XML
|
||||
DAT outputs. If this flag is enabled, a clrmamepro DAT will be created instead.
|
||||
|
||||
-ga, --generate-all Start tool in generate all mode
|
||||
This starts the tool in DATabase generate all mode. This will allow for creation of
|
||||
managed DATs based on the entire DAT folder.
|
||||
|
||||
-nr, --no-rename Don't auto-rename games
|
||||
By default, games are automatically renamed with the source (for system-derived
|
||||
DATs), system (for source-derived DATs), or both (for the complete merged DAT).
|
||||
This flag disables the automatic renaming and uses the game names as they are.
|
||||
|
||||
-o, --old Output DAT in CMP format instead of XML
|
||||
As a holdover from only two output formats, this tool defaults to Logiqx XML
|
||||
DAT outputs. If this flag is enabled, a clrmamepro DAT will be created instead.
|
||||
|
||||
-hd, --headerer Backup or restore copier headers from a variety of file types
|
||||
Headerer is meant as an intermediary between header skipper files (which, a bit
|
||||
apart from their name, do not just show how to skip copier headers) and rom managers
|
||||
@@ -339,34 +297,10 @@ Options:
|
||||
This sets an output folder to be used when the files are created. If a path
|
||||
is not defined, the application directory is used instead.
|
||||
|
||||
-i, --import Start tool in import mode
|
||||
This starts the tool in DATabase import mode. This will allow for hashing of new
|
||||
DAT files in the dats folder. If a source for the DAT cannot be automatically
|
||||
determined, the user will be promted to select a source or enter a new one.
|
||||
|
||||
-ig, --ignore Don't prompt for new sources
|
||||
If a source cannot be determined, then use the "Default" source instead of
|
||||
asking the user.
|
||||
|
||||
-input= Set an input string
|
||||
This should only be used if one of the inputs starts with a flag or another already
|
||||
defined input.
|
||||
|
||||
-lso, --list-sources List all sources (id <= name)
|
||||
List all sources in the database, ordered by the internal ID and mapped to the name
|
||||
|
||||
-lsy, --list-systems List all systems (id <= name)
|
||||
List all systems in the database, ordered by the internal ID and mapped to the name
|
||||
|
||||
-rm, --remove Remove a system or source from the database
|
||||
Remove a system or source to the DAT database so it can no longer be used
|
||||
|
||||
-system= System ID"
|
||||
Internal ID of the system to be removed
|
||||
|
||||
-source= Source ID
|
||||
Internal ID of the source to be removed
|
||||
|
||||
-st, --stats Get statistics on all input DATs
|
||||
This will output by default the combined statistics for all input DAT files. The stats
|
||||
that are outputted are as follows:
|
||||
|
||||
@@ -108,9 +108,7 @@
|
||||
<Compile Include="Objects\Dat\Disk.cs" />
|
||||
<Compile Include="Objects\Dat\Release.cs" />
|
||||
<Compile Include="Objects\Dat\Sample.cs" />
|
||||
<Compile Include="Objects\GenerateTwo.cs" />
|
||||
<Compile Include="Objects\Headerer.cs" />
|
||||
<Compile Include="Objects\ImportTwo.cs" />
|
||||
<Compile Include="Objects\Dat\Rom.cs" />
|
||||
<Compile Include="Objects\SimpleSort.cs" />
|
||||
<Compile Include="Objects\Archive\ZipFileEntry.cs" />
|
||||
@@ -139,8 +137,6 @@
|
||||
<Compile Include="Tools\FileTools.cs" />
|
||||
<Compile Include="Tools\DBTools.cs" />
|
||||
<Compile Include="Data\Enums.cs" />
|
||||
<Compile Include="Interfaces\IGenerate.cs" />
|
||||
<Compile Include="Interfaces\IImport.cs" />
|
||||
<Compile Include="Objects\Logger.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Mappings\Mappings.cs" />
|
||||
@@ -150,9 +146,6 @@
|
||||
<Compile Include="Data\Build.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="dats.sqlite">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="LICENSE">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
@@ -57,46 +57,6 @@ CREATE TABLE IF NOT EXISTS data (
|
||||
SqliteCommand slc = new SqliteCommand(query, dbc);
|
||||
slc.ExecuteNonQuery();
|
||||
}
|
||||
else if (type == "dats")
|
||||
{
|
||||
string query = @"
|
||||
CREATE TABLE IF NOT EXISTS dats (
|
||||
'id' INTEGER PRIMARY KEY NOT NULL,
|
||||
'size' INTEGER NOT NULL DEFAULT -1,
|
||||
'sha1' TEXT NOT NULL,
|
||||
'name' TEXT NOT NULL
|
||||
)";
|
||||
SqliteCommand slc = new SqliteCommand(query, dbc);
|
||||
slc.ExecuteNonQuery();
|
||||
|
||||
query = @"
|
||||
CREATE TABLE IF NOT EXISTS datsdata (
|
||||
'id' INTEGER NOT NULL,
|
||||
'key' TEXT NOT NULL,
|
||||
'value' TEXT,
|
||||
PRIMARY KEY (id, key, value)
|
||||
)";
|
||||
slc = new SqliteCommand(query, dbc);
|
||||
slc.ExecuteNonQuery();
|
||||
|
||||
query = @"
|
||||
CREATE TABLE IF NOT EXISTS source (
|
||||
'id' INTEGER PRIMARY KEY NOT NULL,
|
||||
'name' TEXT NOT NULL UNIQUE,
|
||||
'url' TEXT NOT NULL
|
||||
)";
|
||||
slc = new SqliteCommand(query, dbc);
|
||||
slc.ExecuteNonQuery();
|
||||
|
||||
query = @"
|
||||
CREATE TABLE IF NOT EXISTS system (
|
||||
'id' INTEGER PRIMARY KEY NOT NULL,
|
||||
'manufacturer' TEXT NOT NULL,
|
||||
'name' TEXT NOT NULL
|
||||
)";
|
||||
slc = new SqliteCommand(query, dbc);
|
||||
slc.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,5 @@
|
||||
using Mono.Data.Sqlite;
|
||||
using SabreTools.Helper;
|
||||
using SabreTools.Helper;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SabreTools
|
||||
{
|
||||
@@ -9,119 +7,6 @@ namespace SabreTools
|
||||
{
|
||||
#region Helper methods
|
||||
|
||||
/// <summary>
|
||||
/// Perform initial setup for the program
|
||||
/// </summary>
|
||||
private static void Setup()
|
||||
{
|
||||
Build.Start("SabreTools");
|
||||
|
||||
// Perform initial database and folder setup
|
||||
if (!Directory.Exists(_datroot))
|
||||
{
|
||||
Directory.CreateDirectory(_datroot);
|
||||
}
|
||||
if (!Directory.Exists(_outroot))
|
||||
{
|
||||
Directory.CreateDirectory(_outroot);
|
||||
}
|
||||
DBTools.EnsureDatabase(Constants.DATabaseDbSchema, Constants.DATabaseFileName, Constants.DATabaseConnectionString);
|
||||
|
||||
using (SqliteConnection dbc = new SqliteConnection(Constants.DATabaseConnectionString))
|
||||
{
|
||||
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 = Path.Combine(_datroot, sldr.GetString(1).Trim() + " - " + sldr.GetString(2).Trim());
|
||||
|
||||
if (!Directory.Exists(system))
|
||||
{
|
||||
Directory.CreateDirectory(system);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DBTools.EnsureDatabase(Constants.HeadererDbSchema, Constants.HeadererFileName, Constants.HeadererConnectionString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List sources in the database
|
||||
/// </summary>
|
||||
/// <remarks>This does not have an analogue in DATabaseTwo</remarks>
|
||||
private static void ListSources()
|
||||
{
|
||||
string query = @"
|
||||
SELECT DISTINCT source.id, source.name, source.url
|
||||
FROM source
|
||||
ORDER BY source.name";
|
||||
using (SqliteConnection dbc = new SqliteConnection(Constants.DATabaseConnectionString))
|
||||
{
|
||||
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 sources found! Please add a system and then try again.");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Available Sources (id <= name):\n");
|
||||
while (sldr.Read())
|
||||
{
|
||||
Console.WriteLine(sldr.GetInt32(0) + "\t<=\t" + sldr.GetString(1) + (!String.IsNullOrEmpty(sldr.GetString(2)) ? " (" + sldr.GetString(2) + ")" : ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List systems in the database
|
||||
/// </summary>
|
||||
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(Constants.DATabaseConnectionString))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the multiplier to be used with the size given
|
||||
/// </summary>
|
||||
|
||||
@@ -11,40 +11,6 @@ namespace SabreTools
|
||||
{
|
||||
#region Init Methods
|
||||
|
||||
/// <summary>
|
||||
/// Wrap adding a new source to the database
|
||||
/// </summary>
|
||||
/// <param name="name">Source name</param>
|
||||
/// <param name="url">Source URL(s)</param>
|
||||
private static void InitAddSource(string name, string url)
|
||||
{
|
||||
if (DBTools.AddSource(name, url, Constants.DATabaseConnectionString))
|
||||
{
|
||||
_logger.Log("Source " + name + " added!");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error("Source " + name + " could not be added!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap adding a new system to the database
|
||||
/// </summary>
|
||||
/// <param name="manufacturer">Manufacturer name</param>
|
||||
/// <param name="system">System name</param>
|
||||
private static void InitAddSystem(string manufacturer, string system)
|
||||
{
|
||||
if (DBTools.AddSystem(manufacturer, system, Constants.DATabaseConnectionString))
|
||||
{
|
||||
_logger.Log("System " + manufacturer + " - " + system + " added!");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error("System " + manufacturer + " - " + system + " could not be added!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap sorting files using an input DAT
|
||||
/// </summary>
|
||||
@@ -209,56 +175,6 @@ namespace SabreTools
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap generating a DAT from the library
|
||||
/// </summary>
|
||||
/// <param name="system">System ID to be used in the DAT (blank means all)</param>
|
||||
/// <param name="norename">True if files should not be renamed with system and/or source in merged mode (default false)</param>
|
||||
/// <param name="old">True if the output file should be in ClrMamePro format (default false)</param>
|
||||
private static void InitGenerate(string systemid, bool norename, bool old)
|
||||
{
|
||||
IGenerate gen = new GenerateTwo(systemid, "" /* sourceid */, _datroot, _outroot, Constants.DATabaseConnectionString, _logger, norename, old);
|
||||
gen.Export();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap generating all standard DATs from the library
|
||||
/// </summary>
|
||||
private static void InitGenerateAll(bool norename, bool old)
|
||||
{
|
||||
List<string> systems = new List<string>();
|
||||
using (SqliteConnection dbc = new SqliteConnection(Constants.DATabaseConnectionString))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap splitting a DAT by best available hashes
|
||||
/// </summary>
|
||||
@@ -303,64 +219,6 @@ namespace SabreTools
|
||||
headerer.Process();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap importing and updating DATs
|
||||
/// </summary>
|
||||
/// <param name="ignore"></param>
|
||||
private static void InitImport(bool ignore)
|
||||
{
|
||||
IImport imp = new ImportTwo(_datroot, Constants.DATabaseConnectionString, _logger, ignore);
|
||||
imp.UpdateDatabase();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap removing an existing source from the database
|
||||
/// </summary>
|
||||
/// <param name="id">Source ID to be removed from the database</param>
|
||||
private static void InitRemoveSource(string sourceid)
|
||||
{
|
||||
int srcid = -1;
|
||||
if (Int32.TryParse(sourceid, out srcid))
|
||||
{
|
||||
if (DBTools.RemoveSource(srcid, Constants.DATabaseConnectionString))
|
||||
{
|
||||
_logger.Log("Source '" + srcid + "' removed!");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error("Source with id '" + srcid + "' could not be removed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error("Invalid input");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap removing an existing system from the database
|
||||
/// </summary>
|
||||
/// <param name="id">System ID to be removed from the database</param>
|
||||
private static void InitRemoveSystem(string systemid)
|
||||
{
|
||||
int sysid = -1;
|
||||
if (Int32.TryParse(systemid, out sysid))
|
||||
{
|
||||
if (DBTools.RemoveSystem(sysid, Constants.DATabaseConnectionString))
|
||||
{
|
||||
_logger.Log("System '" + sysid + "' removed!");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error("System with id '" + sysid + "' could not be removed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error("Invalid input");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrap sorting files using an input DAT
|
||||
/// </summary>
|
||||
|
||||
@@ -1,798 +0,0 @@
|
||||
using SabreTools.Helper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SabreTools
|
||||
{
|
||||
public partial class SabreTools
|
||||
{
|
||||
#region Menus
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based main menu
|
||||
/// </summary>
|
||||
private static void ShowMainMenu()
|
||||
{
|
||||
Console.Clear();
|
||||
string selection = "";
|
||||
while (selection.ToLowerInvariant() != "x")
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
Console.WriteLine(@"MAIN MENU
|
||||
===========================
|
||||
Make a selection:
|
||||
|
||||
1) Show command line usage
|
||||
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
|
||||
7) Add and remove systems and sources
|
||||
8) 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":
|
||||
DatToolsMenu();
|
||||
break;
|
||||
case "5":
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
ListSources();
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
break;
|
||||
case "6":
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
ListSystems();
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
break;
|
||||
case "7":
|
||||
AddRemoveMenu();
|
||||
break;
|
||||
case "8":
|
||||
Console.Clear();
|
||||
Build.Credits();
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Console.Clear();
|
||||
Console.WriteLine("Thank you for using DATabase!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based import menu
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based generate menu
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based DAT tools menu
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// At an unspecified future date, this will also include the following currently-separate programs:
|
||||
/// - DATFromDir
|
||||
/// </remarks>
|
||||
private static void DatToolsMenu()
|
||||
{
|
||||
string selection = "";
|
||||
while (selection.ToLowerInvariant() != "b")
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
Console.WriteLine(@"DAT TOOLS MENU
|
||||
===========================
|
||||
Make a selection:
|
||||
|
||||
1) Convert or clean DAT or folder of DATs
|
||||
2) Convert DAT to missfile
|
||||
3) Trim all entries in DAT and merge into a single game
|
||||
4) Merge, diff, and/or dedup 2 or more DAT files
|
||||
5) Split DAT using 2 extensions
|
||||
6) Split DATs by best available hash values
|
||||
7) Get statistics on a DAT or folder of DATs
|
||||
B) Go back to the previous menu
|
||||
");
|
||||
Console.Write("Enter selection: ");
|
||||
selection = Console.ReadLine();
|
||||
switch (selection)
|
||||
{
|
||||
case "1":
|
||||
ConvertMenu();
|
||||
break;
|
||||
case "2":
|
||||
ConvertMissMenu();
|
||||
break;
|
||||
case "3":
|
||||
TrimMergeMenu();
|
||||
break;
|
||||
case "4":
|
||||
MergeDiffMenu();
|
||||
break;
|
||||
case "5":
|
||||
ExtSplitMenu();
|
||||
break;
|
||||
case "6":
|
||||
HashSplitMenu();
|
||||
break;
|
||||
case "7":
|
||||
StatsMenu();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based any to any conversion menu
|
||||
/// </summary>
|
||||
private static void ConvertMenu()
|
||||
{
|
||||
string selection = "", input = "", outDir = "";
|
||||
OutputFormat outputFormat = OutputFormat.Xml;
|
||||
while (selection.ToLowerInvariant() != "b")
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
Console.WriteLine(@"DAT CONVERSION MENU
|
||||
===========================
|
||||
Make a selection:
|
||||
|
||||
1) File or folder to convert" + (input == "" ? "" : ":\n" + input) + @"
|
||||
2) New output folder" + (outDir == "" ? " (blank means source directory)" : ":\n" + outDir) + @"
|
||||
3) Current output type: " + (outputFormat.ToString()) + @"
|
||||
4) Process file or folder
|
||||
B) Go back to the previous menu
|
||||
");
|
||||
Console.Write("Enter selection: ");
|
||||
selection = Console.ReadLine();
|
||||
switch (selection)
|
||||
{
|
||||
case "1":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter a file or folder name: ");
|
||||
input = Console.ReadLine();
|
||||
break;
|
||||
case "2":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter a folder name: ");
|
||||
outDir = Console.ReadLine();
|
||||
break;
|
||||
case "3":
|
||||
string subsel = "";
|
||||
while (subsel == "")
|
||||
{
|
||||
Console.Clear();
|
||||
Console.WriteLine(@"Possible output formats:
|
||||
1) Xml
|
||||
2) ClrMamePro
|
||||
3) RomCenter
|
||||
4) SabreDAT
|
||||
");
|
||||
Console.Write("Please enter your selection: ");
|
||||
subsel = Console.ReadLine();
|
||||
|
||||
switch (subsel)
|
||||
{
|
||||
case "1":
|
||||
outputFormat = OutputFormat.Xml;
|
||||
break;
|
||||
case "2":
|
||||
outputFormat = OutputFormat.ClrMamePro;
|
||||
break;
|
||||
case "3":
|
||||
outputFormat = OutputFormat.RomCenter;
|
||||
break;
|
||||
case "4":
|
||||
outputFormat = OutputFormat.SabreDat;
|
||||
break;
|
||||
default:
|
||||
subsel = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "4":
|
||||
Console.Clear();
|
||||
List<string> temp = new List<string>();
|
||||
temp.Add(input);
|
||||
/*
|
||||
InitUpdate(temp, "", "", "", "", "", "", "", "", "", "", "", "", false, "", "", "",
|
||||
(outputFormat == OutputFormat.ClrMamePro), (outputFormat == OutputFormat.MissFile), (outputFormat == OutputFormat.RomCenter),
|
||||
(outputFormat == OutputFormat.SabreDat), (outputFormat == OutputFormat.Xml), false, "", "", false, "", "", false, false, false,
|
||||
false, false, false, false, false, "", "", "", -1, -1, -1, "", "", "", null, outDir, false, false);
|
||||
*/
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
input = ""; outDir = "";
|
||||
outputFormat = OutputFormat.Xml;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based DAT to missfile conversion menu
|
||||
/// </summary>
|
||||
private static void ConvertMissMenu()
|
||||
{
|
||||
string selection = "", input = "", prefix = "", postfix = "", addext = "", repext = "";
|
||||
bool usegame = true, quotes = false, gamename = false, romba = false, tsv = false;
|
||||
while (selection.ToLowerInvariant() != "b")
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
Console.WriteLine(@"DAT -> MISS CONVERT MENU
|
||||
===========================
|
||||
Make a selection:
|
||||
|
||||
1) File to convert" + (input != "" ? ":\n\t" + input : "") + @"
|
||||
2) " + (usegame ? "Output roms instead of games" : "Output games instead of roms") + @"
|
||||
3) " + (romba ? "Disable Romba-style output naming" : "Enable Romba-style output naming (overrides previous)") + @"
|
||||
4) Prefix to add to each line" + (prefix != "" ? ":\n\t" + prefix : "") + @"
|
||||
5) Postfix to add to each line" + (postfix != "" ? ":\n\t" + postfix : "") + @"
|
||||
6) " + (quotes ? "Don't add quotes around each item" : "Add quotes around each item") + @"
|
||||
7) Replace all extensions with another" + (repext != "" ? ":\t" + repext : "") + @"
|
||||
8) Add extensions to each item" + (addext != "" ? ":\n\t" + addext : "") + @"
|
||||
" + (!usegame ? " 9) " + (gamename ? "Don't add game name before every item" : "Add game name before every item") + "\n" : "") +
|
||||
@" 10) " + (romba ? "Don't output items in Romba format" : "Output items in Romba format") + @"
|
||||
12) " + (tsv ? "Don't output items in TSV format" : "Output items in TSV format") + @"
|
||||
12) Begin conversion
|
||||
B) Go back to the previous menu
|
||||
");
|
||||
Console.Write("Enter selection: ");
|
||||
selection = Console.ReadLine();
|
||||
switch (selection)
|
||||
{
|
||||
case "1":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the file name: ");
|
||||
input = Console.ReadLine();
|
||||
break;
|
||||
case "2":
|
||||
usegame = !usegame;
|
||||
break;
|
||||
case "3":
|
||||
romba = !romba;
|
||||
break;
|
||||
case "4":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the prefix: ");
|
||||
prefix = Console.ReadLine();
|
||||
break;
|
||||
case "5":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the postfix: ");
|
||||
postfix = Console.ReadLine();
|
||||
break;
|
||||
case "6":
|
||||
quotes = !quotes;
|
||||
break;
|
||||
case "7":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the replacement extension: ");
|
||||
repext = Console.ReadLine();
|
||||
break;
|
||||
case "8":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the additional extension: ");
|
||||
addext = Console.ReadLine();
|
||||
break;
|
||||
case "9":
|
||||
gamename = !gamename;
|
||||
break;
|
||||
case "10":
|
||||
romba = !romba;
|
||||
break;
|
||||
case "11":
|
||||
tsv = !tsv;
|
||||
break;
|
||||
case "12":
|
||||
Console.Clear();
|
||||
List<string> temp = new List<string>();
|
||||
temp.Add(input);
|
||||
/*
|
||||
InitUpdate(temp, "", "", "", "", "", "", "", "", "", "", "", "", false, "", "", "",
|
||||
false, true, false, false, false, usegame, prefix, postfix, quotes, repext, addext,
|
||||
gamename, romba, tsv, false, false, false, false, false, "", "", "", -1, -1, -1,
|
||||
"", "", "", null, "", false, false);
|
||||
*/
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
input = ""; prefix = ""; postfix = ""; addext = ""; repext = "";
|
||||
usegame = true; quotes = false; gamename = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based TrimMerge menu
|
||||
/// </summary>
|
||||
private static void TrimMergeMenu()
|
||||
{
|
||||
string selection = "", input = "", root = "";
|
||||
bool forceunpack = true, rename = true;
|
||||
while (selection.ToLowerInvariant() != "b")
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
Console.WriteLine(@"DAT TRIM MENU
|
||||
===========================
|
||||
Make a selection:
|
||||
|
||||
1) File or folder to process" + (input != "" ? ":\n\t" + input : "") + @"
|
||||
2) Set the root directory for trimming calculation" + (root != "" ? ":\n\t" + root : "") + @"
|
||||
3) " + (forceunpack ? "Remove 'forcepacking=\"unzip\"' from output" : "Add 'forcepacking=\"unzip\"' to output") + @"
|
||||
4) " + (rename ? "Keep all game names" : "Rename all games to '!'") + @"
|
||||
5) Process the file or folder
|
||||
B) Go back to the previous menu
|
||||
");
|
||||
Console.Write("Enter selection: ");
|
||||
selection = Console.ReadLine();
|
||||
switch (selection)
|
||||
{
|
||||
case "1":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the file or folder name: ");
|
||||
input = Console.ReadLine();
|
||||
break;
|
||||
case "2":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the root folder name: ");
|
||||
root = Console.ReadLine();
|
||||
break;
|
||||
case "3":
|
||||
forceunpack = !forceunpack;
|
||||
break;
|
||||
case "4":
|
||||
rename = !rename;
|
||||
break;
|
||||
case "5":
|
||||
Console.Clear();
|
||||
//InitTrimMerge(input, root, rename, forceunpack);
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
selection = ""; input = ""; root = "";
|
||||
forceunpack = true; rename = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based MergeDiff menu
|
||||
/// </summary>
|
||||
private static void MergeDiffMenu()
|
||||
{
|
||||
string selection = "", input = "", name = "", desc = "", cat = "", version = "", author = "";
|
||||
bool dedup = false, diff = false, bare = false, forceunpack = false, old = false, superdat = false, cascade = false, inplace = false;
|
||||
while (selection.ToLowerInvariant() != "b")
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
Console.WriteLine(@"MERGE AND DIFF MENU
|
||||
===========================
|
||||
Make a selection:
|
||||
|
||||
1) Add a file or folder to process
|
||||
2) Internal DAT name" + (name != "" ? ":\t" + name : "") + @"
|
||||
3) External DAT name/description" + (desc != "" ? ":\t" + desc : "") + @"
|
||||
4) Category" + (cat != "" ? ":\t" + cat : "") + @"
|
||||
5) Version" + (version != "" ? ":\t" + version : "") + @"
|
||||
6) Author" + (author != "" ? ":\t" + author : "") + @"
|
||||
7) " + (dedup ? "Don't dedup files in output" : "Dedup files in output") + @" 8) " + (diff ? "Only merge the input files" : "Diff the input files") + @"
|
||||
9) " + (bare ? "Don't append the date to the name" : "Append the date to the name") + @"
|
||||
10) " + (forceunpack ? "Remove 'forcepacking=\"unzip\"' from output" : "Add 'forcepacking=\"unzip\"' to output") + @"
|
||||
11) " + (old ? "Enable XML output" : "Enable ClrMamePro output") + @"
|
||||
12) " + (superdat ? "Disable SuperDAT output" : "Enable SuperDAT output") + @"
|
||||
13) " + (cascade ? "Disable cascaded diffing (only if diff enabled)" : "Enable cascaded diffing (only if diff enabled)") + @"
|
||||
14) " + (inplace ? "Disable inplace diffing (only if cascade enabled)" : "Enable inplace diffing (only if cascade enabled)") + @"
|
||||
15) Process the DAT(s)
|
||||
B) Go back to the previous menu
|
||||
");
|
||||
Console.Write("Enter selection: ");
|
||||
selection = Console.ReadLine();
|
||||
switch (selection)
|
||||
{
|
||||
case "1":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter a file or folder name: ");
|
||||
input += (input == "" ? "" : ";") + Console.ReadLine();
|
||||
break;
|
||||
case "2":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter a name: ");
|
||||
name = Console.ReadLine();
|
||||
break;
|
||||
case "3":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter a description: ");
|
||||
desc = Console.ReadLine();
|
||||
break;
|
||||
case "4":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter a category: ");
|
||||
cat = Console.ReadLine();
|
||||
break;
|
||||
case "5":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter a version: ");
|
||||
version = Console.ReadLine();
|
||||
break;
|
||||
case "6":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter an author: ");
|
||||
author = Console.ReadLine();
|
||||
break;
|
||||
case "7":
|
||||
dedup = !dedup;
|
||||
break;
|
||||
case "8":
|
||||
diff = !diff;
|
||||
break;
|
||||
case "9":
|
||||
bare = !bare;
|
||||
break;
|
||||
case "10":
|
||||
forceunpack = !forceunpack;
|
||||
break;
|
||||
case "11":
|
||||
old = !old;
|
||||
break;
|
||||
case "12":
|
||||
superdat = !superdat;
|
||||
break;
|
||||
case "13":
|
||||
cascade = !cascade;
|
||||
break;
|
||||
case "14":
|
||||
inplace = !inplace;
|
||||
break;
|
||||
case "15":
|
||||
Console.Clear();
|
||||
List<string> inputs = new List<string>(input.Split(';'));
|
||||
//InitMergeDiff(inputs, name, desc, cat, version, author, diff, dedup, bare, forceunpack, old, superdat, cascade, inplace);
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
selection = ""; input = ""; name = ""; desc = ""; cat = ""; version = ""; author = "";
|
||||
dedup = false; diff = false; bare = false; forceunpack = false; old = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based ExtSplit menu
|
||||
/// </summary>
|
||||
private static void ExtSplitMenu()
|
||||
{
|
||||
string selection = "", input = "", exta = "", extb = "", outDir = "";
|
||||
while (selection.ToLowerInvariant() != "b")
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
Console.WriteLine(@"EXTENSION SPLIT MENU
|
||||
===========================
|
||||
Make a selection:
|
||||
|
||||
1) File to split" + (input != "" ? ":\n\t" + input : "") + @"
|
||||
2) First file extension" + (exta != "" ? ":\t" + exta : "") + @"
|
||||
3) Second file extension" + (extb != "" ? ":\t" + extb : "") + @"
|
||||
4) Output directory" + (outDir != "" ? ":\n\t" + outDir : "") + @"
|
||||
5) Split the file
|
||||
B) Go back to the previous menu
|
||||
");
|
||||
Console.Write("Enter selection: ");
|
||||
selection = Console.ReadLine();
|
||||
switch (selection)
|
||||
{
|
||||
case "1":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the file name: ");
|
||||
input = Console.ReadLine();
|
||||
break;
|
||||
case "2":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the first extension: ");
|
||||
exta = Console.ReadLine();
|
||||
break;
|
||||
case "3":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the second extension: ");
|
||||
extb = Console.ReadLine();
|
||||
break;
|
||||
case "4":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the output directory: ");
|
||||
outDir = Console.ReadLine();
|
||||
break;
|
||||
case "5":
|
||||
Console.Clear();
|
||||
List<string> inputs = new List<string>();
|
||||
inputs.Add(input);
|
||||
InitExtSplit(inputs, exta, extb, outDir);
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
input = ""; exta = ""; extb = ""; outDir = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based HashSplit menu
|
||||
/// </summary>
|
||||
private static void HashSplitMenu()
|
||||
{
|
||||
string selection = "", input = "", outDir = "";
|
||||
while (selection.ToLowerInvariant() != "b")
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
Console.WriteLine(@"HASH SPLIT MENU
|
||||
===========================
|
||||
Make a selection:
|
||||
|
||||
1) File or folder to split" + (input != "" ? ":\n\t" + input : "") + @"
|
||||
2) Output directory" + (outDir != "" ? ":\n\t" + outDir : "") + @"
|
||||
3) Split the file
|
||||
B) Go back to the previous menu
|
||||
");
|
||||
Console.Write("Enter selection: ");
|
||||
selection = Console.ReadLine();
|
||||
switch (selection)
|
||||
{
|
||||
case "1":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the file or folder name: ");
|
||||
input = Console.ReadLine();
|
||||
break;
|
||||
case "2":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the output directory: ");
|
||||
outDir = Console.ReadLine();
|
||||
break;
|
||||
case "3":
|
||||
Console.Clear();
|
||||
List<string> inputs = new List<string>();
|
||||
inputs.Add(input);
|
||||
InitHashSplit(inputs, outDir);
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
input = ""; outDir = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based Stats menu
|
||||
/// </summary>
|
||||
private static void StatsMenu()
|
||||
{
|
||||
string selection = "", input = "";
|
||||
bool single = false;
|
||||
while (selection.ToLowerInvariant() != "b")
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
Console.WriteLine(@"STATISTICS MENU
|
||||
===========================
|
||||
Make a selection:
|
||||
|
||||
1) File or folder to get stats on" + (input != "" ? ":\n\t" + input : "") + @"
|
||||
2) " + (single ? "Don't show individual DAT statistics" : "Show individual DAT statistics") + @"
|
||||
3) Get stats on the file(s)
|
||||
B) Go back to the previous menu
|
||||
");
|
||||
Console.Write("Enter selection: ");
|
||||
selection = Console.ReadLine();
|
||||
switch (selection)
|
||||
{
|
||||
case "1":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the file or folder name: ");
|
||||
input = Console.ReadLine();
|
||||
break;
|
||||
case "2":
|
||||
single = !single;
|
||||
break;
|
||||
case "3":
|
||||
Console.Clear();
|
||||
List<string> inputs = new List<string>();
|
||||
inputs.Add(input);
|
||||
InitStats(inputs, single);
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
input = "";
|
||||
single = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the text-based add and remove menu
|
||||
/// </summary>
|
||||
private static void AddRemoveMenu()
|
||||
{
|
||||
string selection = "", manufacturer = "", system = "", name = "", url = "";
|
||||
while (selection.ToLowerInvariant() != "b")
|
||||
{
|
||||
Console.Clear();
|
||||
Build.Start("DATabase");
|
||||
Console.WriteLine(@"ADD AND REMOVE MENU
|
||||
===========================
|
||||
Make a selection:
|
||||
|
||||
1) Add a source
|
||||
2) Remove a source
|
||||
3) Add a system
|
||||
4) Remove a system
|
||||
B) Go back to the previous menu
|
||||
");
|
||||
Console.Write("Enter selection: ");
|
||||
selection = Console.ReadLine();
|
||||
switch (selection)
|
||||
{
|
||||
case "1":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the source name: ");
|
||||
name = Console.ReadLine();
|
||||
Console.Write("\nPlease enter the source URL: ");
|
||||
url = Console.ReadLine();
|
||||
InitAddSource(name, url);
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
manufacturer = ""; system = ""; name = ""; url = "";
|
||||
break;
|
||||
case "2":
|
||||
Console.Clear();
|
||||
ListSources();
|
||||
Console.Write("Please enter the source: ");
|
||||
InitRemoveSource(Console.ReadLine());
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
manufacturer = ""; system = ""; name = ""; url = "";
|
||||
break;
|
||||
case "3":
|
||||
Console.Clear();
|
||||
Console.Write("Please enter the manufacturer: ");
|
||||
manufacturer = Console.ReadLine();
|
||||
Console.Write("\nPlease enter the system: ");
|
||||
system = Console.ReadLine();
|
||||
InitAddSystem(manufacturer, system);
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
manufacturer = ""; system = ""; name = ""; url = "";
|
||||
break;
|
||||
case "4":
|
||||
Console.Clear();
|
||||
ListSystems();
|
||||
Console.Write("Please enter the system: ");
|
||||
InitRemoveSystem(Console.ReadLine());
|
||||
Console.Write("\nPress any key to continue...");
|
||||
Console.ReadKey();
|
||||
manufacturer = ""; system = ""; name = ""; url = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,8 @@ namespace SabreTools
|
||||
{
|
||||
Console.Clear();
|
||||
}
|
||||
Setup();
|
||||
Build.Start("SabreTools");
|
||||
DBTools.EnsureDatabase(Constants.HeadererDbSchema, Constants.HeadererFileName, Constants.HeadererConnectionString);
|
||||
|
||||
// Credits take precidence over all
|
||||
if ((new List<string>(args)).Contains("--credits"))
|
||||
@@ -57,18 +58,6 @@ namespace SabreTools
|
||||
// If there's no arguments, show help
|
||||
if (args.Length == 0)
|
||||
{
|
||||
/*
|
||||
// If there are no arguments, show the menu
|
||||
if (!Console.IsOutputRedirected)
|
||||
{
|
||||
ShowMainMenu();
|
||||
}
|
||||
else
|
||||
{
|
||||
Build.Help();
|
||||
}
|
||||
*/
|
||||
|
||||
Build.Help();
|
||||
_logger.Close();
|
||||
return;
|
||||
@@ -76,7 +65,6 @@ namespace SabreTools
|
||||
|
||||
// Set all default values
|
||||
bool help = false,
|
||||
add = false,
|
||||
addBlanks = false,
|
||||
addDate = false,
|
||||
archivesAsFiles = false,
|
||||
@@ -88,20 +76,12 @@ namespace SabreTools
|
||||
enableGzip = false,
|
||||
extsplit = false,
|
||||
forceunpack = false,
|
||||
generate = false,
|
||||
genall = false,
|
||||
hashsplit = false,
|
||||
headerer = false,
|
||||
ignore = false,
|
||||
import = false,
|
||||
inplace = false,
|
||||
listsrc = false,
|
||||
listsys = false,
|
||||
merge = false,
|
||||
noMD5 = false,
|
||||
norename = false,
|
||||
noSHA1 = false,
|
||||
old = false,
|
||||
quotes = false,
|
||||
rem = false,
|
||||
remext = false,
|
||||
@@ -146,7 +126,6 @@ namespace SabreTools
|
||||
header = "",
|
||||
homepage = "",
|
||||
name = "",
|
||||
manu = "",
|
||||
md5 = "",
|
||||
outDir = "",
|
||||
postfix = "",
|
||||
@@ -157,8 +136,6 @@ namespace SabreTools
|
||||
root = "",
|
||||
rootdir = "",
|
||||
sha1 = "",
|
||||
sources = "",
|
||||
systems = "",
|
||||
tempDir = "",
|
||||
url = "",
|
||||
version = "";
|
||||
@@ -174,10 +151,6 @@ namespace SabreTools
|
||||
case "--help":
|
||||
help = true;
|
||||
break;
|
||||
case "-a":
|
||||
case "--add":
|
||||
add = true;
|
||||
break;
|
||||
case "-ab":
|
||||
case "--add-blank":
|
||||
addBlanks = true;
|
||||
@@ -194,30 +167,10 @@ namespace SabreTools
|
||||
case "--cascade":
|
||||
cascade = true;
|
||||
break;
|
||||
case "-cc":
|
||||
case "--convert-cmp":
|
||||
outputFormat |= OutputFormat.ClrMamePro;
|
||||
break;
|
||||
case "-cm":
|
||||
case "--convert-miss":
|
||||
outputFormat |= OutputFormat.MissFile;
|
||||
break;
|
||||
case "-cr":
|
||||
case "--convert-rc":
|
||||
outputFormat |= OutputFormat.RomCenter;
|
||||
break;
|
||||
case "-cs":
|
||||
case "--convert-sd":
|
||||
outputFormat |= OutputFormat.SabreDat;
|
||||
break;
|
||||
case "-csv":
|
||||
case "--csv":
|
||||
tsv = false;
|
||||
break;
|
||||
case "-cx":
|
||||
case "--convert-xml":
|
||||
outputFormat |= OutputFormat.Xml;
|
||||
break;
|
||||
case "-clean":
|
||||
case "--clean":
|
||||
clean = true;
|
||||
@@ -255,14 +208,6 @@ namespace SabreTools
|
||||
case "--files":
|
||||
archivesAsFiles = true;
|
||||
break;
|
||||
case "-g":
|
||||
case "--generate":
|
||||
generate = true;
|
||||
break;
|
||||
case "-ga":
|
||||
case "--generate-all":
|
||||
genall = true;
|
||||
break;
|
||||
case "-gp":
|
||||
case "--game-prefix":
|
||||
datprefix = true;
|
||||
@@ -279,26 +224,10 @@ namespace SabreTools
|
||||
case "--hash-split":
|
||||
hashsplit = true;
|
||||
break;
|
||||
case "-i":
|
||||
case "--import":
|
||||
import = true;
|
||||
break;
|
||||
case "-ig":
|
||||
case "--ignore":
|
||||
ignore = true;
|
||||
break;
|
||||
case "-ip":
|
||||
case "--inplace":
|
||||
inplace = true;
|
||||
break;
|
||||
case "-lso":
|
||||
case "--list-sources":
|
||||
listsrc = true;
|
||||
break;
|
||||
case "-lsy":
|
||||
case "--list-systems":
|
||||
listsys = true;
|
||||
break;
|
||||
case "-m":
|
||||
case "--merge":
|
||||
merge = true;
|
||||
@@ -315,18 +244,10 @@ namespace SabreTools
|
||||
case "--not-nodump":
|
||||
nodump = false;
|
||||
break;
|
||||
case "-nr":
|
||||
case "--no-rename":
|
||||
norename = true;
|
||||
break;
|
||||
case "-ns":
|
||||
case "--noSHA1":
|
||||
noSHA1 = true;
|
||||
break;
|
||||
case "-o":
|
||||
case "--old":
|
||||
old = true;
|
||||
break;
|
||||
case "-oc":
|
||||
case "--output-cmp":
|
||||
outputFormat |= OutputFormat.ClrMamePro;
|
||||
@@ -375,10 +296,6 @@ namespace SabreTools
|
||||
case "--restore":
|
||||
restore = true;
|
||||
break;
|
||||
case "-rm":
|
||||
case "--remove":
|
||||
rem = true;
|
||||
break;
|
||||
case "-rme":
|
||||
case "--rem-ext":
|
||||
remext = true;
|
||||
@@ -408,6 +325,7 @@ namespace SabreTools
|
||||
stats = true;
|
||||
break;
|
||||
case "-trim":
|
||||
case "--trim":
|
||||
trim = true;
|
||||
break;
|
||||
case "-ts":
|
||||
@@ -509,10 +427,6 @@ namespace SabreTools
|
||||
{
|
||||
inputs.Add(temparg.Split('=')[1]);
|
||||
}
|
||||
else if (temparg.StartsWith("-manu=") && manu == "")
|
||||
{
|
||||
manu = temparg.Split('=')[1];
|
||||
}
|
||||
else if (temparg.StartsWith("-md5=") || temparg.StartsWith("--md5="))
|
||||
{
|
||||
md5 = temparg.Split('=')[1];
|
||||
@@ -577,23 +491,11 @@ namespace SabreTools
|
||||
{
|
||||
slt = GetSizeFromString(temparg.Split('=')[1]);
|
||||
}
|
||||
else if (temparg.StartsWith("-source=") && sources == "")
|
||||
{
|
||||
sources = temparg.Split('=')[1];
|
||||
}
|
||||
else if (temparg.StartsWith("-system=") && systems == "")
|
||||
{
|
||||
systems = temparg.Split('=')[1];
|
||||
}
|
||||
else if (temparg.StartsWith("-t=") || temparg.StartsWith("--temp="))
|
||||
{
|
||||
tempDir = temparg.Split('=')[1];
|
||||
}
|
||||
else if (temparg.StartsWith("-u=") || temparg.StartsWith("--url="))
|
||||
{
|
||||
url = temparg.Split('=')[1];
|
||||
}
|
||||
else if (temparg.StartsWith("-url=") && url == "")
|
||||
else if (temparg.StartsWith("-u=") || temparg.StartsWith("-url=") || temparg.StartsWith("--url="))
|
||||
{
|
||||
url = temparg.Split('=')[1];
|
||||
}
|
||||
@@ -628,8 +530,8 @@ namespace SabreTools
|
||||
}
|
||||
|
||||
// If more than one switch is enabled, show the help screen
|
||||
if (!(add ^ datfromdir ^ extsplit ^ generate ^ genall ^ hashsplit ^ headerer ^ import ^ listsrc ^
|
||||
listsys ^ (merge || diffMode != 0 || update || outputFormat != 0 || tsv != null|| trim) ^ rem ^ stats ^ typesplit))
|
||||
if (!(datfromdir ^ extsplit ^ hashsplit ^ headerer ^ (merge || diffMode != 0 || update
|
||||
|| outputFormat != 0 || tsv != null|| trim) ^ rem ^ stats ^ typesplit))
|
||||
{
|
||||
_logger.Error("Only one feature switch is allowed at a time");
|
||||
Build.Help();
|
||||
@@ -649,25 +551,8 @@ namespace SabreTools
|
||||
|
||||
// Now take care of each mode in succesion
|
||||
|
||||
// Add a source or system
|
||||
if (add)
|
||||
{
|
||||
if (manu != "" && systems != "")
|
||||
{
|
||||
InitAddSystem(manu, systems);
|
||||
}
|
||||
else if (sources != "" && url != "")
|
||||
{
|
||||
InitAddSource(manu, systems);
|
||||
}
|
||||
else
|
||||
{
|
||||
Build.Help();
|
||||
}
|
||||
}
|
||||
|
||||
// Create a DAT from a directory or set of directories
|
||||
else if (datfromdir)
|
||||
if (datfromdir)
|
||||
{
|
||||
InitDatFromDir(inputs, filename, name, description, category, version, author, forceunpack, outputFormat,
|
||||
romba, superdat, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, addBlanks, addDate, tempDir, maxParallelism);
|
||||
@@ -679,20 +564,6 @@ namespace SabreTools
|
||||
InitExtSplit(inputs, exta, extb, outDir);
|
||||
}
|
||||
|
||||
// Generate all DATs
|
||||
else if (genall)
|
||||
{
|
||||
InitImport(ignore);
|
||||
InitGenerateAll(norename, old);
|
||||
}
|
||||
|
||||
// Generate a DAT
|
||||
else if (generate)
|
||||
{
|
||||
InitImport(ignore);
|
||||
InitGenerate(systems, norename, old);
|
||||
}
|
||||
|
||||
// Split a DAT by available hashes
|
||||
else if (hashsplit)
|
||||
{
|
||||
@@ -705,41 +576,6 @@ namespace SabreTools
|
||||
InitHeaderer(inputs, restore, outDir, _logger);
|
||||
}
|
||||
|
||||
// Import a file or folder
|
||||
else if (import)
|
||||
{
|
||||
InitImport(ignore);
|
||||
}
|
||||
|
||||
// List all available sources
|
||||
else if (listsrc)
|
||||
{
|
||||
ListSources();
|
||||
}
|
||||
|
||||
// List all available systems
|
||||
else if (listsys)
|
||||
{
|
||||
ListSystems();
|
||||
}
|
||||
|
||||
// Remove a source or system
|
||||
else if (rem)
|
||||
{
|
||||
if (systems != "")
|
||||
{
|
||||
InitRemoveSystem(systems);
|
||||
}
|
||||
else if (sources != "")
|
||||
{
|
||||
InitRemoveSource(sources);
|
||||
}
|
||||
else
|
||||
{
|
||||
Build.Help();
|
||||
}
|
||||
}
|
||||
|
||||
// Get statistics on input files
|
||||
else if (stats)
|
||||
{
|
||||
|
||||
@@ -103,7 +103,6 @@
|
||||
<Compile Include="SabreTools.cs" />
|
||||
<Compile Include="Partials\SabreTools_Helpers.cs" />
|
||||
<Compile Include="Partials\SabreTools_Inits.cs" />
|
||||
<Compile Include="Partials\SabreTools_Menus.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user