mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Simplified importing DATs into the database by first converting all of them to XML and then having a unified parser. As a consequence of this, there is also the ability to directly convert one RV DAT to an equivalent XML DAT now.
This commit is contained in:
90
DATabase/Converters.cs
Normal file
90
DATabase/Converters.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace DATabase
|
||||
{
|
||||
class Converters
|
||||
{
|
||||
private static string _headerPattern = @"(^.*?) \($";
|
||||
private static string _romPattern = @"^\s+((?:rom)|(?:disk)) \( (name) ""(.*?)"" (?:(size) (.*?) )?(?:(crc) (.*?))?(?:(md5) (.*?) )?(?:(sha1) (.*?) )?\)";
|
||||
private static string _itemPattern = @"^\s+(.*?) ""(.*?)""";
|
||||
private static string _endPattern = @"^\s*\)\s*$";
|
||||
|
||||
public static XElement RomVaultToXML (string[] filecontents)
|
||||
{
|
||||
XElement elem = new XElement("datafile");
|
||||
|
||||
bool block = false;
|
||||
for (int k = 0; k < filecontents.Length; k++)
|
||||
{
|
||||
string line = filecontents[k];
|
||||
|
||||
// If the line is the header or a game
|
||||
if (Regex.IsMatch(line, _headerPattern))
|
||||
{
|
||||
GroupCollection gc = Regex.Match(line, _headerPattern).Groups;
|
||||
|
||||
if (gc[1].Value == "clrmamepro" || gc[1].Value == "romvault")
|
||||
{
|
||||
elem.Add(new XElement("header"));
|
||||
elem = elem.Elements("header").Last();
|
||||
}
|
||||
else
|
||||
{
|
||||
elem.Add(new XElement(gc[1].Value));
|
||||
elem = elem.Elements(gc[1].Value).Last();
|
||||
}
|
||||
|
||||
block = true;
|
||||
}
|
||||
|
||||
// If the line is a rom or disk and we're in a block
|
||||
else if (Regex.IsMatch(line, _romPattern) && block)
|
||||
{
|
||||
GroupCollection gc = Regex.Match(line, _romPattern).Groups;
|
||||
|
||||
XElement temp = new XElement(gc[1].Value);
|
||||
|
||||
// Loop over all attributes and add them if possible
|
||||
for (int i = 1; i < gc.Count; i++)
|
||||
{
|
||||
if (i + 2 < gc.Count)
|
||||
{
|
||||
temp.SetAttributeValue(gc[i+1].Value, gc[i+2].Value);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
elem.Add(new XElement(temp));
|
||||
}
|
||||
// If the line is anything but a rom or disk and we're in a block
|
||||
else if (Regex.IsMatch(line, _itemPattern) && block)
|
||||
{
|
||||
GroupCollection gc = Regex.Match(line, _itemPattern).Groups;
|
||||
|
||||
if (gc[1].Value == "name" && elem.Name != "header")
|
||||
{
|
||||
elem.SetAttributeValue(gc[1].Value, gc[2].Value);
|
||||
elem.Add(new XElement("description", gc[2].Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
elem.Add(new XElement(gc[1].Value, gc[2].Value));
|
||||
}
|
||||
}
|
||||
|
||||
// If we find an end bracket that's not associated with anything else, the block is done
|
||||
else if (Regex.IsMatch(line, _endPattern) && block)
|
||||
{
|
||||
block = false;
|
||||
elem = elem.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Converters.cs" />
|
||||
<Compile Include="Generate.cs" />
|
||||
<Compile Include="Importer.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
|
||||
@@ -258,143 +258,82 @@ namespace DATabase
|
||||
FileStream fs = File.OpenRead(_filepath);
|
||||
StreamReader sr = new StreamReader(fs);
|
||||
|
||||
Console.WriteLine("got here");
|
||||
|
||||
// Set necessary dat values
|
||||
string format = "";
|
||||
bool machinefound = false;
|
||||
string machinename = "";
|
||||
string description = "";
|
||||
long gameid = 0;
|
||||
bool comment = false;
|
||||
|
||||
// Parse the file for its rom information
|
||||
while (sr.Peek() > 0)
|
||||
XmlDocument doc = new XmlDocument();
|
||||
try
|
||||
{
|
||||
string line = sr.ReadLine();
|
||||
|
||||
// First each string has to be normalized
|
||||
line = Style.NormalizeChars(line);
|
||||
|
||||
// If the input style hasn't been set, set it according to the header
|
||||
if (format == "")
|
||||
{
|
||||
if (line.IndexOf("<?xml version=\"1.0\" encoding=\"utf-8\"?>") != -1)
|
||||
{
|
||||
format = "logiqx";
|
||||
doc.LoadXml(sr.ReadToEnd());
|
||||
}
|
||||
else if (line.IndexOf("clrmamepro (") != -1 || line.IndexOf("romvault (") != -1)
|
||||
catch (XmlException ex)
|
||||
{
|
||||
format = "romvault";
|
||||
}
|
||||
}
|
||||
else if (line.IndexOf("<!DOCTYPE softwarelist") != -1)
|
||||
{
|
||||
format = "softwarelist";
|
||||
doc.LoadXml(Converters.RomVaultToXML(File.ReadAllLines(_filepath)).ToString());
|
||||
}
|
||||
|
||||
// If there's an XML-style comment, stop the presses and skip until it's over
|
||||
else if (line.IndexOf("-->") != -1)
|
||||
// Experimental looping using only XML parsing
|
||||
XmlNode node = doc.FirstChild.FirstChild;
|
||||
if (node.Name == "header")
|
||||
{
|
||||
comment = false;
|
||||
}
|
||||
else if (line.IndexOf("<!--") != -1)
|
||||
{
|
||||
comment = true;
|
||||
node = node.NextSibling;
|
||||
}
|
||||
|
||||
// Process Logiqx XML-derived DATs
|
||||
else if(format == "logiqx" && !comment)
|
||||
while (node != null)
|
||||
{
|
||||
if (line.IndexOf("<machine") != -1 || line.IndexOf("<game") != -1)
|
||||
if (node.Name == "machine" || node.Name == "game" || node.Name == "software")
|
||||
{
|
||||
machinefound = true;
|
||||
long gameid = AddGame(sysid, node.Attributes["name"].Value, srcid);
|
||||
|
||||
XElement xml = XElement.Parse(line + (line.IndexOf("<machine") != -1 ? "</machine>" : "</game>"));
|
||||
machinename = xml.Attribute("name").Value;
|
||||
|
||||
gameid = AddGame(sysid, machinename, srcid);
|
||||
}
|
||||
else if (line.IndexOf("<rom") != -1 && machinefound)
|
||||
// Get the roms from the machine
|
||||
if (node.HasChildNodes)
|
||||
{
|
||||
AddRom(line, machinename, "rom", gameid, date);
|
||||
}
|
||||
else if (line.IndexOf("<disk") != -1 && machinefound)
|
||||
// If this node has children, traverse the children
|
||||
foreach (XmlNode child in node.ChildNodes)
|
||||
{
|
||||
AddRom(line, machinename, "disk", gameid, date);
|
||||
}
|
||||
else if (line.IndexOf("</machine>") != -1 || line.IndexOf("</game>") != -1)
|
||||
// If we find a rom or disk, add it
|
||||
if (child.Name == "rom" || child.Name == "disk")
|
||||
{
|
||||
machinefound = false;
|
||||
machinename = "";
|
||||
description = "";
|
||||
gameid = 0;
|
||||
AddRomHelper(
|
||||
child.Name,
|
||||
gameid,
|
||||
child.Attributes["name"].Value,
|
||||
date,
|
||||
(child.Attributes["size"].Value != "" ? Int32.Parse(child.Attributes["size"].Value) : -1),
|
||||
(child.Attributes["crc"].Value != "" ? child.Attributes["crc"].Value : ""),
|
||||
(child.Attributes["md5"].Value != "" ? child.Attributes["md5"].Value : ""),
|
||||
(child.Attributes["sha1"].Value != "" ? child.Attributes["sha1"].Value : "")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Process SoftwareList XML-derived DATs
|
||||
else if (format == "softwarelist" && !comment)
|
||||
// If we find the signs of a software list, traverse the children
|
||||
else if (child.Name == "part" && child.HasChildNodes)
|
||||
{
|
||||
if (line.IndexOf("<software ") != -1)
|
||||
foreach (XmlNode part in child.ChildNodes)
|
||||
{
|
||||
machinefound = true;
|
||||
}
|
||||
else if (line.IndexOf("<description") != -1 && machinefound)
|
||||
// If we find a dataarea, traverse the children
|
||||
if (part.Name == "dataarea")
|
||||
{
|
||||
XElement xml = XElement.Parse(line);
|
||||
machinename = xml.Value;
|
||||
gameid = AddGame(sysid, machinename, srcid);
|
||||
}
|
||||
else if (line.IndexOf("<rom") != -1 && machinefound)
|
||||
foreach (XmlNode data in part.ChildNodes)
|
||||
{
|
||||
AddRom(line, machinename, "rom", gameid, date);
|
||||
}
|
||||
else if (line.IndexOf("<disk") != -1 && machinefound)
|
||||
// If we find a rom or disk, add it
|
||||
if (data.Name == "rom" || data.Name == "disk")
|
||||
{
|
||||
AddRom(line, machinename, "disk", gameid, date);
|
||||
}
|
||||
else if (line.IndexOf("</software>") != -1)
|
||||
{
|
||||
machinefound = false;
|
||||
machinename = "";
|
||||
description = "";
|
||||
gameid = 0;
|
||||
AddRomHelper(
|
||||
data.Name,
|
||||
gameid,
|
||||
data.Attributes["name"].Value,
|
||||
date,
|
||||
(data.Attributes["size"].Value != "" ? Int32.Parse(data.Attributes["size"].Value) : -1),
|
||||
(data.Attributes["crc"].Value != "" ? data.Attributes["crc"].Value : ""),
|
||||
(data.Attributes["md5"].Value != "" ? data.Attributes["md5"].Value : ""),
|
||||
(data.Attributes["sha1"].Value != "" ? data.Attributes["sha1"].Value : "")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Process original style RomVault DATs
|
||||
else if (format == "romvault")
|
||||
{
|
||||
if (line.IndexOf("game") != -1 && !machinefound)
|
||||
{
|
||||
machinefound = true;
|
||||
}
|
||||
else if (line.IndexOf("rom (") != -1 && machinefound)
|
||||
{
|
||||
AddRomOld(line, machinename, "rom", gameid, date);
|
||||
}
|
||||
else if (line.IndexOf("disk (") != -1 && machinefound)
|
||||
{
|
||||
AddRomOld(line, machinename, "disk", gameid, date);
|
||||
}
|
||||
else if (line.IndexOf("name \"") != -1 && machinefound)
|
||||
{
|
||||
string machineNamePattern = "^\\s*name \"(.*)\"";
|
||||
Regex machineNameRegex = new Regex(machineNamePattern);
|
||||
Match machineNameMatch = machineNameRegex.Match(line);
|
||||
machinename = machineNameMatch.Groups[1].Value;
|
||||
|
||||
gameid = AddGame(sysid, machinename, srcid);
|
||||
}
|
||||
else if (line.IndexOf("description \"") == -1 && line.IndexOf(")") != -1)
|
||||
{
|
||||
machinefound = false;
|
||||
machinename = "";
|
||||
description = "";
|
||||
gameid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
node = node.NextSibling;
|
||||
}
|
||||
|
||||
sr.Close();
|
||||
fs.Close();
|
||||
@@ -464,57 +403,7 @@ namespace DATabase
|
||||
return gameid;
|
||||
}
|
||||
|
||||
private bool AddRom(string line, string machinename, string romtype, long gameid, string date)
|
||||
{
|
||||
XElement xml = XElement.Parse(line);
|
||||
|
||||
string name = (xml.Attribute("name") != null ? xml.Attribute("name").Value : "");
|
||||
int size = (xml.Attribute("size") != null ? Int32.Parse(xml.Attribute("size").Value) : -1);
|
||||
string crc = (xml.Attribute("crc") != null ? xml.Attribute("crc").Value : "");
|
||||
string md5 = (xml.Attribute("md5") != null ? xml.Attribute("md5").Value : "");
|
||||
string sha1 = (xml.Attribute("sha1") != null ? xml.Attribute("sha1").Value : "");
|
||||
|
||||
return AddRomHelper(machinename, romtype, gameid, name, date, size, crc, md5, sha1);
|
||||
}
|
||||
|
||||
private bool AddRomOld(string line, string machinename, string romtype, long gameid, string date)
|
||||
{
|
||||
string infoPattern = "name \"(.*)\"";
|
||||
Regex infoRegex = new Regex(infoPattern);
|
||||
Match infoMatch = infoRegex.Match(line);
|
||||
string name = infoMatch.Groups[1].Value;
|
||||
|
||||
string[] rominfo = line.Split(' ');
|
||||
int size = -1;
|
||||
string crc = "";
|
||||
string md5 = "";
|
||||
string sha1 = "";
|
||||
|
||||
string next = "";
|
||||
foreach (string info in rominfo)
|
||||
{
|
||||
if (info == "size" || info == "crc" || info == "md5" || info == "sha1")
|
||||
{
|
||||
next = info;
|
||||
}
|
||||
else if (next != "")
|
||||
{
|
||||
switch (next)
|
||||
{
|
||||
case "size": size = Int32.Parse(info); break;
|
||||
case "crc": crc = info; break;
|
||||
case "md5": md5 = info; break;
|
||||
case "sha1": sha1 = info; break;
|
||||
default: break;
|
||||
}
|
||||
next = "";
|
||||
}
|
||||
}
|
||||
|
||||
return AddRomHelper(machinename, romtype, gameid, name, date, size, crc, md5, sha1);
|
||||
}
|
||||
|
||||
private bool AddRomHelper(string machinename, string romtype, long gameid, string name, string date, int size, string crc, string md5, string sha1)
|
||||
private bool AddRomHelper(string romtype, long gameid, string name, string date, int size, string crc, string md5, string sha1)
|
||||
{
|
||||
// WOD origninally stripped out any subdirs from the imported files, we do the same
|
||||
name = Path.GetFileName(name);
|
||||
|
||||
@@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Data.SQLite;
|
||||
using System.IO;
|
||||
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace DATabase
|
||||
{
|
||||
class Program
|
||||
@@ -158,6 +160,36 @@ ORDER BY systems.manufacturer, systems.system";
|
||||
|
||||
break;
|
||||
|
||||
case "-c":
|
||||
case "--convert":
|
||||
// Check if there are enough arguments
|
||||
if (args.Length > 1)
|
||||
{
|
||||
// Check to see if the second argument is a file that exists
|
||||
if (args.Length > 1 && File.Exists(args[1]))
|
||||
{
|
||||
Console.WriteLine("Converting " + args[1]);
|
||||
XElement conv = Converters.RomVaultToXML(File.ReadAllLines(args[1]));
|
||||
FileStream fs = File.OpenWrite(Path.GetFileNameWithoutExtension(args[1]) + ".new.xml");
|
||||
StreamWriter sw = new StreamWriter(fs);
|
||||
sw.Write(conv);
|
||||
sw.Close();
|
||||
fs.Close();
|
||||
Console.WriteLine("Converted file: " + Path.GetFileNameWithoutExtension(args[1]) + ".new.xml");
|
||||
}
|
||||
// If it's invalid, show the help
|
||||
else
|
||||
{
|
||||
Help();
|
||||
}
|
||||
}
|
||||
// If there aren't enough arguments
|
||||
else
|
||||
{
|
||||
Help();
|
||||
}
|
||||
break;
|
||||
|
||||
// Invalid argument
|
||||
default:
|
||||
Help();
|
||||
@@ -264,9 +296,10 @@ Usage: DATabase <option> (<filename>|<dirname>) | (system=sy) (source=so)
|
||||
-g, --generate Start tool in generate mode
|
||||
-lso List all sources (id <= name)
|
||||
-lsy List all systems (id <= name)
|
||||
-c, --convert Convert a RV DAT to XML
|
||||
|
||||
If started in import mode, either a filename or directory
|
||||
name is required in order to run.
|
||||
If started in import or convert mode, either a filename
|
||||
or directory name is required in order to run.
|
||||
|
||||
If started in generate mode, here are the possible states:
|
||||
system blank, source blank Create MEGAMERGED
|
||||
|
||||
Reference in New Issue
Block a user