mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
[RomTools] Create another helper class
This commit is contained in:
@@ -95,6 +95,7 @@
|
||||
<Compile Include="Remapping.cs" />
|
||||
<Compile Include="Tools\DatTools.cs" />
|
||||
<Compile Include="Data\Structs.cs" />
|
||||
<Compile Include="Tools\RomTools.cs" />
|
||||
<Compile Include="Tools\Stats.cs" />
|
||||
<Compile Include="Tools\Style.cs" />
|
||||
<Compile Include="Data\Build.cs" />
|
||||
|
||||
@@ -2,12 +2,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
|
||||
using DamienG.Security.Cryptography;
|
||||
|
||||
namespace SabreTools.Helper
|
||||
{
|
||||
public class DatTools
|
||||
@@ -170,7 +167,7 @@ namespace SabreTools.Helper
|
||||
else if ((line.Trim().StartsWith("rom (") || line.Trim().StartsWith("disk (")) && block)
|
||||
{
|
||||
// If we're in cleaning mode, sanitize the game name
|
||||
gamename = (clean ? CleanGameName(gamename) : gamename);
|
||||
gamename = (clean ? Style.CleanGameName(gamename) : gamename);
|
||||
|
||||
RomData rom = new RomData
|
||||
{
|
||||
@@ -569,7 +566,7 @@ namespace SabreTools.Helper
|
||||
string[] rominfo = line.Split('¬');
|
||||
|
||||
// If we're in cleaning mode, sanitize the game name
|
||||
rominfo[3] = (clean ? CleanGameName(rominfo[3]) : rominfo[3]);
|
||||
rominfo[3] = (clean ? Style.CleanGameName(rominfo[3]) : rominfo[3]);
|
||||
|
||||
RomData rom = new RomData
|
||||
{
|
||||
@@ -700,7 +697,7 @@ namespace SabreTools.Helper
|
||||
string tempgame = String.Join("\\", parent);
|
||||
|
||||
// If we're in cleaning mode, sanitize the game name
|
||||
tempgame = (clean ? CleanGameName(tempgame) : tempgame);
|
||||
tempgame = (clean ? Style.CleanGameName(tempgame) : tempgame);
|
||||
|
||||
RomData rom = new RomData
|
||||
{
|
||||
@@ -1128,7 +1125,7 @@ namespace SabreTools.Helper
|
||||
// If we're in clean mode, sanitize the game name
|
||||
if (clean)
|
||||
{
|
||||
tempname = CleanGameName(tempname.Split(Path.DirectorySeparatorChar));
|
||||
tempname = Style.CleanGameName(tempname.Split(Path.DirectorySeparatorChar));
|
||||
}
|
||||
|
||||
// Only add the rom if there's useful information in it
|
||||
@@ -1195,7 +1192,7 @@ namespace SabreTools.Helper
|
||||
tempname = (parent.Count > 0 ? String.Join("\\", parent) + Path.DirectorySeparatorChar : "") + tempname;
|
||||
|
||||
// If we're in cleaning mode, sanitize the game name
|
||||
tempname = (clean ? CleanGameName(tempname.Split(Path.DirectorySeparatorChar)) : tempname);
|
||||
tempname = (clean ? Style.CleanGameName(tempname.Split(Path.DirectorySeparatorChar)) : tempname);
|
||||
|
||||
RomData rom = new RomData
|
||||
{
|
||||
@@ -1366,7 +1363,7 @@ namespace SabreTools.Helper
|
||||
}
|
||||
|
||||
// If we're in cleaning mode, sanitize the game name
|
||||
tempname = (clean ? CleanGameName(tempname) : tempname);
|
||||
tempname = (clean ? Style.CleanGameName(tempname) : tempname);
|
||||
|
||||
// Only add the rom if there's useful information in it
|
||||
if (!(crc == "" && md5 == "" && sha1 == "") || nodump)
|
||||
@@ -1431,237 +1428,6 @@ namespace SabreTools.Helper
|
||||
return datdata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merge an arbitrary set of ROMs based on the supplied information
|
||||
/// </summary>
|
||||
/// <param name="inroms">List of RomData objects representing the roms to be merged</param>
|
||||
/// <param name="logger">Logger object for console and/or file output</param>
|
||||
/// <returns>A List of RomData objects representing the merged roms</returns>
|
||||
public static List<RomData> Merge(List<RomData> inroms, Logger logger)
|
||||
{
|
||||
// Check for null or blank roms first
|
||||
if (inroms == null || inroms.Count == 0)
|
||||
{
|
||||
return new List<RomData>();
|
||||
}
|
||||
|
||||
// Create output list
|
||||
List<RomData> outroms = new List<RomData>();
|
||||
|
||||
// First sort the roms by size, crc, md5, sha1 (in order)
|
||||
inroms.Sort(delegate (RomData x, RomData y)
|
||||
{
|
||||
if (x.Size == y.Size)
|
||||
{
|
||||
if (x.CRC == y.CRC)
|
||||
{
|
||||
if (x.MD5 == y.MD5)
|
||||
{
|
||||
return String.Compare(x.SHA1, y.SHA1);
|
||||
}
|
||||
return String.Compare(x.MD5, y.MD5);
|
||||
}
|
||||
return String.Compare(x.CRC, y.CRC);
|
||||
}
|
||||
return (int)(x.Size - y.Size);
|
||||
});
|
||||
|
||||
// Then, deduplicate them by checking to see if data matches
|
||||
foreach (RomData rom in inroms)
|
||||
{
|
||||
// If it's a nodump, add and skip
|
||||
if (rom.Nodump)
|
||||
{
|
||||
outroms.Add(rom);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If it's the first rom in the list, don't touch it
|
||||
if (outroms.Count != 0)
|
||||
{
|
||||
// Check if the rom is a duplicate
|
||||
bool dupefound = false;
|
||||
RomData savedrom = new RomData();
|
||||
int pos = -1;
|
||||
for (int i = 0; i < outroms.Count; i++)
|
||||
{
|
||||
RomData lastrom = outroms[i];
|
||||
|
||||
// Get the duplicate status
|
||||
dupefound = IsDuplicate(rom, lastrom);
|
||||
|
||||
// If it's a duplicate, skip adding it to the output but add any missing information
|
||||
if (dupefound)
|
||||
{
|
||||
savedrom = lastrom;
|
||||
pos = i;
|
||||
|
||||
savedrom.CRC = (String.IsNullOrEmpty(savedrom.CRC) && !String.IsNullOrEmpty(rom.CRC) ? rom.CRC : savedrom.CRC);
|
||||
savedrom.MD5 = (String.IsNullOrEmpty(savedrom.MD5) && !String.IsNullOrEmpty(rom.MD5) ? rom.MD5 : savedrom.MD5);
|
||||
savedrom.SHA1 = (String.IsNullOrEmpty(savedrom.SHA1) && !String.IsNullOrEmpty(rom.SHA1) ? rom.SHA1 : savedrom.SHA1);
|
||||
|
||||
// If the duplicate is external already or should be, set it
|
||||
if (savedrom.Dupe >= DupeType.ExternalHash || savedrom.SystemID != rom.SystemID || savedrom.SourceID != rom.SourceID)
|
||||
{
|
||||
if (savedrom.Game == rom.Game && savedrom.Name == rom.Name)
|
||||
{
|
||||
savedrom.Dupe = DupeType.ExternalAll;
|
||||
}
|
||||
else
|
||||
{
|
||||
savedrom.Dupe = DupeType.ExternalHash;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, it's considered an internal dupe
|
||||
else
|
||||
{
|
||||
if (savedrom.Game == rom.Game && savedrom.Name == rom.Name)
|
||||
{
|
||||
savedrom.Dupe = DupeType.InternalAll;
|
||||
}
|
||||
else
|
||||
{
|
||||
savedrom.Dupe = DupeType.InternalHash;
|
||||
}
|
||||
}
|
||||
|
||||
// If the current system has a lower ID than the previous, set the system accordingly
|
||||
if (rom.SystemID < savedrom.SystemID)
|
||||
{
|
||||
savedrom.SystemID = rom.SystemID;
|
||||
savedrom.System = rom.System;
|
||||
savedrom.Game = rom.Game;
|
||||
savedrom.Name = rom.Name;
|
||||
}
|
||||
|
||||
// If the current source has a lower ID than the previous, set the source accordingly
|
||||
if (rom.SourceID < savedrom.SourceID)
|
||||
{
|
||||
savedrom.SourceID = rom.SourceID;
|
||||
savedrom.Source = rom.Source;
|
||||
savedrom.Game = rom.Game;
|
||||
savedrom.Name = rom.Name;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no duplicate is found, add it to the list
|
||||
if (!dupefound)
|
||||
{
|
||||
outroms.Add(rom);
|
||||
}
|
||||
// Otherwise, if a new rom information is found, add that
|
||||
else
|
||||
{
|
||||
outroms.RemoveAt(pos);
|
||||
outroms.Insert(pos, savedrom);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outroms.Add(rom);
|
||||
}
|
||||
}
|
||||
|
||||
// Then return the result
|
||||
return outroms;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all duplicates found in a DAT based on a rom
|
||||
/// </summary>
|
||||
/// <param name="lastrom">Rom to use as a base</param>
|
||||
/// <param name="datdata">DAT to match against</param>
|
||||
/// <returns>List of matched RomData objects</returns>
|
||||
public static List<RomData> GetDuplicates(RomData lastrom, DatData datdata)
|
||||
{
|
||||
List<RomData> output = new List<RomData>();
|
||||
|
||||
// Check for an empty rom list first
|
||||
if (datdata.Roms == null || datdata.Roms.Count == 0)
|
||||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
// Try to find duplicates
|
||||
foreach (List<RomData> roms in datdata.Roms.Values)
|
||||
{
|
||||
foreach (RomData rom in roms)
|
||||
{
|
||||
if (IsDuplicate(rom, lastrom))
|
||||
{
|
||||
output.Add(rom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a file is a duplicate using partial matching logic
|
||||
/// </summary>
|
||||
/// <param name="rom">Rom to check for duplicate status</param>
|
||||
/// <param name="lastrom">Rom to use as a baseline</param>
|
||||
/// <returns>True if the roms are duplicates, false otherwise</returns>
|
||||
public static bool IsDuplicate(RomData rom, RomData lastrom)
|
||||
{
|
||||
bool dupefound = false;
|
||||
|
||||
// If either is a nodump, it's never a match
|
||||
if (rom.Nodump || lastrom.Nodump)
|
||||
{
|
||||
return dupefound;
|
||||
}
|
||||
|
||||
if (rom.Type == "rom" && lastrom.Type == "rom")
|
||||
{
|
||||
dupefound = ((rom.Size == lastrom.Size) &&
|
||||
((String.IsNullOrEmpty(rom.CRC) || String.IsNullOrEmpty(lastrom.CRC)) || rom.CRC == lastrom.CRC) &&
|
||||
((String.IsNullOrEmpty(rom.MD5) || String.IsNullOrEmpty(lastrom.MD5)) || rom.MD5 == lastrom.MD5) &&
|
||||
((String.IsNullOrEmpty(rom.SHA1) || String.IsNullOrEmpty(lastrom.SHA1)) || rom.SHA1 == lastrom.SHA1)
|
||||
);
|
||||
}
|
||||
else if (rom.Type == "disk" && lastrom.Type == "disk")
|
||||
{
|
||||
dupefound = (((String.IsNullOrEmpty(rom.MD5) || String.IsNullOrEmpty(lastrom.MD5)) || rom.MD5 == lastrom.MD5) &&
|
||||
((String.IsNullOrEmpty(rom.SHA1) || String.IsNullOrEmpty(lastrom.SHA1)) || rom.SHA1 == lastrom.SHA1)
|
||||
);
|
||||
}
|
||||
|
||||
return dupefound;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sort a list of RomData objects by SystemID, SourceID, Game, and Name (in order)
|
||||
/// </summary>
|
||||
/// <param name="roms">List of RomData objects representing the roms to be sorted</param>
|
||||
/// <param name="norename">True if files are not renamed, false otherwise</param>
|
||||
/// <returns>True if it sorted correctly, false otherwise</returns>
|
||||
public static bool Sort(List<RomData> roms, bool norename)
|
||||
{
|
||||
roms.Sort(delegate (RomData x, RomData y)
|
||||
{
|
||||
if (x.SystemID == y.SystemID)
|
||||
{
|
||||
if (x.SourceID == y.SourceID)
|
||||
{
|
||||
if (x.Game == y.Game)
|
||||
{
|
||||
return String.Compare(x.Name, y.Name);
|
||||
}
|
||||
return String.Compare(x.Game, y.Game);
|
||||
}
|
||||
return (norename ? String.Compare(x.Game, y.Game) : x.SourceID - y.SourceID);
|
||||
}
|
||||
return (norename ? String.Compare(x.Game, y.Game) : x.SystemID - y.SystemID);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Take an arbitrarily bucketed Dictionary and return one sorted by Game
|
||||
/// </summary>
|
||||
@@ -1688,7 +1454,7 @@ namespace SabreTools.Helper
|
||||
List<RomData> newroms = roms;
|
||||
if (mergeroms)
|
||||
{
|
||||
newroms = Merge(newroms, logger);
|
||||
newroms = RomTools.Merge(newroms, logger);
|
||||
}
|
||||
|
||||
foreach (RomData rom in newroms)
|
||||
@@ -1717,36 +1483,6 @@ namespace SabreTools.Helper
|
||||
return sortable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean a game (or rom) name to the WoD standard
|
||||
/// </summary>
|
||||
/// <param name="game">Name of the game to be cleaned</param>
|
||||
/// <returns>The cleaned name</returns>
|
||||
public static string CleanGameName(string game)
|
||||
{
|
||||
///Run the name through the filters to make sure that it's correct
|
||||
game = Style.NormalizeChars(game);
|
||||
game = Style.RussianToLatin(game);
|
||||
game = Style.SearchPattern(game);
|
||||
|
||||
game = new Regex(@"(([[(].*[\)\]] )?([^([]+))").Match(game).Groups[1].Value;
|
||||
game = game.TrimStart().TrimEnd();
|
||||
return game;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean a game (or rom) name to the WoD standard
|
||||
/// </summary>
|
||||
/// <param name="game">Array representing the path to be cleaned</param>
|
||||
/// <returns>The cleaned name</returns>
|
||||
public static string CleanGameName(string[] game)
|
||||
{
|
||||
game[game.Length - 1] = CleanGameName(game[game.Length - 1]);
|
||||
string outgame = String.Join(Path.DirectorySeparatorChar.ToString(), game);
|
||||
outgame = outgame.TrimStart().TrimEnd();
|
||||
return outgame;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert, update, and filter a DAT file
|
||||
/// </summary>
|
||||
@@ -1985,69 +1721,5 @@ namespace SabreTools.Helper
|
||||
|
||||
return datdata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve file information for a single file
|
||||
/// </summary>
|
||||
/// <param name="input">Filename to get information from</param>
|
||||
/// <param name="noMD5">True if MD5 hashes should not be calculated, false otherwise</param>
|
||||
/// <param name="noSHA1">True if SHA-1 hashes should not be calcluated, false otherwise</param>
|
||||
/// <returns>Populated RomData object if success, empty one on error</returns>
|
||||
public static RomData GetSingleFileInfo(string input, bool noMD5 = false, bool noSHA1 = false)
|
||||
{
|
||||
RomData rom = new RomData
|
||||
{
|
||||
Name = Path.GetFileName(input),
|
||||
Type = "rom",
|
||||
Size = (new FileInfo(input)).Length,
|
||||
CRC = string.Empty,
|
||||
MD5 = string.Empty,
|
||||
SHA1 = string.Empty,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
using (Crc32 crc = new Crc32())
|
||||
using (MD5 md5 = MD5.Create())
|
||||
using (SHA1 sha1 = SHA1.Create())
|
||||
using (FileStream fs = File.OpenRead(input))
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
crc.TransformBlock(buffer, 0, read, buffer, 0);
|
||||
if (!noMD5)
|
||||
{
|
||||
md5.TransformBlock(buffer, 0, read, buffer, 0);
|
||||
}
|
||||
if (!noSHA1)
|
||||
{
|
||||
sha1.TransformBlock(buffer, 0, read, buffer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
crc.TransformFinalBlock(buffer, 0, 0);
|
||||
rom.CRC = BitConverter.ToString(crc.Hash).Replace("-", "").ToLowerInvariant();
|
||||
|
||||
if (!noMD5)
|
||||
{
|
||||
md5.TransformFinalBlock(buffer, 0, 0);
|
||||
rom.MD5 = BitConverter.ToString(md5.Hash).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
if (!noSHA1)
|
||||
{
|
||||
sha1.TransformFinalBlock(buffer, 0, 0);
|
||||
rom.SHA1 = BitConverter.ToString(sha1.Hash).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return new RomData();
|
||||
}
|
||||
|
||||
return rom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
307
SabreTools.Helper/Tools/RomTools.cs
Normal file
307
SabreTools.Helper/Tools/RomTools.cs
Normal file
@@ -0,0 +1,307 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using DamienG.Security.Cryptography;
|
||||
|
||||
namespace SabreTools.Helper
|
||||
{
|
||||
public class RomTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve file information for a single file
|
||||
/// </summary>
|
||||
/// <param name="input">Filename to get information from</param>
|
||||
/// <param name="noMD5">True if MD5 hashes should not be calculated, false otherwise</param>
|
||||
/// <param name="noSHA1">True if SHA-1 hashes should not be calcluated, false otherwise</param>
|
||||
/// <returns>Populated RomData object if success, empty one on error</returns>
|
||||
public static RomData GetSingleFileInfo(string input, bool noMD5 = false, bool noSHA1 = false)
|
||||
{
|
||||
RomData rom = new RomData
|
||||
{
|
||||
Name = Path.GetFileName(input),
|
||||
Type = "rom",
|
||||
Size = (new FileInfo(input)).Length,
|
||||
CRC = string.Empty,
|
||||
MD5 = string.Empty,
|
||||
SHA1 = string.Empty,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
using (Crc32 crc = new Crc32())
|
||||
using (MD5 md5 = MD5.Create())
|
||||
using (SHA1 sha1 = SHA1.Create())
|
||||
using (FileStream fs = File.OpenRead(input))
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
crc.TransformBlock(buffer, 0, read, buffer, 0);
|
||||
if (!noMD5)
|
||||
{
|
||||
md5.TransformBlock(buffer, 0, read, buffer, 0);
|
||||
}
|
||||
if (!noSHA1)
|
||||
{
|
||||
sha1.TransformBlock(buffer, 0, read, buffer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
crc.TransformFinalBlock(buffer, 0, 0);
|
||||
rom.CRC = BitConverter.ToString(crc.Hash).Replace("-", "").ToLowerInvariant();
|
||||
|
||||
if (!noMD5)
|
||||
{
|
||||
md5.TransformFinalBlock(buffer, 0, 0);
|
||||
rom.MD5 = BitConverter.ToString(md5.Hash).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
if (!noSHA1)
|
||||
{
|
||||
sha1.TransformFinalBlock(buffer, 0, 0);
|
||||
rom.SHA1 = BitConverter.ToString(sha1.Hash).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return new RomData();
|
||||
}
|
||||
|
||||
return rom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merge an arbitrary set of ROMs based on the supplied information
|
||||
/// </summary>
|
||||
/// <param name="inroms">List of RomData objects representing the roms to be merged</param>
|
||||
/// <param name="logger">Logger object for console and/or file output</param>
|
||||
/// <returns>A List of RomData objects representing the merged roms</returns>
|
||||
public static List<RomData> Merge(List<RomData> inroms, Logger logger)
|
||||
{
|
||||
// Check for null or blank roms first
|
||||
if (inroms == null || inroms.Count == 0)
|
||||
{
|
||||
return new List<RomData>();
|
||||
}
|
||||
|
||||
// Create output list
|
||||
List<RomData> outroms = new List<RomData>();
|
||||
|
||||
// First sort the roms by size, crc, md5, sha1 (in order)
|
||||
inroms.Sort(delegate (RomData x, RomData y)
|
||||
{
|
||||
if (x.Size == y.Size)
|
||||
{
|
||||
if (x.CRC == y.CRC)
|
||||
{
|
||||
if (x.MD5 == y.MD5)
|
||||
{
|
||||
return String.Compare(x.SHA1, y.SHA1);
|
||||
}
|
||||
return String.Compare(x.MD5, y.MD5);
|
||||
}
|
||||
return String.Compare(x.CRC, y.CRC);
|
||||
}
|
||||
return (int)(x.Size - y.Size);
|
||||
});
|
||||
|
||||
// Then, deduplicate them by checking to see if data matches
|
||||
foreach (RomData rom in inroms)
|
||||
{
|
||||
// If it's a nodump, add and skip
|
||||
if (rom.Nodump)
|
||||
{
|
||||
outroms.Add(rom);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If it's the first rom in the list, don't touch it
|
||||
if (outroms.Count != 0)
|
||||
{
|
||||
// Check if the rom is a duplicate
|
||||
bool dupefound = false;
|
||||
RomData savedrom = new RomData();
|
||||
int pos = -1;
|
||||
for (int i = 0; i < outroms.Count; i++)
|
||||
{
|
||||
RomData lastrom = outroms[i];
|
||||
|
||||
// Get the duplicate status
|
||||
dupefound = IsDuplicate(rom, lastrom);
|
||||
|
||||
// If it's a duplicate, skip adding it to the output but add any missing information
|
||||
if (dupefound)
|
||||
{
|
||||
savedrom = lastrom;
|
||||
pos = i;
|
||||
|
||||
savedrom.CRC = (String.IsNullOrEmpty(savedrom.CRC) && !String.IsNullOrEmpty(rom.CRC) ? rom.CRC : savedrom.CRC);
|
||||
savedrom.MD5 = (String.IsNullOrEmpty(savedrom.MD5) && !String.IsNullOrEmpty(rom.MD5) ? rom.MD5 : savedrom.MD5);
|
||||
savedrom.SHA1 = (String.IsNullOrEmpty(savedrom.SHA1) && !String.IsNullOrEmpty(rom.SHA1) ? rom.SHA1 : savedrom.SHA1);
|
||||
|
||||
// If the duplicate is external already or should be, set it
|
||||
if (savedrom.Dupe >= DupeType.ExternalHash || savedrom.SystemID != rom.SystemID || savedrom.SourceID != rom.SourceID)
|
||||
{
|
||||
if (savedrom.Game == rom.Game && savedrom.Name == rom.Name)
|
||||
{
|
||||
savedrom.Dupe = DupeType.ExternalAll;
|
||||
}
|
||||
else
|
||||
{
|
||||
savedrom.Dupe = DupeType.ExternalHash;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, it's considered an internal dupe
|
||||
else
|
||||
{
|
||||
if (savedrom.Game == rom.Game && savedrom.Name == rom.Name)
|
||||
{
|
||||
savedrom.Dupe = DupeType.InternalAll;
|
||||
}
|
||||
else
|
||||
{
|
||||
savedrom.Dupe = DupeType.InternalHash;
|
||||
}
|
||||
}
|
||||
|
||||
// If the current system has a lower ID than the previous, set the system accordingly
|
||||
if (rom.SystemID < savedrom.SystemID)
|
||||
{
|
||||
savedrom.SystemID = rom.SystemID;
|
||||
savedrom.System = rom.System;
|
||||
savedrom.Game = rom.Game;
|
||||
savedrom.Name = rom.Name;
|
||||
}
|
||||
|
||||
// If the current source has a lower ID than the previous, set the source accordingly
|
||||
if (rom.SourceID < savedrom.SourceID)
|
||||
{
|
||||
savedrom.SourceID = rom.SourceID;
|
||||
savedrom.Source = rom.Source;
|
||||
savedrom.Game = rom.Game;
|
||||
savedrom.Name = rom.Name;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no duplicate is found, add it to the list
|
||||
if (!dupefound)
|
||||
{
|
||||
outroms.Add(rom);
|
||||
}
|
||||
// Otherwise, if a new rom information is found, add that
|
||||
else
|
||||
{
|
||||
outroms.RemoveAt(pos);
|
||||
outroms.Insert(pos, savedrom);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outroms.Add(rom);
|
||||
}
|
||||
}
|
||||
|
||||
// Then return the result
|
||||
return outroms;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List all duplicates found in a DAT based on a rom
|
||||
/// </summary>
|
||||
/// <param name="lastrom">Rom to use as a base</param>
|
||||
/// <param name="datdata">DAT to match against</param>
|
||||
/// <returns>List of matched RomData objects</returns>
|
||||
public static List<RomData> GetDuplicates(RomData lastrom, DatData datdata)
|
||||
{
|
||||
List<RomData> output = new List<RomData>();
|
||||
|
||||
// Check for an empty rom list first
|
||||
if (datdata.Roms == null || datdata.Roms.Count == 0)
|
||||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
// Try to find duplicates
|
||||
foreach (List<RomData> roms in datdata.Roms.Values)
|
||||
{
|
||||
foreach (RomData rom in roms)
|
||||
{
|
||||
if (IsDuplicate(rom, lastrom))
|
||||
{
|
||||
output.Add(rom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a file is a duplicate using partial matching logic
|
||||
/// </summary>
|
||||
/// <param name="rom">Rom to check for duplicate status</param>
|
||||
/// <param name="lastrom">Rom to use as a baseline</param>
|
||||
/// <returns>True if the roms are duplicates, false otherwise</returns>
|
||||
public static bool IsDuplicate(RomData rom, RomData lastrom)
|
||||
{
|
||||
bool dupefound = false;
|
||||
|
||||
// If either is a nodump, it's never a match
|
||||
if (rom.Nodump || lastrom.Nodump)
|
||||
{
|
||||
return dupefound;
|
||||
}
|
||||
|
||||
if (rom.Type == "rom" && lastrom.Type == "rom")
|
||||
{
|
||||
dupefound = ((rom.Size == lastrom.Size) &&
|
||||
((String.IsNullOrEmpty(rom.CRC) || String.IsNullOrEmpty(lastrom.CRC)) || rom.CRC == lastrom.CRC) &&
|
||||
((String.IsNullOrEmpty(rom.MD5) || String.IsNullOrEmpty(lastrom.MD5)) || rom.MD5 == lastrom.MD5) &&
|
||||
((String.IsNullOrEmpty(rom.SHA1) || String.IsNullOrEmpty(lastrom.SHA1)) || rom.SHA1 == lastrom.SHA1)
|
||||
);
|
||||
}
|
||||
else if (rom.Type == "disk" && lastrom.Type == "disk")
|
||||
{
|
||||
dupefound = (((String.IsNullOrEmpty(rom.MD5) || String.IsNullOrEmpty(lastrom.MD5)) || rom.MD5 == lastrom.MD5) &&
|
||||
((String.IsNullOrEmpty(rom.SHA1) || String.IsNullOrEmpty(lastrom.SHA1)) || rom.SHA1 == lastrom.SHA1)
|
||||
);
|
||||
}
|
||||
|
||||
return dupefound;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sort a list of RomData objects by SystemID, SourceID, Game, and Name (in order)
|
||||
/// </summary>
|
||||
/// <param name="roms">List of RomData objects representing the roms to be sorted</param>
|
||||
/// <param name="norename">True if files are not renamed, false otherwise</param>
|
||||
/// <returns>True if it sorted correctly, false otherwise</returns>
|
||||
public static bool Sort(List<RomData> roms, bool norename)
|
||||
{
|
||||
roms.Sort(delegate (RomData x, RomData y)
|
||||
{
|
||||
if (x.SystemID == y.SystemID)
|
||||
{
|
||||
if (x.SourceID == y.SourceID)
|
||||
{
|
||||
if (x.Game == y.Game)
|
||||
{
|
||||
return String.Compare(x.Name, y.Name);
|
||||
}
|
||||
return String.Compare(x.Game, y.Game);
|
||||
}
|
||||
return (norename ? String.Compare(x.Game, y.Game) : x.SourceID - y.SourceID);
|
||||
}
|
||||
return (norename ? String.Compare(x.Game, y.Game) : x.SystemID - y.SystemID);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,6 +182,36 @@ namespace SabreTools.Helper
|
||||
return outfile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean a game (or rom) name to the WoD standard
|
||||
/// </summary>
|
||||
/// <param name="game">Name of the game to be cleaned</param>
|
||||
/// <returns>The cleaned name</returns>
|
||||
public static string CleanGameName(string game)
|
||||
{
|
||||
///Run the name through the filters to make sure that it's correct
|
||||
game = Style.NormalizeChars(game);
|
||||
game = Style.RussianToLatin(game);
|
||||
game = Style.SearchPattern(game);
|
||||
|
||||
game = new Regex(@"(([[(].*[\)\]] )?([^([]+))").Match(game).Groups[1].Value;
|
||||
game = game.TrimStart().TrimEnd();
|
||||
return game;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean a game (or rom) name to the WoD standard
|
||||
/// </summary>
|
||||
/// <param name="game">Array representing the path to be cleaned</param>
|
||||
/// <returns>The cleaned name</returns>
|
||||
public static string CleanGameName(string[] game)
|
||||
{
|
||||
game[game.Length - 1] = CleanGameName(game[game.Length - 1]);
|
||||
string outgame = String.Join(Path.DirectorySeparatorChar.ToString(), game);
|
||||
outgame = outgame.TrimStart().TrimEnd();
|
||||
return outgame;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the human-readable file size for an arbitrary, 64-bit file size
|
||||
/// The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"
|
||||
|
||||
@@ -371,7 +371,7 @@ namespace SabreTools
|
||||
private string ProcessFile(string item, StreamWriter sw, string basepath, string parent, DatData datdata, string lastparent)
|
||||
{
|
||||
_logger.Log(Path.GetFileName(item) + " treated like a file");
|
||||
RomData rom = DatTools.GetSingleFileInfo(item, _noMD5, _noSHA1);
|
||||
RomData rom = RomTools.GetSingleFileInfo(item, _noMD5, _noSHA1);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -284,7 +284,7 @@ JOIN checksums
|
||||
{
|
||||
foreach (string key in roms.Keys)
|
||||
{
|
||||
roms[key] = DatTools.Merge(roms[key], _logger);
|
||||
roms[key] = RomTools.Merge(roms[key], _logger);
|
||||
}
|
||||
}
|
||||
// END COMMENT
|
||||
|
||||
@@ -378,7 +378,7 @@ namespace SabreTools
|
||||
List<RomData> newroms = roms;
|
||||
if (datdata.MergeRoms)
|
||||
{
|
||||
newroms = DatTools.Merge(newroms, _logger);
|
||||
newroms = RomTools.Merge(newroms, _logger);
|
||||
}
|
||||
|
||||
foreach (RomData rom in newroms)
|
||||
@@ -402,7 +402,7 @@ namespace SabreTools
|
||||
foreach (string key in sortable.Keys)
|
||||
{
|
||||
List<RomData> roms = sortable[key];
|
||||
DatTools.Sort(roms, true);
|
||||
RomTools.Sort(roms, true);
|
||||
|
||||
long gameid = -1;
|
||||
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace SabreTools
|
||||
List<string> keys = userData.Roms.Keys.ToList();
|
||||
foreach (string key in keys)
|
||||
{
|
||||
List<RomData> roms = DatTools.Merge(userData.Roms[key], _logger);
|
||||
List<RomData> roms = RomTools.Merge(userData.Roms[key], _logger);
|
||||
|
||||
if (roms != null && roms.Count > 0)
|
||||
{
|
||||
@@ -415,7 +415,7 @@ namespace SabreTools
|
||||
List<string> keys = userData.Roms.Keys.ToList();
|
||||
foreach (string key in keys)
|
||||
{
|
||||
List<RomData> roms = DatTools.Merge(userData.Roms[key], _logger);
|
||||
List<RomData> roms = RomTools.Merge(userData.Roms[key], _logger);
|
||||
|
||||
if (roms != null && roms.Count > 0)
|
||||
{
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace SabreTools
|
||||
Dictionary<string, List<RomData>> netNew = new Dictionary<string, List<RomData>>();
|
||||
foreach (string key in completeDats.Roms.Keys)
|
||||
{
|
||||
List<RomData> templist = DatTools.Merge(completeDats.Roms[key], _logger);
|
||||
List<RomData> templist = RomTools.Merge(completeDats.Roms[key], _logger);
|
||||
foreach (RomData rom in templist)
|
||||
{
|
||||
if (rom.Dupe == DupeType.None && rom.System == _currentNewMerged)
|
||||
@@ -91,7 +91,7 @@ namespace SabreTools
|
||||
Dictionary<string, List<RomData>> unneeded = new Dictionary<string, List<RomData>>();
|
||||
foreach (string key in completeDats.Roms.Keys)
|
||||
{
|
||||
List<RomData> templist = DatTools.Merge(completeDats.Roms[key], _logger);
|
||||
List<RomData> templist = RomTools.Merge(completeDats.Roms[key], _logger);
|
||||
foreach (RomData rom in templist)
|
||||
{
|
||||
if (rom.Dupe == DupeType.None && rom.System == _currentAllMerged)
|
||||
@@ -128,7 +128,7 @@ namespace SabreTools
|
||||
Dictionary<string, List<RomData>> newMissing = new Dictionary<string, List<RomData>>();
|
||||
foreach (string key in midMissing.Roms.Keys)
|
||||
{
|
||||
List<RomData> templist = DatTools.Merge(midMissing.Roms[key], _logger);
|
||||
List<RomData> templist = RomTools.Merge(midMissing.Roms[key], _logger);
|
||||
foreach (RomData rom in templist)
|
||||
{
|
||||
if (rom.Dupe == DupeType.None && rom.System == _currentMissingMerged)
|
||||
@@ -200,7 +200,7 @@ namespace SabreTools
|
||||
Dictionary<string, List<RomData>> have = new Dictionary<string, List<RomData>>();
|
||||
foreach (string key in midHave.Keys)
|
||||
{
|
||||
List<RomData> templist = DatTools.Merge(midHave[key], _logger);
|
||||
List<RomData> templist = RomTools.Merge(midHave[key], _logger);
|
||||
foreach (RomData rom in templist)
|
||||
{
|
||||
if (rom.Dupe == DupeType.None && rom.System == _currentNewMerged)
|
||||
@@ -368,7 +368,7 @@ namespace SabreTools
|
||||
Dictionary<string, List<RomData>> have = new Dictionary<string, List<RomData>>();
|
||||
foreach (string key in midHave.Roms.Keys)
|
||||
{
|
||||
List<RomData> templist = DatTools.Merge(midHave.Roms[key], _logger);
|
||||
List<RomData> templist = RomTools.Merge(midHave.Roms[key], _logger);
|
||||
foreach (RomData rom in templist)
|
||||
{
|
||||
if (rom.Dupe == DupeType.None && rom.System == _currentAllMerged)
|
||||
@@ -438,7 +438,7 @@ namespace SabreTools
|
||||
Dictionary<string, List<RomData>> have = new Dictionary<string, List<RomData>>();
|
||||
foreach (string key in midHave.Roms.Keys)
|
||||
{
|
||||
List<RomData> templist = DatTools.Merge(midHave.Roms[key], _logger);
|
||||
List<RomData> templist = RomTools.Merge(midHave.Roms[key], _logger);
|
||||
foreach (RomData rom in templist)
|
||||
{
|
||||
if (rom.Dupe == DupeType.None && rom.System == _currentNewMerged)
|
||||
|
||||
@@ -297,7 +297,7 @@ namespace SabreTools
|
||||
_logger.User("Beginning processing of '" + input + "'");
|
||||
|
||||
// Get the hash of the file first
|
||||
RomData rom = DatTools.GetSingleFileInfo(input);
|
||||
RomData rom = RomTools.GetSingleFileInfo(input);
|
||||
|
||||
// If we have a blank RomData, it's an error
|
||||
if (rom.Name == null)
|
||||
@@ -306,7 +306,7 @@ namespace SabreTools
|
||||
}
|
||||
|
||||
// Try to find the matches to the file that was found
|
||||
List<RomData> foundroms = DatTools.GetDuplicates(rom, _datdata);
|
||||
List<RomData> foundroms = RomTools.GetDuplicates(rom, _datdata);
|
||||
_logger.User("File '" + input + "' had " + foundroms.Count + " matches in the DAT!");
|
||||
foreach (RomData found in foundroms)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user