diff --git a/DATabase/Generate.cs b/DATabase/Generate.cs index e6fd4fa3..27975092 100644 --- a/DATabase/Generate.cs +++ b/DATabase/Generate.cs @@ -255,8 +255,8 @@ JOIN checksums // If we're in a merged mode, merge and then resort by the correct parameters if (merged) { - roms = Sorting.RomMerge(roms, true); - Sorting.RomSort(roms, _norename); + roms = RomManipulation.Merge(roms, true); + RomManipulation.Sort(roms, _norename); } // Now check rename within games diff --git a/DATabase/Import.cs b/DATabase/Import.cs index e4894483..ddbb38b3 100644 --- a/DATabase/Import.cs +++ b/DATabase/Import.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Data.SQLite; using System.IO; using System.Text.RegularExpressions; @@ -377,156 +378,24 @@ namespace SabreTools } } - // Attempt to load the current file as XML - bool superdat = false; - XmlDocument doc = new XmlDocument(); - try - { - doc.LoadXml(File.ReadAllText(_filepath)); - } - catch (XmlException) - { - doc.LoadXml(Converters.RomVaultToXML(File.ReadAllLines(_filepath)).ToString()); - } + // Get all roms that are found in the DAT to see what needs to be added + List roms = RomManipulation.Parse(_filepath, sysid, srcid, _logger); - // Experimental looping using only XML parsing - XmlNode node = doc.FirstChild; - if (node != null && node.Name == "xml") + // Sort and loop over all roms, checking for adds + RomManipulation.Sort(roms, true); + string lastgame = ""; + long gameid = -1; + foreach (RomData rom in roms) { - // Skip over everything that's not an element - while (node.NodeType != XmlNodeType.Element) + // If we have a new game, check for a new ID + if (rom.Game != lastgame) { - node = node.NextSibling; - } - } - - // Once we find the main body, enter it - if (node != null && (node.Name == "datafile" || node.Name == "softwarelist")) - { - node = node.FirstChild; - } - - // Skip the header if it exists - if (node != null && node.Name == "header") - { - // Check for SuperDAT mode - if (node.SelectSingleNode("name").InnerText.Contains(" - SuperDAT")) - { - superdat = true; + gameid = AddGame(sysid, rom.Game, srcid); + lastgame = rom.Game; } - // Skip over anything that's not an element - while (node.NodeType != XmlNodeType.Element) - { - node = node.NextSibling; - } - } - - while (node != null) - { - if (node.NodeType == XmlNodeType.Element && (node.Name == "machine" || node.Name == "game" || node.Name == "software")) - { - long gameid = -1; - string tempname = ""; - if (node.Name == "software") - { - tempname = node.SelectSingleNode("description").InnerText; - } - else - { - // There are rare cases where a malformed XML will not have the required attributes. We can only skip them. - if (node.Attributes.Count == 0) - { - _logger.Error(@"A node with malformed XML has been found! - For RV DATs, please make sure that all names and descriptions are quoted. - For XML DATs, make sure that the DAT has all required information."); - node = node.NextSibling; - continue; - } - tempname = node.Attributes["name"].Value; - } - - if (superdat) - { - tempname = Regex.Match(tempname, @".*?\\(.*)").Groups[1].Value; - } - - gameid = AddGame(sysid, tempname, srcid); - - // Get the roms from the machine - if (node.HasChildNodes) - { - // If this node has children, traverse the children - foreach (XmlNode child in node.ChildNodes) - { - // If we find a rom or disk, add it - if (child.NodeType == XmlNodeType.Element && (child.Name == "rom" || child.Name == "disk")) - { - // Take care of hex-sized files - long size = -1; - if (child.Attributes["size"] != null && child.Attributes["size"].Value.Contains("0x")) - { - size = Convert.ToInt64(child.Attributes["size"].Value, 16); - } - else if (child.Attributes["size"] != null) - { - size = Int64.Parse(child.Attributes["size"].Value); - } - - AddRom( - child.Name, - gameid, - child.Attributes["name"].Value, - date, - size, - (child.Attributes["crc"] != null ? child.Attributes["crc"].Value.ToLowerInvariant().Trim() : ""), - (child.Attributes["md5"] != null ? child.Attributes["md5"].Value.ToLowerInvariant().Trim() : ""), - (child.Attributes["sha1"] != null ? child.Attributes["sha1"].Value.ToLowerInvariant().Trim() : "") - ); - } - // If we find the signs of a software list, traverse the children - else if (child.NodeType == XmlNodeType.Element && child.Name == "part" && child.HasChildNodes) - { - foreach (XmlNode part in child.ChildNodes) - { - // If we find a dataarea, traverse the children - if (part.NodeType == XmlNodeType.Element && part.Name == "dataarea") - { - foreach (XmlNode data in part.ChildNodes) - { - // If we find a rom or disk, add it - if (data.NodeType == XmlNodeType.Element && (data.Name == "rom" || data.Name == "disk") && data.Attributes["name"] != null) - { - // Take care of hex-sized files - long size = -1; - if (data.Attributes["size"] != null && data.Attributes["size"].Value.Contains("0x")) - { - size = Convert.ToInt64(data.Attributes["size"].Value, 16); - } - else if (data.Attributes["size"] != null) - { - size = Int64.Parse(data.Attributes["size"].Value); - } - - AddRom( - data.Name, - gameid, - data.Attributes["name"].Value, - date, - size, - (data.Attributes["crc"] != null ? data.Attributes["crc"].Value.ToLowerInvariant().Trim() : ""), - (data.Attributes["md5"] != null ? data.Attributes["md5"].Value.ToLowerInvariant().Trim() : ""), - (data.Attributes["sha1"] != null ? data.Attributes["sha1"].Value.ToLowerInvariant().Trim() : "") - ); - } - } - } - } - } - } - } - } - node = node.NextSibling; + // Try to add the rom with the game information + AddRom(rom, gameid, date); } return true; @@ -598,28 +467,23 @@ namespace SabreTools /// /// Add a file to the database if it doesn't already exist /// - /// File type (either "rom" or "disk") + /// RomData object representing the rom /// ID of the parent game to be mapped to - /// File name /// Last updated date - /// File size in bytes - /// CRC32 hash of the file - /// MD5 hash of the file - /// SHA-1 hash of the file /// True if the file exists or could be added, false on error - private bool AddRom(string romtype, long gameid, string name, string date, long size, string crc, string md5, string sha1) + private bool AddRom(RomData rom, long gameid, string date) { // WOD origninally stripped out any subdirs from the imported files, we do the same - name = Path.GetFileName(name); + rom.Name = Path.GetFileName(rom.Name); // Run the name through the filters to make sure that it's correct - name = Style.NormalizeChars(name); - name = Style.RussianToLatin(name); - name = Regex.Replace(name, @"(.*) \.(.*)", "$1.$2"); + rom.Name = Style.NormalizeChars(rom.Name); + rom.Name = Style.RussianToLatin(rom.Name); + rom.Name = Regex.Replace(rom.Name, @"(.*) \.(.*)", "$1.$2"); - if (romtype != "rom" && romtype != "disk") + if (rom.Type != "rom" && rom.Type != "disk") { - romtype = "rom"; + rom.Type = "rom"; } // Check to see if this exact file is in the database already @@ -627,13 +491,13 @@ namespace SabreTools SELECT files.id FROM files JOIN checksums ON files.id=checksums.file - WHERE files.name='" + name.Replace("'", "''") + @"' - AND files.type='" + romtype + @"' + WHERE files.name='" + rom.Name.Replace("'", "''") + @"' + AND files.type='" + rom.Type + @"' AND files.setid=" + gameid + " " + - " AND checksums.size=" + size + - " AND checksums.crc='" + crc + "'" + - " AND checksums.md5='" + md5 + "'" + - " AND checksums.sha1='" + sha1 + "'"; + " AND checksums.size=" + rom.Size + + " AND checksums.crc='" + rom.CRC + "'" + + " AND checksums.md5='" + rom.MD5 + "'" + + " AND checksums.sha1='" + rom.SHA1 + "'"; using (SQLiteConnection dbc = new SQLiteConnection(_connectionString)) { dbc.Open(); @@ -646,7 +510,7 @@ SELECT files.id FROM files { query = @" INSERT INTO files (setid, name, type, lastupdated) - VALUES (" + gameid + ", '" + name.Replace("'", "''") + "', '" + romtype + "', '" + date + "')"; + VALUES (" + gameid + ", '" + rom.Name.Replace("'", "''") + "', '" + rom.Type + "', '" + date + "')"; using (SQLiteCommand slc2 = new SQLiteCommand(query, dbc)) { int affected = slc2.ExecuteNonQuery(); @@ -662,7 +526,7 @@ INSERT INTO files (setid, name, type, lastupdated) } query = @"INSERT INTO checksums (file, size, crc, md5, sha1) VALUES (" + - romid + ", " + size + ", '" + crc + "'" + ", '" + md5 + "'" + ", '" + sha1 + "')"; + romid + ", " + rom.Size + ", '" + rom.CRC + "'" + ", '" + rom.MD5 + "'" + ", '" + rom.SHA1 + "')"; using (SQLiteCommand slc3 = new SQLiteCommand(query, dbc)) { affected = slc3.ExecuteNonQuery(); @@ -671,14 +535,14 @@ INSERT INTO files (setid, name, type, lastupdated) // If the insert of the checksums failed, that's bad if (affected < 1) { - _logger.Error("There was an error adding checksums for " + name + " to the database!"); + _logger.Error("There was an error adding checksums for " + rom.Name + " to the database!"); return false; } } // Otherwise, something happened which is bad else { - _logger.Error("There was an error adding " + name + " to the database!"); + _logger.Error("There was an error adding " + rom.Name + " to the database!"); return false; } } diff --git a/DatSplit/DatSplit.cs b/DatSplit/DatSplit.cs index d267a3d6..97a4c1ee 100644 --- a/DatSplit/DatSplit.cs +++ b/DatSplit/DatSplit.cs @@ -32,142 +32,47 @@ namespace DatSplit return; } + Logger logger = new Logger(false, "datsplit.log"); + logger.Start(); + // Output the title Build.Start("DatSplit"); - // Set needed strings + // Set needed variables _filename = args[0]; _extA = (args[1].StartsWith(".") ? args[1] : "." + args[1]).ToUpperInvariant(); _extB = (args[2].StartsWith(".") ? args[2] : "." + args[2]).ToUpperInvariant(); + List romsA = new List(); + List romsB = new List(); - // Take the filename, and load it as an XML document - XmlDocument doc = new XmlDocument(); - try - { - doc.LoadXml(File.ReadAllText(_filename)); - } - catch (XmlException) - { - doc.LoadXml(Converters.RomVaultToXML(File.ReadAllLines(_filename)).ToString()); - } + // Load the current DAT to be processed + List roms = RomManipulation.Parse(_filename, 0, 0, logger); - // We all start the same - XmlNode node = doc.FirstChild; - if (node != null && node.Name == "xml") + // Now separate the roms accordingly + foreach (RomData rom in roms) { - // Skip over everything that's not an element - while (node.NodeType != XmlNodeType.Element) + if (rom.Name.ToUpperInvariant().EndsWith(_extA)) { - node = node.NextSibling; + romsA.Add(rom); } - } - - XmlDocument outDocA = new XmlDocument(); - outDocA.AppendChild(outDocA.CreateXmlDeclaration("1.0", Encoding.UTF8.WebName, null)); - outDocA.AppendChild(outDocA.CreateDocumentType("datafile", "-//Logiqx//DTD ROM Management Datafile//EN", "http://www.logiqx.com/Dats/datafile.dtd", null)); - XmlNode outA = outDocA.CreateNode(XmlNodeType.Element, node.Name, ""); - - XmlDocument outDocB = new XmlDocument(); - outDocB.AppendChild(outDocB.CreateXmlDeclaration("1.0", Encoding.UTF8.WebName, null)); - outDocB.AppendChild(outDocB.CreateDocumentType("datafile", "-//Logiqx//DTD ROM Management Datafile//EN", "http://www.logiqx.com/Dats/datafile.dtd", null)); - XmlNode outB = outDocB.CreateNode(XmlNodeType.Element, node.Name, ""); - - // Once we find the main body, enter it - if (node != null && node.Name == "datafile") - { - node = node.FirstChild; - } - - // Now here's where it differs from import - while (node != null) - { - // If we're at a game node, add the parent node but not all the internals - if (node.NodeType == XmlNodeType.Element && (node.Name == "machine" || node.Name == "game")) + else if (rom.Name.ToUpperInvariant().EndsWith(_extB)) { - bool inA = false; - bool inB = false; - - // Get the roms from the machine - if (node.HasChildNodes) - { - // If this node has children, traverse the children - foreach (XmlNode child in node.ChildNodes) - { - // If we find a rom or disk, add it - if (child.NodeType == XmlNodeType.Element && (child.Name == "rom" || child.Name == "disk")) - { - // Take care of hex-sized files - long size = -1; - if (child.Attributes["size"] != null && child.Attributes["size"].Value.Contains("0x")) - { - size = Convert.ToInt64(child.Attributes["size"].Value, 16); - } - else if (child.Attributes["size"] != null) - { - size = Int64.Parse(child.Attributes["size"].Value); - } - - if (child.Attributes["name"].Value.ToUpperInvariant().EndsWith(_extA)) - { - if (!inA) - { - //XmlNode temp = tempDoc.CreateNode(XmlNodeType.Element, node.Name, ""); - XmlNode temp = outDocA.ImportNode(node, false); - outA.AppendChild(temp); - outA = outA.LastChild; - inA = true; - } - outA.AppendChild(outDocA.ImportNode(child, true)); - } - else if (child.Attributes["name"].Value.ToUpperInvariant().EndsWith(_extB)) - { - if (!inB) - { - //XmlNode temp = tempDoc.CreateNode(XmlNodeType.Element, node.Name, ""); - XmlNode temp = outDocB.ImportNode(node, false); - outB.AppendChild(temp); - outB = outB.LastChild; - inB = true; - } - outB.AppendChild(outDocB.ImportNode(child, true)); - } - else - { - outA.AppendChild(outDocA.ImportNode(child, true)); - outB.AppendChild(outDocB.ImportNode(child, true)); - } - } - } - - // Set the output node to the right one for both - if (inA) - { - outA = outA.ParentNode; - } - if (inB) - { - outB = outB.ParentNode; - } - } + romsB.Add(rom); } else { - XmlNode tempNode = outDocA.ImportNode(node, true); - outA.AppendChild(tempNode); - tempNode = outDocB.ImportNode(node, true); - outB.AppendChild(tempNode); + romsA.Add(rom); + romsB.Add(rom); } - node = node.NextSibling; } - // Append the built nodes to the documents - outDocA.AppendChild(outDocA.ImportNode(outA, true)); - string outPathA = Path.GetFileNameWithoutExtension(_filename) + _extA + Path.GetExtension(_filename); - File.WriteAllText(outPathA, Style.Beautify(outDocA), Encoding.UTF8); + // Then write out both files + Output.WriteToDat(Path.GetFileNameWithoutExtension(_filename) + "." + _extA, Path.GetFileNameWithoutExtension(_filename) + "." + _extA, + "", "", "", "", false, Path.GetExtension(_filename) == ".dat", "", romsA, logger); + Output.WriteToDat(Path.GetFileNameWithoutExtension(_filename) + "." + _extB, Path.GetFileNameWithoutExtension(_filename) + "." + _extB, + "", "", "", "", false, Path.GetExtension(_filename) == ".dat", "", romsB, logger); - outDocB.AppendChild(outDocB.ImportNode(outB, true)); - string outPathB = Path.GetFileNameWithoutExtension(_filename) + _extB + Path.GetExtension(_filename); - File.WriteAllText(outPathB, Style.Beautify(outDocB), Encoding.UTF8); + logger.Close(); } } } diff --git a/SabreHelper/RomManipulation.cs b/SabreHelper/RomManipulation.cs new file mode 100644 index 00000000..bdf519cd --- /dev/null +++ b/SabreHelper/RomManipulation.cs @@ -0,0 +1,288 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using System.Xml; + +namespace SabreTools.Helper +{ + public class RomManipulation + { + /// + /// Parse a DAT and return all found games and roms within + /// + /// Name of the file to be parsed + /// System ID for the DAT + /// Source ID for the DAT + /// Logger object for console and/or file output + /// List of RomData objects representing the found data + public static List Parse(string filename, int sysid, int srcid, Logger logger) + { + List roms = new List(); + + bool superdat = false; + XmlDocument doc = new XmlDocument(); + try + { + doc.LoadXml(File.ReadAllText(filename)); + } + catch (XmlException) + { + doc.LoadXml(Converters.RomVaultToXML(File.ReadAllLines(filename)).ToString()); + } + + // Experimental looping using only XML parsing + XmlNode node = doc.FirstChild; + if (node != null && node.Name == "xml") + { + // Skip over everything that's not an element + while (node.NodeType != XmlNodeType.Element) + { + node = node.NextSibling; + } + } + + // Once we find the main body, enter it + if (node != null && (node.Name == "datafile" || node.Name == "softwarelist")) + { + node = node.FirstChild; + } + + // Skip the header if it exists + if (node != null && node.Name == "header") + { + // Check for SuperDAT mode + if (node.SelectSingleNode("name").InnerText.Contains(" - SuperDAT")) + { + superdat = true; + } + + // Skip over anything that's not an element + while (node.NodeType != XmlNodeType.Element) + { + node = node.NextSibling; + } + } + + // Loop over the document until the end + while (node != null) + { + if (node.NodeType == XmlNodeType.Element && (node.Name == "machine" || node.Name == "game" || node.Name == "software")) + { + string tempname = ""; + if (node.Name == "software") + { + tempname = node.SelectSingleNode("description").InnerText; + } + else + { + // There are rare cases where a malformed XML will not have the required attributes. We can only skip them. + if (node.Attributes.Count == 0) + { + logger.Error(@"A node with malformed XML has been found! + For RV DATs, please make sure that all names and descriptions are quoted. + For XML DATs, make sure that the DAT has all required information."); + node = node.NextSibling; + continue; + } + tempname = node.Attributes["name"].Value; + } + + if (superdat) + { + tempname = Regex.Match(tempname, @".*?\\(.*)").Groups[1].Value; + } + + // Get the roms from the machine + if (node.HasChildNodes) + { + // If this node has children, traverse the children + foreach (XmlNode child in node.ChildNodes) + { + // If we find a rom or disk, add it + if (child.NodeType == XmlNodeType.Element && (child.Name == "rom" || child.Name == "disk")) + { + // Take care of hex-sized files + long size = -1; + if (child.Attributes["size"] != null && child.Attributes["size"].Value.Contains("0x")) + { + size = Convert.ToInt64(child.Attributes["size"].Value, 16); + } + else if (child.Attributes["size"] != null) + { + size = Int64.Parse(child.Attributes["size"].Value); + } + + roms.Add(new RomData + { + Game = tempname, + Name = child.Attributes["name"].Value, + Type = child.Name, + SystemID = sysid, + SourceID = srcid, + Size = size, + CRC = (child.Attributes["crc"] != null ? child.Attributes["crc"].Value.ToLowerInvariant().Trim() : ""), + MD5 = (child.Attributes["md5"] != null ? child.Attributes["md5"].Value.ToLowerInvariant().Trim() : ""), + SHA1 = (child.Attributes["sha1"] != null ? child.Attributes["sha1"].Value.ToLowerInvariant().Trim() : ""), + }); + } + // If we find the signs of a software list, traverse the children + else if (child.NodeType == XmlNodeType.Element && child.Name == "part" && child.HasChildNodes) + { + foreach (XmlNode part in child.ChildNodes) + { + // If we find a dataarea, traverse the children + if (part.NodeType == XmlNodeType.Element && part.Name == "dataarea") + { + foreach (XmlNode data in part.ChildNodes) + { + // If we find a rom or disk, add it + if (data.NodeType == XmlNodeType.Element && (data.Name == "rom" || data.Name == "disk") && data.Attributes["name"] != null) + { + // Take care of hex-sized files + long size = -1; + if (data.Attributes["size"] != null && data.Attributes["size"].Value.Contains("0x")) + { + size = Convert.ToInt64(data.Attributes["size"].Value, 16); + } + else if (data.Attributes["size"] != null) + { + size = Int64.Parse(data.Attributes["size"].Value); + } + + roms.Add(new RomData + { + Game = tempname, + Name = data.Attributes["name"].Value, + Type = data.Name, + SystemID = sysid, + SourceID = srcid, + Size = size, + CRC = (data.Attributes["crc"] != null ? data.Attributes["crc"].Value.ToLowerInvariant().Trim() : ""), + MD5 = (data.Attributes["md5"] != null ? data.Attributes["md5"].Value.ToLowerInvariant().Trim() : ""), + SHA1 = (data.Attributes["sha1"] != null ? data.Attributes["sha1"].Value.ToLowerInvariant().Trim() : ""), + }); + } + } + } + } + } + } + } + } + node = node.NextSibling; + } + + return roms; + } + + /// + /// Merge an arbitrary set of ROMs based on the supplied information + /// + /// List of RomData objects representing the roms to be merged + /// True if the list should be considered pre-sorted (default false) + /// A List of RomData objects representing the merged roms + public static List Merge(List inroms, bool presorted = false) + { + List outroms = new List(); + + // First sort the roms by size, crc, sysid, srcid, md5, and sha1 (in order), if not sorted already + if (!presorted) + { + inroms.Sort(delegate (RomData x, RomData y) + { + if (x.Size == y.Size) + { + if (x.CRC == y.CRC) + { + if (x.SystemID == y.SystemID) + { + if (x.SourceID == y.SourceID) + { + if (x.MD5 == y.MD5) + { + return String.Compare(x.SHA1, y.SHA1); + } + return String.Compare(x.MD5, y.MD5); + } + return x.SourceID - y.SourceID; + } + return x.SystemID - y.SystemID; + } + 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 the first rom in the list, don't touch it + if (outroms.Count != 0) + { + // Check if the rom is a duplicate + RomData last = outroms[outroms.Count - 1]; + + bool shouldcont = false; + if (rom.Type == "rom" && last.Type == "rom") + { + shouldcont = ((rom.Size != -1 && rom.Size == last.Size) && ( + (rom.CRC != "" && last.CRC != "" && rom.CRC == last.CRC) || + (rom.MD5 != "" && last.MD5 != "" && rom.MD5 == last.MD5) || + (rom.SHA1 != "" && last.SHA1 != "" && rom.SHA1 == last.SHA1) + ) + ); + } + else if (rom.Type == "disk" && last.Type == "disk") + { + shouldcont = ((rom.MD5 != "" && last.MD5 != "" && rom.MD5 == last.MD5) || + (rom.SHA1 != "" && last.SHA1 != "" && rom.SHA1 == last.SHA1) + ); + } + + // If it's a duplicate, skip adding it to the output but add any missing information + if (shouldcont) + { + last.CRC = (last.CRC == "" && rom.CRC != "" ? rom.CRC : last.CRC); + last.MD5 = (last.MD5 == "" && rom.MD5 != "" ? rom.MD5 : last.MD5); + last.SHA1 = (last.SHA1 == "" && rom.SHA1 != "" ? rom.SHA1 : last.SHA1); + + outroms.RemoveAt(inroms.Count - 1); + outroms.Insert(inroms.Count, last); + + continue; + } + } + } + + // Then return the result + return outroms; + } + + /// + /// Sort a list of RomData objects by SystemID, SourceID, Game, and Name (in order) + /// + /// List of RomData objects representing the roms to be sorted + /// True if files are not renamed, false otherwise + public static void Sort(List 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); + }); + } + } +} diff --git a/SabreHelper/SabreHelper.csproj b/SabreHelper/SabreHelper.csproj index 8785088d..2ba55f07 100644 --- a/SabreHelper/SabreHelper.csproj +++ b/SabreHelper/SabreHelper.csproj @@ -76,7 +76,7 @@ - + diff --git a/SabreHelper/Sorting.cs b/SabreHelper/Sorting.cs deleted file mode 100644 index 042366b5..00000000 --- a/SabreHelper/Sorting.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace SabreTools.Helper -{ - public class Sorting - { - /// - /// Merge an arbitrary set of ROMs based on the supplied information - /// - /// List of RomData objects representing the roms to be merged - /// True if the list should be considered pre-sorted (default false) - /// A List of RomData objects representing the merged roms - public static List RomMerge(List inroms, bool presorted = false) - { - List outroms = new List(); - - // First sort the roms by size, crc, sysid, srcid, md5, and sha1 (in order), if not sorted already - if (!presorted) - { - inroms.Sort(delegate (RomData x, RomData y) - { - if (x.Size == y.Size) - { - if (x.CRC == y.CRC) - { - if (x.SystemID == y.SystemID) - { - if (x.SourceID == y.SourceID) - { - if (x.MD5 == y.MD5) - { - return String.Compare(x.SHA1, y.SHA1); - } - return String.Compare(x.MD5, y.MD5); - } - return x.SourceID - y.SourceID; - } - return x.SystemID - y.SystemID; - } - 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 the first rom in the list, don't touch it - if (outroms.Count != 0) - { - // Check if the rom is a duplicate - RomData last = outroms[outroms.Count - 1]; - - bool shouldcont = false; - if (rom.Type == "rom" && last.Type == "rom") - { - shouldcont = ((rom.Size != -1 && rom.Size == last.Size) && ( - (rom.CRC != "" && last.CRC != "" && rom.CRC == last.CRC) || - (rom.MD5 != "" && last.MD5 != "" && rom.MD5 == last.MD5) || - (rom.SHA1 != "" && last.SHA1 != "" && rom.SHA1 == last.SHA1) - ) - ); - } - else if (rom.Type == "disk" && last.Type == "disk") - { - shouldcont = ((rom.MD5 != "" && last.MD5 != "" && rom.MD5 == last.MD5) || - (rom.SHA1 != "" && last.SHA1 != "" && rom.SHA1 == last.SHA1) - ); - } - - // If it's a duplicate, skip adding it to the output but add any missing information - if (shouldcont) - { - last.CRC = (last.CRC == "" && rom.CRC != "" ? rom.CRC : last.CRC); - last.MD5 = (last.MD5 == "" && rom.MD5 != "" ? rom.MD5 : last.MD5); - last.SHA1 = (last.SHA1 == "" && rom.SHA1 != "" ? rom.SHA1 : last.SHA1); - - outroms.RemoveAt(inroms.Count - 1); - outroms.Insert(inroms.Count, last); - - continue; - } - } - } - - // Then return the result - return outroms; - } - - /// - /// Sort a list of RomData objects by SystemID, SourceID, Game, and Name (in order) - /// - /// List of RomData objects representing the roms to be sorted - /// True if files are not renamed, false otherwise - public static void RomSort(List 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); - }); - } - } -} diff --git a/SingleGame/SingleGame.cs b/SingleGame/SingleGame.cs index 61ca03eb..94bde25f 100644 --- a/SingleGame/SingleGame.cs +++ b/SingleGame/SingleGame.cs @@ -30,6 +30,9 @@ namespace SabreTools return; } + Logger logger = new Logger(false, "singlegame.log"); + logger.Start(); + // Output the title Build.Start("SingleGame"); @@ -46,122 +49,37 @@ namespace SabreTools _path = (_path == "" ? Environment.CurrentDirectory : _path); - // Take the filename, and load it as an XML document - XmlDocument doc = new XmlDocument(); - try - { - doc.LoadXml(File.ReadAllText(_filename)); - } - catch (XmlException) - { - doc.LoadXml(Converters.RomVaultToXML(File.ReadAllLines(_filename)).ToString()); - } + // Import the existing DAT + List roms = RomManipulation.Parse(_filename, 0, 0, logger); - // We all start the same - XmlNode node = doc.FirstChild; - if (node != null && node.Name == "xml") + // If we are in single game mode, rename all games + if (_rename) { - // Skip over everything that's not an element - while (node.NodeType != XmlNodeType.Element) + roms.ForEach(delegate (RomData x) { - node = node.NextSibling; - } + x.Game = "!"; + }); } - XmlDocument tempDoc = new XmlDocument(); - XmlNode outNode = tempDoc.CreateNode(XmlNodeType.Element, node.Name, ""); - - // Once we find the main body, enter it - if (node != null && node.Name == "datafile") + // Trim all file names according to the path that's set + roms.ForEach(delegate (RomData x) { - node = node.FirstChild; - } + // Windows max name length is 260 + int usableLength = 259 - _path.Length; - // Now here's where it differs from import - bool inGame = false; - while (node != null) - { - // If we're at a game node, add the parent node but not all the internals - if (_rename && node.NodeType == XmlNodeType.Element && (node.Name == "machine" || node.Name == "game")) + if (x.Name.Length > usableLength) { - if (!inGame) - { - XmlElement tempNode = tempDoc.CreateElement(node.Name); - tempNode.SetAttribute("name", "!"); - outNode.AppendChild(tempNode); - outNode = outNode.LastChild; - inGame = true; - } - - // Get the roms from the machine - if (node.HasChildNodes) - { - // If this node has children, traverse the children - foreach (XmlNode child in node.ChildNodes) - { - // If we find a rom or disk, add it - if (child.NodeType == XmlNodeType.Element && (child.Name == "rom" || child.Name == "disk")) - { - // Take care of hex-sized files - long size = -1; - if (child.Attributes["size"] != null && child.Attributes["size"].Value.Contains("0x")) - { - size = Convert.ToInt64(child.Attributes["size"].Value, 16); - } - else if (child.Attributes["size"] != null) - { - size = Int64.Parse(child.Attributes["size"].Value); - } - - XmlElement tempNode = (XmlElement)tempDoc.ImportNode(child, true); - - // Windows max name length is 260 - string tempname = child.Attributes["name"].Value; - int usableLength = 259 - _path.Length; - - if (tempname.Length > usableLength) - { - string ext = Path.GetExtension(tempname); - tempname = tempname.Substring(0, usableLength - ext.Length); - tempname += ext; - } - tempNode.SetAttribute("name", tempname); - outNode.AppendChild(tempNode); - } - } - } + string ext = Path.GetExtension(x.Name); + x.Name = x.Name.Substring(0, usableLength - ext.Length); + x.Name += ext; } - else - { - XmlNode tempNode = tempDoc.ImportNode(node, true); + }); - if (tempNode.Name == "header") - { - if (tempNode.SelectSingleNode("clrmamepro") == null) - { - XmlElement tempChild = tempDoc.CreateElement("clrmamepro"); - tempChild.SetAttribute("forcepacking", "unzip"); - tempNode.AppendChild(tempChild); - } - else - { - (tempNode.SelectSingleNode("clrmamepro") as XmlElement).SetAttribute("forcepacking", "unzip"); - } - } + // Now write the file out accordingly + Output.WriteToDat(Path.GetFileNameWithoutExtension(_filename), + Path.GetFileNameWithoutExtension(_filename), "", "", "", "", false, Path.GetExtension(_filename) == ".dat", "", roms, logger); - outNode.AppendChild(tempNode); - } - node = node.NextSibling; - } - if (inGame) - { - outNode = outNode.ParentNode; - } - - tempDoc.AppendChild(tempDoc.CreateDocumentType("datafile", "-//Logiqx//DTD ROM Management Datafile//EN", "http://www.logiqx.com/Dats/datafile.dtd", null)); - tempDoc.AppendChild(outNode); - string outPath = Path.GetFileNameWithoutExtension(_filename) + ".new" + Path.GetExtension(_filename); - File.WriteAllText(outPath, Style.Beautify(tempDoc)); + logger.Close(); } } }