2016-04-11 15:09:50 -07:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.IO;
|
2016-05-22 23:33:33 -07:00
|
|
|
|
using System.IO.Compression;
|
2016-04-11 15:09:50 -07:00
|
|
|
|
using System.Security.Cryptography;
|
2016-05-23 15:57:09 -07:00
|
|
|
|
using System.Text;
|
2016-05-22 20:42:04 -07:00
|
|
|
|
using System.Text.RegularExpressions;
|
2016-04-11 15:09:50 -07:00
|
|
|
|
|
2016-04-12 23:24:08 -07:00
|
|
|
|
using SabreTools.Helper;
|
2016-04-11 17:03:00 -07:00
|
|
|
|
using DamienG.Security.Cryptography;
|
2016-04-12 23:07:23 -07:00
|
|
|
|
using SharpCompress.Archive;
|
|
|
|
|
|
using SharpCompress.Common;
|
|
|
|
|
|
using SharpCompress.Reader;
|
2016-04-11 17:03:00 -07:00
|
|
|
|
|
2016-04-11 15:09:50 -07:00
|
|
|
|
namespace SabreTools
|
|
|
|
|
|
{
|
2016-04-11 23:49:06 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Create a DAT file from a specified file, directory, or set thereof
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class DATFromDir
|
2016-04-11 15:09:50 -07:00
|
|
|
|
{
|
2016-04-11 21:33:55 -07:00
|
|
|
|
// Path-related variables
|
2016-04-20 20:41:00 -07:00
|
|
|
|
private string _basePath;
|
|
|
|
|
|
private string _tempDir;
|
2016-04-11 21:33:55 -07:00
|
|
|
|
|
2016-05-22 12:45:20 -07:00
|
|
|
|
// User specified inputs
|
2016-04-20 20:41:00 -07:00
|
|
|
|
private List<String> _inputs;
|
2016-05-22 12:45:20 -07:00
|
|
|
|
private DatData _datdata;
|
2016-04-20 20:41:00 -07:00
|
|
|
|
private bool _noMD5;
|
|
|
|
|
|
private bool _noSHA1;
|
2016-04-21 14:38:11 -07:00
|
|
|
|
private bool _bare;
|
2016-04-20 20:41:00 -07:00
|
|
|
|
private bool _archivesAsFiles;
|
2016-05-22 17:38:17 -07:00
|
|
|
|
private bool _enableGzip;
|
2016-04-11 21:33:55 -07:00
|
|
|
|
|
|
|
|
|
|
// Other required variables
|
2016-04-20 20:41:00 -07:00
|
|
|
|
private Logger _logger;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Create a new DATFromDir object
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="inputs">A List of Strings representing the files and folders to be DATted</param>
|
2016-05-22 12:45:20 -07:00
|
|
|
|
/// <param name="datdata">DatData object representing the requested output DAT</param>
|
2016-04-20 20:41:00 -07:00
|
|
|
|
/// <param name="noMD5">True if MD5 hashes should be skipped over, false otherwise</param>
|
|
|
|
|
|
/// <param name="noSHA1">True if SHA-1 hashes should be skipped over, false otherwise</param>
|
2016-04-21 14:38:11 -07:00
|
|
|
|
/// <param name="bare">True if the date should be omitted from the DAT, false otherwise</param>
|
2016-05-22 12:45:20 -07:00
|
|
|
|
/// <param name="archivesAsFiles">True if archives should be treated as files, false otherwise</param>
|
2016-05-22 17:38:17 -07:00
|
|
|
|
/// <param name="enableGzip">True if GZIP archives should be treated as files, false otherwise</param>>
|
2016-04-20 20:41:00 -07:00
|
|
|
|
/// <param name="logger">Logger object for console and file output</param>
|
2016-05-28 15:54:06 -07:00
|
|
|
|
/// <param name="tempDir">Name of the directory to create a temp folder in (blank is current directory)</param>
|
|
|
|
|
|
public DATFromDir(List<String> inputs, DatData datdata, bool noMD5, bool noSHA1, bool bare, bool archivesAsFiles, bool enableGzip, string tempDir, Logger logger)
|
2016-04-20 20:41:00 -07:00
|
|
|
|
{
|
|
|
|
|
|
_inputs = inputs;
|
2016-05-22 12:45:20 -07:00
|
|
|
|
_datdata = datdata;
|
2016-04-20 20:41:00 -07:00
|
|
|
|
_noMD5 = noMD5;
|
|
|
|
|
|
_noSHA1 = noSHA1;
|
2016-04-21 14:38:11 -07:00
|
|
|
|
_bare = bare;
|
2016-04-20 20:41:00 -07:00
|
|
|
|
_archivesAsFiles = archivesAsFiles;
|
2016-05-22 17:38:17 -07:00
|
|
|
|
_enableGzip = enableGzip;
|
2016-05-28 15:54:06 -07:00
|
|
|
|
_tempDir = tempDir;
|
2016-04-20 20:41:00 -07:00
|
|
|
|
_logger = logger;
|
|
|
|
|
|
}
|
2016-04-11 21:33:55 -07:00
|
|
|
|
|
2016-04-11 23:49:06 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Start help or use supplied parameters
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="args">String array representing command line parameters</param>
|
|
|
|
|
|
public static void Main(string[] args)
|
2016-04-11 15:09:50 -07:00
|
|
|
|
{
|
2016-06-09 23:35:12 -07:00
|
|
|
|
// If output is being redirected, don't allow clear screens
|
|
|
|
|
|
if (!Console.IsOutputRedirected)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.Clear();
|
|
|
|
|
|
}
|
2016-04-11 23:12:40 -07:00
|
|
|
|
|
2016-04-18 16:32:17 -07:00
|
|
|
|
// Credits take precidence over all
|
|
|
|
|
|
if ((new List<string>(args)).Contains("--credits"))
|
|
|
|
|
|
{
|
|
|
|
|
|
Build.Credits();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-05-10 15:41:33 -07:00
|
|
|
|
Logger logger = new Logger(true, "datfromdir.log");
|
2016-04-20 20:41:00 -07:00
|
|
|
|
logger.Start();
|
|
|
|
|
|
|
2016-04-11 21:33:55 -07:00
|
|
|
|
// First things first, take care of all of the arguments that this could have
|
2016-05-22 17:38:17 -07:00
|
|
|
|
bool noMD5 = false, noSHA1 = false, forceunpack = false, archivesAsFiles = false, old = false, superDat = false, bare = false, romba = false, enableGzip = false;
|
2016-05-28 15:54:06 -07:00
|
|
|
|
string name = "", desc = "", cat = "", version = "", author = "", tempDir = "";
|
2016-04-11 21:33:55 -07:00
|
|
|
|
List<string> inputs = new List<string>();
|
|
|
|
|
|
foreach (string arg in args)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (arg)
|
|
|
|
|
|
{
|
2016-04-11 23:12:40 -07:00
|
|
|
|
case "-h":
|
|
|
|
|
|
case "-?":
|
|
|
|
|
|
case "--help":
|
2016-04-12 23:24:08 -07:00
|
|
|
|
Build.Help();
|
2016-04-20 20:41:00 -07:00
|
|
|
|
logger.Close();
|
2016-04-11 23:12:40 -07:00
|
|
|
|
return;
|
2016-04-12 23:46:10 -07:00
|
|
|
|
case "-b":
|
|
|
|
|
|
case "--bare":
|
2016-04-21 14:38:11 -07:00
|
|
|
|
bare = true;
|
2016-04-12 23:46:10 -07:00
|
|
|
|
break;
|
2016-04-11 21:33:55 -07:00
|
|
|
|
case "-f":
|
|
|
|
|
|
case "--files":
|
2016-04-20 21:17:23 -07:00
|
|
|
|
archivesAsFiles = true;
|
2016-04-11 21:33:55 -07:00
|
|
|
|
break;
|
2016-05-22 17:38:17 -07:00
|
|
|
|
case "-gz":
|
|
|
|
|
|
case "--gz-files":
|
|
|
|
|
|
enableGzip = true;
|
|
|
|
|
|
break;
|
2016-06-11 15:42:49 -07:00
|
|
|
|
case "-nm":
|
2016-05-22 17:38:17 -07:00
|
|
|
|
case "--noMD5":
|
|
|
|
|
|
noMD5 = true;
|
|
|
|
|
|
break;
|
2016-04-11 21:33:55 -07:00
|
|
|
|
case "-o":
|
|
|
|
|
|
case "--old":
|
2016-04-20 20:41:00 -07:00
|
|
|
|
old = true;
|
2016-04-11 21:33:55 -07:00
|
|
|
|
break;
|
2016-05-22 12:45:20 -07:00
|
|
|
|
case "-ro":
|
|
|
|
|
|
case "--romba":
|
|
|
|
|
|
romba = true;
|
|
|
|
|
|
break;
|
2016-05-22 17:38:17 -07:00
|
|
|
|
case "-s":
|
|
|
|
|
|
case "--noSHA1":
|
|
|
|
|
|
noSHA1 = true;
|
|
|
|
|
|
break;
|
2016-04-17 19:26:19 -07:00
|
|
|
|
case "-sd":
|
|
|
|
|
|
case "--superdat":
|
2016-04-20 20:41:00 -07:00
|
|
|
|
superDat = true;
|
2016-04-17 19:26:19 -07:00
|
|
|
|
break;
|
2016-05-22 17:38:17 -07:00
|
|
|
|
case "-u":
|
|
|
|
|
|
case "--unzip":
|
|
|
|
|
|
forceunpack = true;
|
|
|
|
|
|
break;
|
2016-04-11 21:33:55 -07:00
|
|
|
|
default:
|
|
|
|
|
|
if (arg.StartsWith("-n=") || arg.StartsWith("--name="))
|
|
|
|
|
|
{
|
2016-04-20 20:41:00 -07:00
|
|
|
|
name = arg.Split('=')[1];
|
2016-04-11 21:33:55 -07:00
|
|
|
|
}
|
|
|
|
|
|
else if (arg.StartsWith("-d=") || arg.StartsWith("--desc="))
|
|
|
|
|
|
{
|
2016-04-20 20:41:00 -07:00
|
|
|
|
desc = arg.Split('=')[1];
|
2016-04-11 21:33:55 -07:00
|
|
|
|
}
|
|
|
|
|
|
else if (arg.StartsWith("-c=") || arg.StartsWith("--cat="))
|
|
|
|
|
|
{
|
2016-04-20 20:41:00 -07:00
|
|
|
|
cat = arg.Split('=')[1];
|
2016-04-11 21:33:55 -07:00
|
|
|
|
}
|
2016-04-21 13:32:35 -07:00
|
|
|
|
else if (arg.StartsWith("-au=") || arg.StartsWith("--author="))
|
2016-04-12 11:58:10 -07:00
|
|
|
|
{
|
2016-04-20 20:41:00 -07:00
|
|
|
|
author = arg.Split('=')[1];
|
2016-04-12 11:58:10 -07:00
|
|
|
|
}
|
2016-05-28 15:54:06 -07:00
|
|
|
|
else if (arg.StartsWith("-t=") || arg.StartsWith("--temp="))
|
|
|
|
|
|
{
|
|
|
|
|
|
tempDir = arg.Split('=')[1];
|
|
|
|
|
|
}
|
2016-04-12 11:58:10 -07:00
|
|
|
|
else if (arg.StartsWith("-v=") || arg.StartsWith("--version="))
|
|
|
|
|
|
{
|
2016-04-20 20:41:00 -07:00
|
|
|
|
version = arg.Split('=')[1];
|
2016-04-12 11:58:10 -07:00
|
|
|
|
}
|
2016-04-11 21:33:55 -07:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
inputs.Add(arg);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-04-11 23:12:40 -07:00
|
|
|
|
|
|
|
|
|
|
// If there's no inputs, show the help
|
|
|
|
|
|
if (inputs.Count == 0)
|
|
|
|
|
|
{
|
2016-04-12 23:24:08 -07:00
|
|
|
|
Build.Help();
|
2016-04-20 20:41:00 -07:00
|
|
|
|
logger.Close();
|
2016-04-11 23:12:40 -07:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2016-04-11 21:33:55 -07:00
|
|
|
|
|
2016-04-18 20:04:38 -07:00
|
|
|
|
// Output the title
|
|
|
|
|
|
Build.Start("DATFromDir");
|
|
|
|
|
|
|
2016-04-13 15:00:22 -07:00
|
|
|
|
// If any of the inputs are not valid, show the help
|
|
|
|
|
|
foreach (string input in inputs)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!File.Exists(input) && !Directory.Exists(input))
|
|
|
|
|
|
{
|
2016-04-20 20:41:00 -07:00
|
|
|
|
logger.Error(input + " is not a valid input!");
|
2016-04-13 15:00:22 -07:00
|
|
|
|
Console.WriteLine();
|
|
|
|
|
|
Build.Help();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-04-20 20:41:00 -07:00
|
|
|
|
// Create a new DATFromDir object and process the inputs
|
2016-05-22 12:45:20 -07:00
|
|
|
|
DatData datdata = new DatData
|
|
|
|
|
|
{
|
|
|
|
|
|
Name = name,
|
|
|
|
|
|
Description = desc,
|
|
|
|
|
|
Category = cat,
|
|
|
|
|
|
Version = version,
|
|
|
|
|
|
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
|
|
|
|
|
Author = author,
|
|
|
|
|
|
ForcePacking = (forceunpack ? ForcePacking.Unzip : ForcePacking.None),
|
|
|
|
|
|
OutputFormat = (old ? OutputFormat.ClrMamePro : OutputFormat.Xml),
|
|
|
|
|
|
Romba = romba,
|
|
|
|
|
|
Type = (superDat ? "SuperDAT" : ""),
|
|
|
|
|
|
Roms = new Dictionary<string, List<RomData>>(),
|
|
|
|
|
|
};
|
2016-05-28 15:54:06 -07:00
|
|
|
|
DATFromDir dfd = new DATFromDir(inputs, datdata, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, tempDir, logger);
|
2016-04-20 20:41:00 -07:00
|
|
|
|
bool success = dfd.Start();
|
|
|
|
|
|
|
|
|
|
|
|
// If we failed, show the help
|
|
|
|
|
|
if (!success)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine();
|
|
|
|
|
|
Build.Help();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
logger.Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Process the file, folder, or list of some combination into a DAT file
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>True if the DAT could be created, false otherwise</returns>
|
2016-05-22 20:42:04 -07:00
|
|
|
|
/// <remarks>Try to get the hashing multithreaded (either on a per-hash or per-file level)</remarks>
|
2016-04-20 20:41:00 -07:00
|
|
|
|
public bool Start()
|
|
|
|
|
|
{
|
2016-05-23 15:57:09 -07:00
|
|
|
|
// Double check to see what it needs to be named
|
|
|
|
|
|
_basePath = (_inputs.Count > 0 ? (File.Exists(_inputs[0]) ? _inputs[0] : _inputs[0] + Path.DirectorySeparatorChar) : "");
|
|
|
|
|
|
_basePath = (_basePath != "" ? Path.GetFullPath(_basePath) : "");
|
2016-05-25 11:08:20 -07:00
|
|
|
|
|
|
|
|
|
|
// If the description is defined but not the name, set the name from the description
|
|
|
|
|
|
if (String.IsNullOrEmpty(_datdata.Name) && !String.IsNullOrEmpty(_datdata.Description))
|
|
|
|
|
|
{
|
|
|
|
|
|
_datdata.Name = _datdata.Description;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If the name is defined but not the description, set the description from the name
|
|
|
|
|
|
else if (!String.IsNullOrEmpty(_datdata.Name) && String.IsNullOrEmpty(_datdata.Description))
|
|
|
|
|
|
{
|
|
|
|
|
|
_datdata.Description = _datdata.Name + (_bare ? "" : " (" + _datdata.Date + ")");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If neither the name or description are defined, set them from the automatic values
|
|
|
|
|
|
else if (String.IsNullOrEmpty(_datdata.Name) && String.IsNullOrEmpty(_datdata.Description))
|
2016-05-23 15:57:09 -07:00
|
|
|
|
{
|
|
|
|
|
|
if (_inputs.Count > 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
_datdata.Name = Environment.CurrentDirectory.Split(Path.DirectorySeparatorChar).Last();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_basePath.EndsWith(Path.DirectorySeparatorChar.ToString()))
|
|
|
|
|
|
{
|
|
|
|
|
|
_basePath = _basePath.Substring(0, _basePath.Length - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
_datdata.Name = _basePath.Split(Path.DirectorySeparatorChar).Last();
|
|
|
|
|
|
}
|
2016-05-25 11:08:20 -07:00
|
|
|
|
|
|
|
|
|
|
// If the name is still somehow empty, populate it with defaults
|
|
|
|
|
|
_datdata.Name = (String.IsNullOrEmpty(_datdata.Name) ? "Default" : _datdata.Name);
|
|
|
|
|
|
_datdata.Description = _datdata.Name + (_bare ? "" : " (" + _datdata.Date + ")");
|
2016-05-23 15:57:09 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create and open the output file for writing
|
|
|
|
|
|
FileStream fs = File.Create(Style.CreateOutfileName(Environment.CurrentDirectory, _datdata));
|
|
|
|
|
|
StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
|
|
|
|
|
|
sw.AutoFlush = true;
|
|
|
|
|
|
|
|
|
|
|
|
// Write out the initial file header
|
|
|
|
|
|
Output.WriteHeader(sw, _datdata, _logger);
|
2016-04-11 15:09:50 -07:00
|
|
|
|
|
2016-05-17 10:31:57 -07:00
|
|
|
|
// Loop over each of the found paths, if any
|
2016-05-23 15:57:09 -07:00
|
|
|
|
string lastparent = null;
|
2016-05-17 10:31:57 -07:00
|
|
|
|
foreach (string path in _inputs)
|
2016-04-17 19:26:19 -07:00
|
|
|
|
{
|
2016-05-17 10:31:57 -07:00
|
|
|
|
// Set local paths and vars
|
|
|
|
|
|
_basePath = (File.Exists(path) ? path : path + Path.DirectorySeparatorChar);
|
|
|
|
|
|
_basePath = Path.GetFullPath(_basePath);
|
2016-04-17 19:26:19 -07:00
|
|
|
|
|
2016-05-17 10:31:57 -07:00
|
|
|
|
// This is where the main loop would go
|
|
|
|
|
|
if (File.Exists(_basePath))
|
|
|
|
|
|
{
|
2016-05-25 10:23:42 -07:00
|
|
|
|
lastparent = ProcessFile(_basePath, sw, lastparent);
|
2016-05-17 10:31:57 -07:00
|
|
|
|
}
|
|
|
|
|
|
else if (Directory.Exists(_basePath))
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.Log("Folder found: " + _basePath);
|
2016-04-17 19:26:19 -07:00
|
|
|
|
|
2016-05-17 10:31:57 -07:00
|
|
|
|
// Process the files in the base folder first
|
|
|
|
|
|
foreach (string item in Directory.EnumerateFiles(_basePath, "*", SearchOption.TopDirectoryOnly))
|
2016-04-11 23:12:40 -07:00
|
|
|
|
{
|
2016-05-23 15:57:09 -07:00
|
|
|
|
lastparent = ProcessFile(item, sw, lastparent);
|
2016-04-17 19:26:19 -07:00
|
|
|
|
}
|
2016-05-12 11:23:11 -07:00
|
|
|
|
|
2016-05-17 10:31:57 -07:00
|
|
|
|
// Then process each of the subfolders themselves
|
|
|
|
|
|
string basePathBackup = _basePath;
|
|
|
|
|
|
foreach (string item in Directory.EnumerateDirectories(_basePath))
|
|
|
|
|
|
{
|
2016-05-22 12:45:20 -07:00
|
|
|
|
if (_datdata.Type != "SuperDAT")
|
2016-05-17 18:49:13 -07:00
|
|
|
|
{
|
|
|
|
|
|
_basePath = (File.Exists(item) ? item : item + Path.DirectorySeparatorChar);
|
|
|
|
|
|
_basePath = Path.GetFullPath(_basePath);
|
|
|
|
|
|
}
|
2016-05-19 10:28:53 -07:00
|
|
|
|
|
|
|
|
|
|
bool items = false;
|
2016-05-17 17:21:31 -07:00
|
|
|
|
foreach (string subitem in Directory.EnumerateFiles(item, "*", SearchOption.AllDirectories))
|
2016-05-12 11:23:11 -07:00
|
|
|
|
{
|
2016-05-19 10:28:53 -07:00
|
|
|
|
items = true;
|
2016-05-25 10:23:42 -07:00
|
|
|
|
lastparent = ProcessFile(subitem, sw, lastparent);
|
2016-05-12 11:23:11 -07:00
|
|
|
|
}
|
2016-05-19 10:28:53 -07:00
|
|
|
|
|
2016-06-04 23:07:58 -07:00
|
|
|
|
// In romba mode we ignore empty folders completely
|
|
|
|
|
|
if (!_datdata.Romba)
|
2016-05-19 10:28:53 -07:00
|
|
|
|
{
|
2016-06-04 23:07:58 -07:00
|
|
|
|
// If there were no subitems, add a "blank" game to to the set (if not in Romba mode)
|
|
|
|
|
|
if (!items)
|
2016-05-19 10:28:53 -07:00
|
|
|
|
{
|
2016-06-04 23:07:58 -07:00
|
|
|
|
string actualroot = item.Remove(0, basePathBackup.Length);
|
2016-05-19 10:28:53 -07:00
|
|
|
|
RomData rom = new RomData
|
|
|
|
|
|
{
|
|
|
|
|
|
Name = "null",
|
2016-05-23 15:57:09 -07:00
|
|
|
|
Game = (_datdata.Type == "SuperDAT" ?
|
|
|
|
|
|
_datdata.Name + (actualroot != "" && !actualroot.StartsWith(Path.DirectorySeparatorChar.ToString()) ?
|
|
|
|
|
|
Path.DirectorySeparatorChar.ToString() :
|
|
|
|
|
|
"") + actualroot :
|
|
|
|
|
|
actualroot),
|
2016-05-19 10:28:53 -07:00
|
|
|
|
Size = -1,
|
|
|
|
|
|
CRC = "null",
|
|
|
|
|
|
MD5 = "null",
|
|
|
|
|
|
SHA1 = "null",
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
string key = rom.Size + "-" + rom.CRC;
|
2016-05-22 12:45:20 -07:00
|
|
|
|
if (_datdata.Roms.ContainsKey(key))
|
2016-05-19 10:28:53 -07:00
|
|
|
|
{
|
2016-05-22 12:45:20 -07:00
|
|
|
|
_datdata.Roms[key].Add(rom);
|
2016-05-19 10:28:53 -07:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
List<RomData> temp = new List<RomData>();
|
|
|
|
|
|
temp.Add(rom);
|
2016-05-22 12:45:20 -07:00
|
|
|
|
_datdata.Roms.Add(key, temp);
|
2016-05-19 10:28:53 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-06-04 23:07:58 -07:00
|
|
|
|
|
|
|
|
|
|
// Now scour subdirectories for empties and add those as well (if not in Romba mode)
|
|
|
|
|
|
foreach (string subdir in Directory.EnumerateDirectories(item, "*", SearchOption.AllDirectories))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Directory.EnumerateFiles(subdir, "*", SearchOption.AllDirectories).Count() == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
string actualroot = subdir.Remove(0, basePathBackup.Length);
|
|
|
|
|
|
RomData rom = new RomData
|
|
|
|
|
|
{
|
|
|
|
|
|
Name = "null",
|
|
|
|
|
|
Game = (_datdata.Type == "SuperDAT" ?
|
|
|
|
|
|
_datdata.Name + (actualroot != "" && !actualroot.StartsWith(Path.DirectorySeparatorChar.ToString()) ?
|
|
|
|
|
|
Path.DirectorySeparatorChar.ToString() :
|
|
|
|
|
|
"") + actualroot :
|
|
|
|
|
|
actualroot),
|
|
|
|
|
|
Size = -1,
|
|
|
|
|
|
CRC = "null",
|
|
|
|
|
|
MD5 = "null",
|
|
|
|
|
|
SHA1 = "null",
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
string key = rom.Size + "-" + rom.CRC;
|
|
|
|
|
|
if (_datdata.Roms.ContainsKey(key))
|
|
|
|
|
|
{
|
|
|
|
|
|
_datdata.Roms[key].Add(rom);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
List<RomData> temp = new List<RomData>();
|
|
|
|
|
|
temp.Add(rom);
|
|
|
|
|
|
_datdata.Roms.Add(key, temp);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-05-19 10:28:53 -07:00
|
|
|
|
}
|
2016-04-11 23:12:40 -07:00
|
|
|
|
}
|
2016-05-17 10:31:57 -07:00
|
|
|
|
_basePath = basePathBackup;
|
|
|
|
|
|
}
|
|
|
|
|
|
// If this somehow skips past the original sensors
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.Error(path + " is not a valid input!");
|
2016-04-13 14:32:36 -07:00
|
|
|
|
}
|
2016-04-11 15:09:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-01 11:02:52 -07:00
|
|
|
|
// Now output any empties to the stream (if not in Romba mode)
|
|
|
|
|
|
if (!_datdata.Romba)
|
2016-04-13 00:44:55 -07:00
|
|
|
|
{
|
2016-06-01 11:02:52 -07:00
|
|
|
|
foreach (List<RomData> roms in _datdata.Roms.Values)
|
2016-04-13 00:44:55 -07:00
|
|
|
|
{
|
2016-06-01 11:02:52 -07:00
|
|
|
|
for (int i = 0; i < roms.Count; i++)
|
2016-04-13 00:44:55 -07:00
|
|
|
|
{
|
2016-06-01 11:02:52 -07:00
|
|
|
|
RomData rom = roms[i];
|
2016-05-17 10:31:57 -07:00
|
|
|
|
|
2016-06-01 11:02:52 -07:00
|
|
|
|
// If we're in a mode that doesn't allow for actual empty folders, add the blank info
|
|
|
|
|
|
if (_datdata.OutputFormat != OutputFormat.SabreDat && _datdata.OutputFormat != OutputFormat.MissFile)
|
|
|
|
|
|
{
|
|
|
|
|
|
rom.Type = "rom";
|
|
|
|
|
|
rom.Name = "-";
|
|
|
|
|
|
rom.Size = Constants.SizeZero;
|
|
|
|
|
|
rom.CRC = Constants.CRCZero;
|
|
|
|
|
|
rom.MD5 = Constants.MD5Zero;
|
|
|
|
|
|
rom.SHA1 = Constants.SHA1Zero;
|
|
|
|
|
|
}
|
2016-05-17 10:31:57 -07:00
|
|
|
|
|
2016-06-01 11:02:52 -07:00
|
|
|
|
// If we have a different game and we're not at the start of the list, output the end of last item
|
|
|
|
|
|
int last = 0;
|
|
|
|
|
|
if (lastparent != null && lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
|
|
|
|
|
|
{
|
|
|
|
|
|
Output.WriteEndGame(sw, rom, new List<string>(), new List<string>(), lastparent, _datdata, 0, out last, _logger);
|
|
|
|
|
|
}
|
2016-05-17 10:31:57 -07:00
|
|
|
|
|
2016-06-01 11:02:52 -07:00
|
|
|
|
// If we have a new game, output the beginning of the new item
|
|
|
|
|
|
if (lastparent == null || lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
|
|
|
|
|
|
{
|
|
|
|
|
|
Output.WriteStartGame(sw, rom, new List<string>(), lastparent, _datdata, 0, last, _logger);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Write out the rom data
|
|
|
|
|
|
if (_datdata.OutputFormat != OutputFormat.SabreDat && _datdata.OutputFormat != OutputFormat.MissFile)
|
|
|
|
|
|
{
|
|
|
|
|
|
Output.WriteRomData(sw, rom, lastparent, _datdata, 0, _logger);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
lastparent = rom.Game;
|
2016-05-23 15:57:09 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-05-16 21:52:49 -07:00
|
|
|
|
|
2016-06-01 11:02:52 -07:00
|
|
|
|
// If we had roms but not blanks (and not in Romba mode), create an artifical rom for the purposes of outputting
|
|
|
|
|
|
if (lastparent != null && _datdata.Roms.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
_datdata.Roms.Add("temp", new List<RomData>());
|
|
|
|
|
|
}
|
2016-05-25 11:59:08 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-05-23 15:57:09 -07:00
|
|
|
|
// Now write the final piece and close the output stream
|
|
|
|
|
|
Output.WriteFooter(sw, _datdata, 0, _logger);
|
|
|
|
|
|
sw.Close();
|
2016-04-20 20:41:00 -07:00
|
|
|
|
|
|
|
|
|
|
return true;
|
2016-04-11 23:12:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-04-11 23:49:06 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Check a given file for hashes, based on current settings
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="item">Filename of the item to be checked</param>
|
2016-05-23 15:57:09 -07:00
|
|
|
|
/// <param name="sw">StreamWriter representing the output file</param>
|
2016-05-25 11:45:34 -07:00
|
|
|
|
/// <param name="lastparent">Name of the last parent rom to make sure that everything is grouped as well as possible</param>
|
|
|
|
|
|
/// <returns>New parent to be used</returns>
|
|
|
|
|
|
private string ProcessFile(string item, StreamWriter sw, string lastparent)
|
2016-04-11 20:41:04 -07:00
|
|
|
|
{
|
2016-05-31 23:34:19 -07:00
|
|
|
|
// Define the temporary directory
|
|
|
|
|
|
string tempdir = (String.IsNullOrEmpty(_tempDir) ? Environment.CurrentDirectory : _tempDir);
|
|
|
|
|
|
tempdir += (tempdir.EndsWith(Path.DirectorySeparatorChar.ToString()) ? "" : Path.DirectorySeparatorChar.ToString());
|
|
|
|
|
|
tempdir += "temp" + DateTime.Now.ToString("yyyyMMddHHmmss") + Path.DirectorySeparatorChar;
|
2016-05-28 15:54:06 -07:00
|
|
|
|
|
2016-05-22 17:41:52 -07:00
|
|
|
|
// Special case for if we are in Romba mode (all names are supposed to be SHA-1 hashes)
|
2016-05-22 17:38:17 -07:00
|
|
|
|
if (_datdata.Romba)
|
|
|
|
|
|
{
|
2016-05-31 23:34:19 -07:00
|
|
|
|
string datum = Path.GetFileName(item).ToLowerInvariant();
|
|
|
|
|
|
long filesize = new FileInfo(item).Length;
|
2016-05-22 17:38:17 -07:00
|
|
|
|
|
2016-05-22 17:41:52 -07:00
|
|
|
|
// Check if the name is the right length
|
2016-05-31 23:34:19 -07:00
|
|
|
|
if (!Regex.IsMatch(datum, @"^[0-9a-f]{40}\.gz"))
|
2016-05-22 17:41:52 -07:00
|
|
|
|
{
|
|
|
|
|
|
_logger.Warning("Non SHA-1 filename found, skipping: '" + datum + "'");
|
2016-05-23 15:57:09 -07:00
|
|
|
|
return "";
|
2016-05-22 17:41:52 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-05-31 23:34:19 -07:00
|
|
|
|
// Check if the file is at least the minimum length
|
2016-06-01 22:49:02 -07:00
|
|
|
|
if (filesize < 32 /* bytes */)
|
2016-05-31 23:34:19 -07:00
|
|
|
|
{
|
|
|
|
|
|
_logger.Warning("Possibly corrupt file '" + item + "' with size " + Style.GetBytesReadable(filesize));
|
|
|
|
|
|
return "";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Get the Romba-specific header data
|
|
|
|
|
|
byte[] header;
|
|
|
|
|
|
byte[] footer;
|
|
|
|
|
|
using (FileStream itemstream = File.OpenRead(item))
|
|
|
|
|
|
{
|
|
|
|
|
|
using (BinaryReader br = new BinaryReader(itemstream))
|
|
|
|
|
|
{
|
2016-06-01 22:49:02 -07:00
|
|
|
|
header = br.ReadBytes(32);
|
2016-05-31 23:34:19 -07:00
|
|
|
|
br.BaseStream.Seek(-4, SeekOrigin.End);
|
|
|
|
|
|
footer = br.ReadBytes(4);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Now convert the data and get the right positions
|
|
|
|
|
|
string headerstring = BitConverter.ToString(header).Replace("-", string.Empty);
|
|
|
|
|
|
string gzmd5 = headerstring.Substring(24, 32);
|
|
|
|
|
|
string gzcrc = headerstring.Substring(56, 8);
|
|
|
|
|
|
string gzsize = BitConverter.ToString(footer.Reverse().ToArray()).Replace("-", string.Empty);
|
|
|
|
|
|
long extractedsize = Convert.ToInt64(gzsize, 16);
|
|
|
|
|
|
|
2016-06-01 14:32:16 -07:00
|
|
|
|
// Only try to add if the file size is greater than 750 MiB
|
|
|
|
|
|
if (filesize >= (750 * Constants.MibiByte))
|
2016-05-31 23:34:19 -07:00
|
|
|
|
{
|
2016-06-01 22:49:02 -07:00
|
|
|
|
// ISIZE is mod 4GiB, so we add that if the ISIZE is smaller than the filesize and greater than 1% different
|
2016-06-01 14:31:42 -07:00
|
|
|
|
bool shouldfollowup = false;
|
2016-06-01 22:49:02 -07:00
|
|
|
|
if (extractedsize < filesize && (100 * extractedsize / filesize) < 99 /* percent */)
|
2016-05-31 23:34:19 -07:00
|
|
|
|
{
|
2016-06-01 14:47:24 -07:00
|
|
|
|
_logger.Log("mancalc - Filename: '" + Path.GetFullPath(item) + "'\nExtracted file size: " +
|
2016-05-31 23:34:19 -07:00
|
|
|
|
extractedsize + ", " + Style.GetBytesReadable(extractedsize) + "\nArchive file size: " + filesize + ", " + Style.GetBytesReadable(filesize));
|
|
|
|
|
|
}
|
2016-06-01 22:49:02 -07:00
|
|
|
|
while (extractedsize < filesize && (100 * extractedsize / filesize) < 99 /* percent */)
|
2016-05-31 23:34:19 -07:00
|
|
|
|
{
|
2016-06-01 11:33:08 -07:00
|
|
|
|
extractedsize += (4 * Constants.GibiByte);
|
2016-06-01 14:31:42 -07:00
|
|
|
|
shouldfollowup = true;
|
2016-05-31 23:34:19 -07:00
|
|
|
|
}
|
2016-06-01 14:31:42 -07:00
|
|
|
|
if (shouldfollowup)
|
|
|
|
|
|
{
|
2016-06-01 14:48:02 -07:00
|
|
|
|
_logger.Log("Filename: '" + Path.GetFullPath(item) + "'\nFinal file size: " + extractedsize + ", " + Style.GetBytesReadable(extractedsize) +
|
2016-06-01 14:14:56 -07:00
|
|
|
|
"\nExtracted CRC: " + gzcrc + "\nExtracted MD5: " + gzmd5 + "\nSHA-1: " + Path.GetFileNameWithoutExtension(item));
|
2016-06-01 14:31:42 -07:00
|
|
|
|
}
|
2016-05-31 23:34:19 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-05-22 17:38:17 -07:00
|
|
|
|
RomData rom = new RomData
|
|
|
|
|
|
{
|
|
|
|
|
|
Type = "rom",
|
2016-05-31 23:34:19 -07:00
|
|
|
|
Game = Path.GetFileNameWithoutExtension(item),
|
|
|
|
|
|
Name = Path.GetFileNameWithoutExtension(item),
|
|
|
|
|
|
Size = extractedsize,
|
|
|
|
|
|
CRC = gzcrc,
|
|
|
|
|
|
MD5 = gzmd5,
|
2016-05-22 17:38:17 -07:00
|
|
|
|
SHA1 = Path.GetFileNameWithoutExtension(item),
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2016-05-23 15:57:09 -07:00
|
|
|
|
int last = 0;
|
|
|
|
|
|
Output.WriteStartGame(sw, rom, new List<string>(), "", _datdata, 0, 0, _logger);
|
|
|
|
|
|
Output.WriteRomData(sw, rom, "", _datdata, 0, _logger);
|
|
|
|
|
|
Output.WriteEndGame(sw, rom, new List<string>(), new List<string>(), "", _datdata, 0, out last, _logger);
|
2016-05-22 17:38:17 -07:00
|
|
|
|
|
2016-05-31 23:34:19 -07:00
|
|
|
|
_logger.User("File added: " + Path.GetFileNameWithoutExtension(item) + Environment.NewLine);
|
2016-06-01 10:49:57 -07:00
|
|
|
|
return rom.Game;
|
2016-05-22 17:38:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-05-17 16:53:02 -07:00
|
|
|
|
// Create the temporary output directory
|
2016-04-11 23:12:40 -07:00
|
|
|
|
bool encounteredErrors = true;
|
2016-04-20 20:41:00 -07:00
|
|
|
|
if (!_archivesAsFiles)
|
2016-04-11 23:12:40 -07:00
|
|
|
|
{
|
2016-05-22 23:33:33 -07:00
|
|
|
|
IArchive archive = null;
|
2016-04-12 23:07:23 -07:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2016-05-22 23:33:33 -07:00
|
|
|
|
archive = ArchiveFactory.Open(item);
|
2016-04-13 13:35:50 -07:00
|
|
|
|
ArchiveType at = archive.Type;
|
|
|
|
|
|
_logger.Log("Found archive of type: " + at);
|
|
|
|
|
|
|
2016-05-22 23:33:33 -07:00
|
|
|
|
if (at == ArchiveType.Zip || at == ArchiveType.SevenZip || at == ArchiveType.Rar)
|
2016-04-13 13:35:50 -07:00
|
|
|
|
{
|
2016-05-28 15:54:06 -07:00
|
|
|
|
// Create the temp directory
|
|
|
|
|
|
DirectoryInfo di = Directory.CreateDirectory(tempdir);
|
|
|
|
|
|
|
|
|
|
|
|
// Extract all files to the temp directory
|
2016-04-13 13:35:50 -07:00
|
|
|
|
IReader reader = archive.ExtractAllEntries();
|
2016-05-28 15:54:06 -07:00
|
|
|
|
reader.WriteAllToDirectory(tempdir, ExtractOptions.ExtractFullPath);
|
2016-04-13 13:35:50 -07:00
|
|
|
|
encounteredErrors = false;
|
|
|
|
|
|
}
|
2016-05-22 23:33:33 -07:00
|
|
|
|
else if (at == ArchiveType.GZip && _enableGzip)
|
|
|
|
|
|
{
|
2016-05-28 15:54:06 -07:00
|
|
|
|
// Close the original archive handle
|
2016-05-22 23:33:33 -07:00
|
|
|
|
archive.Dispose();
|
2016-05-28 15:54:06 -07:00
|
|
|
|
|
|
|
|
|
|
// Create the temp directory
|
|
|
|
|
|
DirectoryInfo di = Directory.CreateDirectory(tempdir);
|
2016-05-22 23:33:33 -07:00
|
|
|
|
|
|
|
|
|
|
using (FileStream itemstream = File.OpenRead(item))
|
|
|
|
|
|
{
|
2016-05-28 15:54:06 -07:00
|
|
|
|
using (FileStream outstream = File.Create(tempdir + Path.GetFileNameWithoutExtension(item)))
|
2016-05-22 23:33:33 -07:00
|
|
|
|
{
|
|
|
|
|
|
using (GZipStream gz = new GZipStream(itemstream, CompressionMode.Decompress))
|
|
|
|
|
|
{
|
|
|
|
|
|
gz.CopyTo(outstream);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
encounteredErrors = false;
|
|
|
|
|
|
}
|
2016-04-18 13:10:07 -07:00
|
|
|
|
archive.Dispose();
|
2016-04-12 23:07:23 -07:00
|
|
|
|
}
|
|
|
|
|
|
catch (InvalidOperationException)
|
|
|
|
|
|
{
|
|
|
|
|
|
encounteredErrors = true;
|
2016-05-23 12:11:22 -07:00
|
|
|
|
if (archive != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
archive.Dispose();
|
|
|
|
|
|
}
|
2016-04-12 23:07:23 -07:00
|
|
|
|
}
|
2016-04-12 23:39:22 -07:00
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.Error(ex.ToString());
|
2016-04-12 23:49:51 -07:00
|
|
|
|
encounteredErrors = true;
|
2016-05-23 12:11:22 -07:00
|
|
|
|
if (archive != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
archive.Dispose();
|
|
|
|
|
|
}
|
2016-04-12 23:39:22 -07:00
|
|
|
|
}
|
2016-04-11 23:12:40 -07:00
|
|
|
|
}
|
2016-04-11 20:41:04 -07:00
|
|
|
|
|
|
|
|
|
|
// Get a list of files including size and hashes
|
|
|
|
|
|
Crc32 crc = new Crc32();
|
|
|
|
|
|
MD5 md5 = MD5.Create();
|
|
|
|
|
|
SHA1 sha1 = SHA1.Create();
|
|
|
|
|
|
|
|
|
|
|
|
// If the file was an archive and was extracted successfully, check it
|
|
|
|
|
|
if (!encounteredErrors)
|
|
|
|
|
|
{
|
2016-05-23 15:57:09 -07:00
|
|
|
|
int last = 0;
|
|
|
|
|
|
|
2016-04-12 23:39:22 -07:00
|
|
|
|
_logger.Log(Path.GetFileName(item) + " treated like an archive");
|
2016-05-28 15:54:06 -07:00
|
|
|
|
foreach (string entry in Directory.EnumerateFiles(tempdir, "*", SearchOption.AllDirectories))
|
2016-04-11 20:41:04 -07:00
|
|
|
|
{
|
2016-05-10 15:41:33 -07:00
|
|
|
|
_logger.Log("Found file: " + entry);
|
2016-05-28 15:54:06 -07:00
|
|
|
|
string fileCRC = string.Empty;
|
|
|
|
|
|
string fileMD5 = string.Empty;
|
|
|
|
|
|
string fileSHA1 = string.Empty;
|
2016-04-11 20:41:04 -07:00
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
using (FileStream fs = File.Open(entry, FileMode.Open))
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (byte b in crc.ComputeHash(fs))
|
|
|
|
|
|
{
|
|
|
|
|
|
fileCRC += b.ToString("x2").ToLower();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-04-11 23:12:40 -07:00
|
|
|
|
if (!_noMD5)
|
2016-04-11 20:41:04 -07:00
|
|
|
|
{
|
2016-04-11 23:12:40 -07:00
|
|
|
|
using (FileStream fs = File.Open(entry, FileMode.Open))
|
|
|
|
|
|
{
|
|
|
|
|
|
fileMD5 = BitConverter.ToString(md5.ComputeHash(fs)).Replace("-", "");
|
|
|
|
|
|
}
|
2016-04-11 20:41:04 -07:00
|
|
|
|
}
|
2016-04-11 23:12:40 -07:00
|
|
|
|
if (!_noSHA1)
|
2016-04-11 20:41:04 -07:00
|
|
|
|
{
|
2016-04-11 23:12:40 -07:00
|
|
|
|
using (FileStream fs = File.Open(entry, FileMode.Open))
|
|
|
|
|
|
{
|
|
|
|
|
|
fileSHA1 = BitConverter.ToString(sha1.ComputeHash(fs)).Replace("-", "");
|
|
|
|
|
|
}
|
2016-04-11 20:41:04 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (IOException)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-05-17 17:30:41 -07:00
|
|
|
|
string actualroot = "";
|
|
|
|
|
|
string actualitem = "";
|
|
|
|
|
|
|
2016-05-28 15:54:06 -07:00
|
|
|
|
actualitem = entry.Remove(0, tempdir.Length);
|
2016-05-17 17:21:31 -07:00
|
|
|
|
|
|
|
|
|
|
// If we're in SuperDAT mode, make sure the added item is by itself
|
2016-05-22 12:45:20 -07:00
|
|
|
|
if (_datdata.Type == "SuperDAT")
|
2016-05-17 17:21:31 -07:00
|
|
|
|
{
|
2016-05-17 18:49:13 -07:00
|
|
|
|
actualroot = Path.GetDirectoryName(item.Remove(0, _basePath.Length));
|
2016-05-17 17:30:41 -07:00
|
|
|
|
actualroot = (actualroot == "" ? _basePath.Split(Path.DirectorySeparatorChar).Last() : actualroot);
|
|
|
|
|
|
actualroot += Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(item) + Path.DirectorySeparatorChar + Path.GetDirectoryName(actualitem);
|
2016-05-17 17:21:31 -07:00
|
|
|
|
actualroot = actualroot.TrimEnd(Path.DirectorySeparatorChar);
|
|
|
|
|
|
actualitem = Path.GetFileName(actualitem);
|
|
|
|
|
|
}
|
2016-05-17 17:30:41 -07:00
|
|
|
|
// Otherwise, set the correct root and such
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
actualroot = Path.GetFileNameWithoutExtension(item);
|
|
|
|
|
|
actualroot = actualroot.TrimEnd(Path.DirectorySeparatorChar);
|
|
|
|
|
|
}
|
2016-05-17 17:21:31 -07:00
|
|
|
|
|
2016-05-16 21:52:49 -07:00
|
|
|
|
RomData rom = new RomData
|
2016-04-11 23:59:32 -07:00
|
|
|
|
{
|
2016-04-18 14:05:34 -07:00
|
|
|
|
Type = "rom",
|
2016-05-23 15:57:09 -07:00
|
|
|
|
Game = (_datdata.Type == "SuperDAT" ?
|
|
|
|
|
|
_datdata.Name + (actualroot != "" && !actualroot.StartsWith(Path.DirectorySeparatorChar.ToString()) ?
|
|
|
|
|
|
Path.DirectorySeparatorChar.ToString() :
|
|
|
|
|
|
"") + actualroot :
|
|
|
|
|
|
actualroot),
|
2016-05-17 18:49:13 -07:00
|
|
|
|
Name = actualitem,
|
2016-04-11 23:59:32 -07:00
|
|
|
|
Size = (new FileInfo(entry)).Length,
|
|
|
|
|
|
CRC = fileCRC,
|
|
|
|
|
|
MD5 = fileMD5,
|
|
|
|
|
|
SHA1 = fileSHA1,
|
2016-05-16 21:52:49 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2016-05-23 15:57:09 -07:00
|
|
|
|
// If we have a different game and we're not at the start of the list, output the end of last item
|
2016-05-25 11:43:44 -07:00
|
|
|
|
if (lastparent != null && lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
|
2016-05-16 21:52:49 -07:00
|
|
|
|
{
|
2016-05-25 11:43:44 -07:00
|
|
|
|
Output.WriteEndGame(sw, rom, new List<string>(), new List<string>(), lastparent, _datdata, 0, out last, _logger);
|
2016-05-16 21:52:49 -07:00
|
|
|
|
}
|
2016-05-23 15:57:09 -07:00
|
|
|
|
// If we have a different game and we're not at the start of the list, output the end of the last item
|
|
|
|
|
|
else if (lastparent != null && lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
|
|
|
|
|
|
{
|
|
|
|
|
|
Output.WriteEndGame(sw, rom, new List<string>(), new List<string>(), lastparent, _datdata, 0, out last, _logger);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If we have a new game, output the beginning of the new item
|
2016-05-25 11:43:44 -07:00
|
|
|
|
if (lastparent == null || lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
|
2016-05-16 21:52:49 -07:00
|
|
|
|
{
|
2016-05-25 11:43:44 -07:00
|
|
|
|
Output.WriteStartGame(sw, rom, new List<string>(), lastparent, _datdata, 0, last, _logger);
|
2016-05-16 21:52:49 -07:00
|
|
|
|
}
|
2016-04-11 20:41:04 -07:00
|
|
|
|
|
2016-05-23 15:57:09 -07:00
|
|
|
|
// Write out the rom data
|
2016-05-25 11:43:44 -07:00
|
|
|
|
Output.WriteRomData(sw, rom, lastparent, _datdata, 0, _logger);
|
2016-05-10 15:41:33 -07:00
|
|
|
|
_logger.User("File added: " + entry + Environment.NewLine);
|
2016-05-23 15:57:09 -07:00
|
|
|
|
|
2016-05-25 11:43:44 -07:00
|
|
|
|
lastparent = rom.Game;
|
2016-04-11 20:41:04 -07:00
|
|
|
|
}
|
2016-05-17 16:53:02 -07:00
|
|
|
|
|
|
|
|
|
|
// Delete the temp directory
|
2016-05-28 15:54:06 -07:00
|
|
|
|
if (Directory.Exists(tempdir))
|
2016-05-17 16:53:02 -07:00
|
|
|
|
{
|
2016-05-28 15:54:06 -07:00
|
|
|
|
Directory.Delete(tempdir, true);
|
2016-05-17 16:53:02 -07:00
|
|
|
|
}
|
2016-04-11 20:41:04 -07:00
|
|
|
|
}
|
|
|
|
|
|
// Otherwise, just get the info on the file itself
|
|
|
|
|
|
else if (!Directory.Exists(item) && File.Exists(item))
|
|
|
|
|
|
{
|
2016-04-12 23:39:22 -07:00
|
|
|
|
_logger.Log(Path.GetFileName(item) + " treated like a file");
|
2016-04-12 20:34:38 -07:00
|
|
|
|
|
2016-04-11 20:41:04 -07:00
|
|
|
|
string fileCRC = String.Empty;
|
|
|
|
|
|
string fileMD5 = String.Empty;
|
|
|
|
|
|
string fileSHA1 = String.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
using (FileStream fs = File.Open(item, FileMode.Open))
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (byte b in crc.ComputeHash(fs))
|
|
|
|
|
|
{
|
|
|
|
|
|
fileCRC += b.ToString("x2").ToLower();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-04-11 23:12:40 -07:00
|
|
|
|
if (!_noMD5)
|
2016-04-11 20:41:04 -07:00
|
|
|
|
{
|
2016-04-11 23:12:40 -07:00
|
|
|
|
using (FileStream fs = File.Open(item, FileMode.Open))
|
|
|
|
|
|
{
|
|
|
|
|
|
fileMD5 = BitConverter.ToString(md5.ComputeHash(fs)).Replace("-", "");
|
|
|
|
|
|
}
|
2016-04-11 20:41:04 -07:00
|
|
|
|
}
|
2016-04-11 23:12:40 -07:00
|
|
|
|
if (!_noSHA1)
|
2016-04-11 20:41:04 -07:00
|
|
|
|
{
|
2016-04-11 23:12:40 -07:00
|
|
|
|
using (FileStream fs = File.Open(item, FileMode.Open))
|
|
|
|
|
|
{
|
|
|
|
|
|
fileSHA1 = BitConverter.ToString(sha1.ComputeHash(fs)).Replace("-", "");
|
|
|
|
|
|
}
|
2016-04-11 20:41:04 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-04-13 00:44:55 -07:00
|
|
|
|
if (_basePath.EndsWith(Path.DirectorySeparatorChar.ToString()))
|
|
|
|
|
|
{
|
|
|
|
|
|
_basePath = _basePath.Substring(0, _basePath.Length - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string actualroot = (item == _basePath ? item.Split(Path.DirectorySeparatorChar).Last() : item.Remove(0, _basePath.Length).Split(Path.DirectorySeparatorChar)[0]);
|
2016-05-22 12:45:20 -07:00
|
|
|
|
actualroot = (actualroot == "" && _datdata.Type != "SuperDAT" ? _basePath.Split(Path.DirectorySeparatorChar).Last() : actualroot);
|
2016-05-17 17:21:31 -07:00
|
|
|
|
string actualitem = (item == _basePath ? item : item.Remove(0, _basePath.Length + 1));
|
|
|
|
|
|
|
|
|
|
|
|
// If we're in SuperDAT mode, make sure the added item is by itself
|
2016-05-22 12:45:20 -07:00
|
|
|
|
if (_datdata.Type == "SuperDAT")
|
2016-05-17 17:21:31 -07:00
|
|
|
|
{
|
2016-05-17 18:49:13 -07:00
|
|
|
|
actualroot += (actualroot != "" ? Path.DirectorySeparatorChar.ToString() : "") + Path.GetDirectoryName(actualitem);
|
2016-05-17 17:21:31 -07:00
|
|
|
|
actualroot = actualroot.TrimEnd(Path.DirectorySeparatorChar);
|
|
|
|
|
|
actualitem = Path.GetFileName(actualitem);
|
|
|
|
|
|
}
|
2016-04-11 20:41:04 -07:00
|
|
|
|
|
2016-04-12 00:18:55 -07:00
|
|
|
|
// Drag and drop is funny
|
|
|
|
|
|
if (actualitem == Path.GetFullPath(actualitem))
|
|
|
|
|
|
{
|
|
|
|
|
|
actualitem = Path.GetFileName(actualitem);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-04-18 13:10:07 -07:00
|
|
|
|
_logger.Log("Actual item added: " + actualitem);
|
|
|
|
|
|
|
2016-05-16 21:52:49 -07:00
|
|
|
|
RomData rom = new RomData
|
2016-04-11 23:59:32 -07:00
|
|
|
|
{
|
2016-04-18 14:05:34 -07:00
|
|
|
|
Type = "rom",
|
2016-05-23 15:57:09 -07:00
|
|
|
|
Game = (_datdata.Type == "SuperDAT" ?
|
|
|
|
|
|
_datdata.Name + (actualroot != "" && !actualroot.StartsWith(Path.DirectorySeparatorChar.ToString()) ?
|
|
|
|
|
|
Path.DirectorySeparatorChar.ToString() :
|
|
|
|
|
|
"") + actualroot :
|
|
|
|
|
|
actualroot),
|
2016-04-11 23:59:32 -07:00
|
|
|
|
Name = actualitem,
|
|
|
|
|
|
Size = (new FileInfo(item)).Length,
|
|
|
|
|
|
CRC = fileCRC,
|
|
|
|
|
|
MD5 = fileMD5,
|
|
|
|
|
|
SHA1 = fileSHA1,
|
2016-05-16 21:52:49 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2016-05-23 15:57:09 -07:00
|
|
|
|
// If we have a different game and we're not at the start of the list, output the end of last item
|
|
|
|
|
|
int last = 0;
|
|
|
|
|
|
if (lastparent != null && lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
|
2016-05-16 21:52:49 -07:00
|
|
|
|
{
|
2016-05-23 15:57:09 -07:00
|
|
|
|
Output.WriteEndGame(sw, rom, new List<string>(), new List<string>(), lastparent, _datdata, 0, out last, _logger);
|
2016-05-16 21:52:49 -07:00
|
|
|
|
}
|
2016-05-23 15:57:09 -07:00
|
|
|
|
|
|
|
|
|
|
// If we have a new game, output the beginning of the new item
|
|
|
|
|
|
if (lastparent == null || lastparent.ToLowerInvariant() != rom.Game.ToLowerInvariant())
|
2016-05-16 21:52:49 -07:00
|
|
|
|
{
|
2016-05-23 15:57:09 -07:00
|
|
|
|
Output.WriteStartGame(sw, rom, new List<string>(), lastparent, _datdata, 0, last, _logger);
|
2016-05-16 21:52:49 -07:00
|
|
|
|
}
|
2016-04-11 20:41:04 -07:00
|
|
|
|
|
2016-05-23 15:57:09 -07:00
|
|
|
|
// Write out the rom data
|
|
|
|
|
|
Output.WriteRomData(sw, rom, lastparent, _datdata, 0, _logger);
|
2016-05-10 15:41:33 -07:00
|
|
|
|
_logger.User("File added: " + actualitem + Environment.NewLine);
|
2016-05-23 15:57:09 -07:00
|
|
|
|
|
|
|
|
|
|
return rom.Game;
|
2016-04-11 20:41:04 -07:00
|
|
|
|
}
|
2016-04-18 13:10:07 -07:00
|
|
|
|
catch (IOException ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.Error(ex.ToString());
|
2016-05-23 15:57:09 -07:00
|
|
|
|
return null;
|
2016-04-18 13:10:07 -07:00
|
|
|
|
}
|
2016-04-11 20:41:04 -07:00
|
|
|
|
}
|
2016-05-25 11:43:44 -07:00
|
|
|
|
return lastparent;
|
2016-04-11 20:41:04 -07:00
|
|
|
|
}
|
2016-04-11 15:09:50 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|