diff --git a/DATabase/DATabase.cs b/DATabase/DATabase.cs index 54662cdd..ec087ca1 100644 --- a/DATabase/DATabase.cs +++ b/DATabase/DATabase.cs @@ -1,6 +1,7 @@ using System; using System.Data.SQLite; using System.IO; +using System.Xml; using System.Xml.Linq; using SabreTools.Helper; @@ -50,7 +51,7 @@ namespace SabreTools } // Determine which switches are enabled (with values if necessary) - bool help = false, import = false, generate = false, convert = false, + bool help = false, import = false, generate = false, convertXml = false, convertRV = false, listsys = false, listsrc = false, norename = false, old = false, log = false, genall = false, add = false, rem = false, skip = false; string systems = "", sources = "", input = "", manu = "", url = "", outdir = ""; @@ -61,7 +62,8 @@ namespace SabreTools import = import || (arg == "-i" || arg == "--import"); generate = generate || (arg == "-g" || arg == "--generate"); genall = genall || (arg == "-ga" || arg == "--generate-all"); - convert = convert || (arg == "-c" || arg == "--convert"); + convertRV = convertRV || (arg == "-cr" || arg == "--convert-rv"); + convertXml = convertXml || (arg == "-cx" || arg == "--convert-xml"); listsys = listsys || (arg == "-lsy" || arg == "--list-systems"); listsrc = listsrc || (arg == "-lso" || arg == "--list-sources"); add = add || (arg == "-a" || arg == "--add"); @@ -99,7 +101,7 @@ namespace SabreTools } // If more than one switch is enabled or help is set, show the help screen - if (help || !(import ^ generate ^ listsys ^ listsrc ^ genall ^ add ^ rem)) + if (help || !(import ^ generate ^ listsys ^ listsrc ^ genall ^ add ^ rem ^ convertRV ^ convertXml)) { Help(); logger.Close(); @@ -141,10 +143,16 @@ namespace SabreTools ListSystems(); } - // Convert RV DAT to XML DAT - else if (convert) + // Convert XML DAT to RV DAT + else if (convertRV) { - InitConvert(input); + InitConvertRV(input); + } + + // Convert RV DAT to XML DAT + else if (convertXml) + { + InitConvertXML(input); } // Add a source or system @@ -219,10 +227,11 @@ Make a selection: 3) Generate a DAT file 4) Generate all DAT files 5) Convert a DAT file from RV to XML - 6) List all available sources - 7) List all available systems - 8) Add and Remove from database - 9) " + (logger.ToFile ? "Disable Logging" : "Enable Logging") + @" + 6) Convert a DAT file from XML to RV + 7) List all available sources + 8) List all available systems + 9) Add and Remove from database + 10) " + (logger.ToFile ? "Disable Logging" : "Enable Logging") + @" X) Exit Program "); Console.Write("Enter selection: "); @@ -243,26 +252,29 @@ Make a selection: GenerateAllMenu(); break; case "5": - ConvertMenu(); + ConvertXMLMenu(); break; case "6": + ConvertRVMenu(); + break; + case "7": Console.Clear(); PrintHeader(); ListSources(); Console.Write("\nPress any key to continue..."); Console.ReadKey(); break; - case "7": + case "8": Console.Clear(); PrintHeader(); ListSystems(); Console.Write("\nPress any key to continue..."); Console.ReadKey(); break; - case "8": + case "9": AddRemoveMenu(); break; - case "9": + case "10": logger.ToFile = !logger.ToFile; break; } @@ -295,7 +307,8 @@ Options: -ga, --generate-all Start tool in generate all mode -lso, --list-sources List all sources (id <= name) -lsy, --list-systems List all systems (id <= name) - -c, --convert Convert a RV DAT to XML + -cr, --convert-rv Convert an XML DAT to RV + -cx, --convert-xml Convert a RV DAT to XML A filename or folder is required to run -l, --log Enable logging of program output "); @@ -596,25 +609,25 @@ Make a selection: } /// - /// Show the text-based conversion menu + /// Show the text-based XML to RV conversion menu /// - private static void ConvertMenu() + private static void ConvertRVMenu() { string selection = ""; while (selection.ToLowerInvariant() != "b") { Console.Clear(); PrintHeader(); - Console.WriteLine(@"CONVERT MENU + Console.WriteLine(@"XML -> RV CONVERT MENU =========================== -Enter the name of a DAT file to convert from RV to XML +Enter the name of a DAT file to convert from XML to RV or 'b' to go back to the previous menu: "); selection = Console.ReadLine(); if (selection.ToLowerInvariant() != "b") { Console.Clear(); - InitConvert(selection); + InitConvertXML(selection); Console.Write("\nPress any key to continue..."); Console.ReadKey(); } @@ -623,10 +636,70 @@ or 'b' to go back to the previous menu: } /// - /// Wrap converting DAT file from RomValut to XML + /// Wrap converting DAT file from XML to RomVault /// /// - private static void InitConvert(string filename) + private static void InitConvertRV(string filename) + { + if (File.Exists(filename)) + { + Console.WriteLine("Converting " + filename); + XmlDocument doc = new XmlDocument(); + try + { + doc.LoadXml(File.ReadAllText(filename)); + string conv = Converters.XMLToRomVault(doc); + FileStream fs = File.OpenWrite(Path.GetFileNameWithoutExtension(filename) + ".new.dat"); + StreamWriter sw = new StreamWriter(fs); + sw.Write(conv); + sw.Close(); + fs.Close(); + Console.WriteLine("Converted file: " + Path.GetFileNameWithoutExtension(filename) + ".new.dat"); + } + catch (XmlException ex) + { + logger.Warning("The file " + filename + " could not be parsed as an XML file."); + } + } + else + { + Console.WriteLine("I'm sorry but " + filename + "doesn't exist!"); + } + return; + } + + /// + /// Show the text-based RV to XML conversion menu + /// + private static void ConvertXMLMenu() + { + string selection = ""; + while (selection.ToLowerInvariant() != "b") + { + Console.Clear(); + PrintHeader(); + Console.WriteLine(@"RV -> XML CONVERT MENU +=========================== +Enter the name of a DAT file to convert from RV to XML +or 'b' to go back to the previous menu: +"); + selection = Console.ReadLine(); + if (selection.ToLowerInvariant() != "b") + { + Console.Clear(); + InitConvertXML(selection); + Console.Write("\nPress any key to continue..."); + Console.ReadKey(); + } + } + return; + } + + /// + /// Wrap converting DAT file from RomVault to XML + /// + /// + private static void InitConvertXML(string filename) { if (File.Exists(filename)) { diff --git a/DATabase/Helper/Converters.cs b/DATabase/Helper/Converters.cs index 7af929a5..4d597478 100644 --- a/DATabase/Helper/Converters.cs +++ b/DATabase/Helper/Converters.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Text.RegularExpressions; +using System.Xml; using System.Xml.Linq; namespace SabreTools.Helper @@ -138,5 +139,119 @@ namespace SabreTools.Helper return elem; } - } + + /// + /// Convert an XML derived DAT to a RomVault style DAT + /// + /// XElement representing the file + /// String representing the output RomVault DAT file + public static String XMLToRomVault(XmlDocument root) + { + string output = ""; + + // Experimental looping using only XML parsing + XmlNode node = root.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; + } + + // Read the header if it exists + if (node != null && node.Name == "header") + { + output += "clrmamepro ("; + + XmlNode child = node.FirstChild; + while (child != null) + { + output += "\n\t" + child.Name + " \"" + child.InnerText + "\""; + child = child.NextSibling; + } + output += "\n)"; + + // 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")) + { + // There are rare cases where a malformed XML will not have the required attributes. We can only skip them. + if (node.Attributes.Count == 0) + { + node = node.NextSibling; + continue; + } + + output += "\ngame (\n\tname \"" + node.Attributes["name"].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 (node.NodeType == XmlNodeType.Element && (child.Name == "rom" || child.Name == "disk")) + { + output += "\n\t" + child.Name + " ( name \"" + child.Attributes["name"].Value + "\"" + + (child.Attributes["size"] != null ? " size " + Int32.Parse(child.Attributes["size"].Value) : "") + + (child.Attributes["crc"] != null ? " crc " + child.Attributes["crc"].Value.ToLowerInvariant().Trim() : "") + + (child.Attributes["md5"] != null ? " md5 " + child.Attributes["md5"].Value.ToLowerInvariant().Trim() : "") + + (child.Attributes["sha1"] != null ? " sha1 " + 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) + { + output += "\n\t" + data.Name + " ( name \"" + data.Attributes["name"].Value + + (data.Attributes["size"] != null ? " size " + Int32.Parse(data.Attributes["size"].Value) : "") + + (data.Attributes["crc"] != null ? " crc " + data.Attributes["crc"].Value.ToLowerInvariant().Trim() : "") + + (data.Attributes["md5"] != null ? " md5 " + data.Attributes["md5"].Value.ToLowerInvariant().Trim() : "") + + (data.Attributes["sha1"] != null ? " sha1 " + data.Attributes["sha1"].Value.ToLowerInvariant().Trim() : "") + " )"; + } + } + } + } + } + else + { + output += "\n\t" + child.Name + " \"" + child.InnerText + "\""; + } + } + } + output += "\n)"; + } + node = node.NextSibling; + } + + Console.WriteLine(output); + Console.Read(); + + return output; + } + } }