Enable SabreDAT read-in and fix output

Additionally, fix the necessity for blank strings in DatData definitions for read-in. Now if it's null it'll try writing to it as well.
This commit is contained in:
Matt Nadareski
2016-05-18 23:51:54 -07:00
parent 1006e36712
commit e0b4b13bcd
6 changed files with 285 additions and 86 deletions

View File

@@ -1332,16 +1332,6 @@ Make a selection:
logger.User("Converting \"" + Path.GetFileName(filename) + "\""); logger.User("Converting \"" + Path.GetFileName(filename) + "\"");
DatData datdata = new DatData DatData datdata = new DatData
{ {
Name = "",
Description = "",
Category = "",
Version = "",
Date = "",
Author = "",
Email = "",
Homepage = "",
Url = "",
Comment = "",
OutputFormat = outputFormat, OutputFormat = outputFormat,
Roms = new Dictionary<string, List<RomData>>(), Roms = new Dictionary<string, List<RomData>>(),
MergeRoms = false, MergeRoms = false,
@@ -1372,16 +1362,6 @@ Make a selection:
logger.User("Converting \"" + Path.GetFullPath(file).Remove(0, filename.Length + 1) + "\""); logger.User("Converting \"" + Path.GetFullPath(file).Remove(0, filename.Length + 1) + "\"");
DatData datdata = new DatData DatData datdata = new DatData
{ {
Name = "",
Description = "",
Category = "",
Version = "",
Date = "",
Author = "",
Email = "",
Homepage = "",
Url = "",
Comment = "",
OutputFormat = outputFormat, OutputFormat = outputFormat,
Roms = new Dictionary<string, List<RomData>>(), Roms = new Dictionary<string, List<RomData>>(),
MergeRoms = false, MergeRoms = false,
@@ -1440,16 +1420,6 @@ Make a selection:
logger.User("Converting " + input); logger.User("Converting " + input);
DatData datdata = new DatData DatData datdata = new DatData
{ {
Name = "",
Description = "",
Category = "",
Version = "",
Date = "",
Author = "",
Email = "",
Homepage = "",
Url = "",
Comment = "",
Roms = new Dictionary<string, List<RomData>>(), Roms = new Dictionary<string, List<RomData>>(),
OutputFormat = OutputFormat.MissFile, OutputFormat = OutputFormat.MissFile,

View File

@@ -59,16 +59,6 @@ namespace SabreTools
// Create the initial DatData object // Create the initial DatData object
DatData datdata = new DatData DatData datdata = new DatData
{ {
Name = "",
Description = "",
Category = "",
Version = "",
Date = "",
Author = "",
Email = "",
Homepage = "",
Url = "",
Comment = "",
Roms = new Dictionary<string, List<RomData>>(), Roms = new Dictionary<string, List<RomData>>(),
}; };

View File

@@ -85,16 +85,6 @@ namespace SabreTools
{ {
DatData datdata = new DatData DatData datdata = new DatData
{ {
Name = "",
Description = "",
Category = "",
Version = "",
Date = "",
Author = "",
Email = "",
Homepage = "",
Url = "",
Comment = "",
Roms = new Dictionary<string, List<RomData>>(), Roms = new Dictionary<string, List<RomData>>(),
ForcePacking = (_forceunpack ? ForcePacking.Unzip : ForcePacking.None), ForcePacking = (_forceunpack ? ForcePacking.Unzip : ForcePacking.None),
OutputFormat = RomManipulation.GetOutputFormat(filename), OutputFormat = RomManipulation.GetOutputFormat(filename),

View File

@@ -20,7 +20,7 @@ namespace SabreTools.Helper
private static string _endPatternCMP = @"^\s*\)\s*$"; private static string _endPatternCMP = @"^\s*\)\s*$";
/// <summary> /// <summary>
/// Convert a ClrMamePro style DAT to an XML derived DAT /// Convert a ClrMamePro style DAT to an Logiqx XML derived DAT
/// </summary> /// </summary>
/// <param name="filecontents">Array of strings representing the input file</param> /// <param name="filecontents">Array of strings representing the input file</param>
/// <returns>XElement representing the output XML DAT file</returns> /// <returns>XElement representing the output XML DAT file</returns>
@@ -160,7 +160,7 @@ namespace SabreTools.Helper
} }
/// <summary> /// <summary>
/// Convert a RomCenter style DAT to an XML derived DAT /// Convert a RomCenter style DAT to an Logiqx XML derived DAT
/// </summary> /// </summary>
/// <param name="filecontents">Array of strings representing the input file</param> /// <param name="filecontents">Array of strings representing the input file</param>
/// <returns>XElement representing the output XML DAT file</returns> /// <returns>XElement representing the output XML DAT file</returns>

View File

@@ -192,7 +192,7 @@ namespace SabreTools.Helper
{ {
state += "\t"; state += "\t";
} }
state += "</folder>\n"; state += "</directory>\n";
} }
// Reset the current depth // Reset the current depth
@@ -221,7 +221,7 @@ namespace SabreTools.Helper
{ {
state += "\t"; state += "\t";
} }
state += "<folder name=\"" + HttpUtility.HtmlEncode(newsplit[i]) + "\" description=\"" + state += "<directory name=\"" + HttpUtility.HtmlEncode(newsplit[i]) + "\" description=\"" +
HttpUtility.HtmlEncode(newsplit[i]) + "\">\n"; HttpUtility.HtmlEncode(newsplit[i]) + "\">\n";
} }
depth = depth - (last == -1 ? 0 : last) + newsplit.Count; depth = depth - (last == -1 ? 0 : last) + newsplit.Count;
@@ -336,14 +336,14 @@ namespace SabreTools.Helper
footer = ")"; footer = ")";
break; break;
case OutputFormat.SabreDat: case OutputFormat.SabreDat:
for (int i = depth; i >= 2; i--) for (int i = depth - 1; i >= 2; i--)
{ {
// Print out the number of tabs and the end folder // Print out the number of tabs and the end folder
for (int j = 0; j < i; j++) for (int j = 0; j < i; j++)
{ {
footer += "\t"; footer += "\t";
} }
footer += "</folder>\n"; footer += "</directory>\n";
} }
footer += "\t</data>\n</datafile>"; footer += "\t</data>\n</datafile>";
break; break;

View File

@@ -100,31 +100,40 @@ namespace SabreTools.Helper
/// <returns>DatData object representing the read-in data</returns> /// <returns>DatData object representing the read-in data</returns>
public static DatData Parse(string filename, int sysid, int srcid, DatData datdata, Logger logger, bool keep = false) public static DatData Parse(string filename, int sysid, int srcid, DatData datdata, Logger logger, bool keep = false)
{ {
// Prepare all internal variables
XmlReader subreader, headreader, flagreader;
bool superdat = false, shouldbreak = false, nodump = false;
string key = "", crc = "", md5 = "", sha1 = "";
long size = -1;
List<string> parent = new List<string>();
XmlTextReader xtr = GetXmlTextReader(filename, logger); XmlTextReader xtr = GetXmlTextReader(filename, logger);
bool superdat = false, shouldbreak = false;
string parent = "";
if (xtr != null) if (xtr != null)
{ {
xtr.MoveToContent(); xtr.MoveToContent();
while (xtr.NodeType != XmlNodeType.None) while (xtr.NodeType != XmlNodeType.None)
{ {
// If we have an end folder element, remove one item from the parent, if possible
if (xtr.NodeType == XmlNodeType.EndElement && xtr.Name == "directory" && parent.Count > 0)
{
parent.RemoveAt(parent.Count - 1);
}
// We only want elements // We only want elements
if (xtr.NodeType != XmlNodeType.Element) if (xtr.NodeType != XmlNodeType.Element)
{ {
xtr.Read(); if (xtr.Read())
continue; {
continue;
}
break;
} }
switch (xtr.Name) switch (xtr.Name)
{ {
case "datafile":
case "softwarelist":
parent = xtr.Name;
xtr.Read();
break;
case "header": case "header":
// We want to process the entire subtree of the header // We want to process the entire subtree of the header
XmlReader headreader = xtr.ReadSubtree(); headreader = xtr.ReadSubtree();
if (headreader != null) if (headreader != null)
{ {
@@ -143,48 +152,60 @@ namespace SabreTools.Helper
{ {
case "name": case "name":
content = headreader.ReadElementContentAsString(); ; content = headreader.ReadElementContentAsString(); ;
datdata.Name = (datdata.Name == "" ? content : datdata.Name); datdata.Name = (String.IsNullOrEmpty(datdata.Name) ? content : datdata.Name);
superdat = superdat || content.Contains(" - SuperDAT"); superdat = superdat || content.Contains(" - SuperDAT");
if (keep)
{
datdata.Type = (String.IsNullOrEmpty(datdata.Type) ? "SuperDAT" : datdata.Type);
}
break; break;
case "description": case "description":
content = headreader.ReadElementContentAsString(); content = headreader.ReadElementContentAsString();
datdata.Description = (datdata.Description == "" ? content : datdata.Description); datdata.Description = (String.IsNullOrEmpty(datdata.Description) ? content : datdata.Description);
break; break;
case "category": case "category":
content = headreader.ReadElementContentAsString(); content = headreader.ReadElementContentAsString();
datdata.Category = (datdata.Category == "" ? content : datdata.Category); datdata.Category = (String.IsNullOrEmpty(datdata.Category) ? content : datdata.Category);
break; break;
case "version": case "version":
content = headreader.ReadElementContentAsString(); content = headreader.ReadElementContentAsString();
datdata.Version = (datdata.Version == "" ? content : datdata.Version); datdata.Version = (String.IsNullOrEmpty(datdata.Version) ? content : datdata.Version);
break; break;
case "date": case "date":
content = headreader.ReadElementContentAsString(); content = headreader.ReadElementContentAsString();
datdata.Date = (datdata.Date == "" ? content : datdata.Date); datdata.Date = (String.IsNullOrEmpty(datdata.Date) ? content : datdata.Date);
break; break;
case "author": case "author":
content = headreader.ReadElementContentAsString(); content = headreader.ReadElementContentAsString();
datdata.Author = (datdata.Author == "" ? content : datdata.Author); datdata.Author = (String.IsNullOrEmpty(datdata.Author) ? content : datdata.Author);
// Special cases for SabreDAT
datdata.Email = (String.IsNullOrEmpty(datdata.Email) && !String.IsNullOrEmpty(headreader.GetAttribute("email")) ?
headreader.GetAttribute("email") : datdata.Email);
datdata.Homepage = (String.IsNullOrEmpty(datdata.Homepage) && !String.IsNullOrEmpty(headreader.GetAttribute("homepage")) ?
headreader.GetAttribute("homepage") : datdata.Email);
datdata.Url = (String.IsNullOrEmpty(datdata.Url) && !String.IsNullOrEmpty(headreader.GetAttribute("url")) ?
headreader.GetAttribute("url") : datdata.Email);
break; break;
case "email": case "email":
content = headreader.ReadElementContentAsString(); content = headreader.ReadElementContentAsString();
datdata.Email = (datdata.Email == "" ? content : datdata.Email); datdata.Email = (String.IsNullOrEmpty(datdata.Email) ? content : datdata.Email);
break; break;
case "homepage": case "homepage":
content = headreader.ReadElementContentAsString(); content = headreader.ReadElementContentAsString();
datdata.Homepage = (datdata.Homepage == "" ? content : datdata.Homepage); datdata.Homepage = (String.IsNullOrEmpty(datdata.Homepage) ? content : datdata.Homepage);
break; break;
case "url": case "url":
content = headreader.ReadElementContentAsString(); content = headreader.ReadElementContentAsString();
datdata.Url = (datdata.Url == "" ? content : datdata.Url); datdata.Url = (String.IsNullOrEmpty(datdata.Url) ? content : datdata.Url);
break; break;
case "comment": case "comment":
content = headreader.ReadElementContentAsString(); content = headreader.ReadElementContentAsString();
datdata.Comment = (datdata.Comment == "" ? content : datdata.Comment); datdata.Comment = (String.IsNullOrEmpty(datdata.Comment) ? content : datdata.Comment);
break; break;
case "type": case "type":
content = headreader.ReadElementContentAsString(); content = headreader.ReadElementContentAsString();
datdata.Type = (datdata.Type == "" ? content : datdata.Type); datdata.Type = (String.IsNullOrEmpty(datdata.Type) ? content : datdata.Type);
superdat = superdat || content.Contains("SuperDAT"); superdat = superdat || content.Contains("SuperDAT");
break; break;
case "clrmamepro": case "clrmamepro":
@@ -232,6 +253,82 @@ namespace SabreTools.Helper
} }
headreader.Read(); headreader.Read();
break; break;
case "flags":
flagreader = xtr.ReadSubtree();
if (flagreader != null)
{
while (!flagreader.EOF)
{
// We only want elements
if (flagreader.NodeType != XmlNodeType.Element || flagreader.Name == "flags")
{
flagreader.Read();
continue;
}
switch (flagreader.Name)
{
case "flag":
if (flagreader.GetAttribute("name") != null && flagreader.GetAttribute("value") != null)
{
content = flagreader.GetAttribute("value");
switch (flagreader.GetAttribute("name"))
{
case "type":
datdata.Type = (datdata.Type == "" ? content : datdata.Type);
superdat = superdat || content.Contains("SuperDAT");
break;
case "forcemerging":
switch (content)
{
case "split":
datdata.ForceMerging = ForceMerging.Split;
break;
case "none":
datdata.ForceMerging = ForceMerging.None;
break;
case "full":
datdata.ForceMerging = ForceMerging.Full;
break;
}
break;
case "forcenodump":
switch (content)
{
case "obsolete":
datdata.ForceNodump = ForceNodump.Obsolete;
break;
case "required":
datdata.ForceNodump = ForceNodump.Required;
break;
case "ignore":
datdata.ForceNodump = ForceNodump.Ignore;
break;
}
break;
case "forcepacking":
switch (content)
{
case "zip":
datdata.ForcePacking = ForcePacking.Zip;
break;
case "unzip":
datdata.ForcePacking = ForcePacking.Unzip;
break;
}
break;
}
}
flagreader.Read();
break;
default:
flagreader.Read();
break;
}
}
}
headreader.Skip();
break;
default: default:
headreader.Read(); headreader.Read();
break; break;
@@ -249,7 +346,7 @@ namespace SabreTools.Helper
string tempname = ""; string tempname = "";
// We want to process the entire subtree of the game // We want to process the entire subtree of the game
XmlReader subreader = xtr.ReadSubtree(); subreader = xtr.ReadSubtree();
if (subreader != null) if (subreader != null)
{ {
@@ -275,7 +372,6 @@ namespace SabreTools.Helper
tempname = Regex.Match(tempname, @".*?\\(.*)").Groups[1].Value; tempname = Regex.Match(tempname, @".*?\\(.*)").Groups[1].Value;
} }
string key = "";
while (subreader.Read()) while (subreader.Read())
{ {
// We only want elements // We only want elements
@@ -290,7 +386,7 @@ namespace SabreTools.Helper
case "rom": case "rom":
case "disk": case "disk":
// If the rom is nodump, flag it // If the rom is nodump, flag it
bool nodump = false; nodump = false;
if (xtr.GetAttribute("flags") == "nodump" || xtr.GetAttribute("status") == "nodump") if (xtr.GetAttribute("flags") == "nodump" || xtr.GetAttribute("status") == "nodump")
{ {
logger.Log("Nodump detected: " + logger.Log("Nodump detected: " +
@@ -299,7 +395,7 @@ namespace SabreTools.Helper
} }
// Take care of hex-sized files // Take care of hex-sized files
long size = -1; size = -1;
if (xtr.GetAttribute("size") != null && xtr.GetAttribute("size").Contains("0x")) if (xtr.GetAttribute("size") != null && xtr.GetAttribute("size").Contains("0x"))
{ {
size = Convert.ToInt64(xtr.GetAttribute("size"), 16); size = Convert.ToInt64(xtr.GetAttribute("size"), 16);
@@ -321,15 +417,15 @@ namespace SabreTools.Helper
} }
// Sanitize the hashes from null, hex sizes, and "true blank" strings // Sanitize the hashes from null, hex sizes, and "true blank" strings
string crc = (xtr.GetAttribute("crc") != null ? xtr.GetAttribute("crc").ToLowerInvariant().Trim() : ""); crc = (xtr.GetAttribute("crc") != null ? xtr.GetAttribute("crc").ToLowerInvariant().Trim() : "");
crc = (crc.StartsWith("0x") ? crc.Remove(0, 2) : crc); crc = (crc.StartsWith("0x") ? crc.Remove(0, 2) : crc);
crc = (crc == "-" ? "" : crc); crc = (crc == "-" ? "" : crc);
crc = (crc == "" ? "" : crc.PadLeft(8, '0')); crc = (crc == "" ? "" : crc.PadLeft(8, '0'));
string md5 = (xtr.GetAttribute("md5") != null ? xtr.GetAttribute("md5").ToLowerInvariant().Trim() : ""); md5 = (xtr.GetAttribute("md5") != null ? xtr.GetAttribute("md5").ToLowerInvariant().Trim() : "");
md5 = (md5.StartsWith("0x") ? md5.Remove(0, 2) : md5); md5 = (md5.StartsWith("0x") ? md5.Remove(0, 2) : md5);
md5 = (md5 == "-" ? "" : md5); md5 = (md5 == "-" ? "" : md5);
md5 = (md5 == "" ? "" : md5.PadLeft(32, '0')); md5 = (md5 == "" ? "" : md5.PadLeft(32, '0'));
string sha1 = (xtr.GetAttribute("sha1") != null ? xtr.GetAttribute("sha1").ToLowerInvariant().Trim() : ""); sha1 = (xtr.GetAttribute("sha1") != null ? xtr.GetAttribute("sha1").ToLowerInvariant().Trim() : "");
sha1 = (sha1.StartsWith("0x") ? sha1.Remove(0, 2) : sha1); sha1 = (sha1.StartsWith("0x") ? sha1.Remove(0, 2) : sha1);
sha1 = (sha1 == "-" ? "" : sha1); sha1 = (sha1 == "-" ? "" : sha1);
sha1 = (sha1 == "" ? "" : sha1.PadLeft(40, '0')); sha1 = (sha1 == "" ? "" : sha1.PadLeft(40, '0'));
@@ -353,9 +449,9 @@ namespace SabreTools.Helper
if (!(crc == "" && md5 == "" && sha1 == "") || nodump) if (!(crc == "" && md5 == "" && sha1 == "") || nodump)
{ {
// If we got to this point and it's a disk, log it because some tools don't like disks // If we got to this point and it's a disk, log it because some tools don't like disks
if (xtr.Name == "disk") if (subreader.Name == "disk")
{ {
logger.Log("Disk found: \"" + xtr.GetAttribute("name") + "\""); logger.Log("Disk found: \"" + subreader.GetAttribute("name") + "\"");
} }
// Get the new values to add // Get the new values to add
@@ -398,6 +494,159 @@ namespace SabreTools.Helper
shouldbreak = true; shouldbreak = true;
} }
break; break;
case "directory":
// Set SuperDAT flag for all SabreDAT inputs, regardless of depth
superdat = true;
if (keep)
{
datdata.Type = (datdata.Type == "" ? "SuperDAT" : datdata.Type);
}
string foldername = (xtr.GetAttribute("name") == null ? "" : xtr.GetAttribute("name"));
if (foldername != "")
{
parent.Add(foldername);
}
xtr.Read();
break;
case "file":
// If the rom is nodump, flag it
nodump = false;
flagreader = xtr.ReadSubtree();
if (flagreader != null)
{
while (!flagreader.EOF)
{
// We only want elements
if (flagreader.NodeType != XmlNodeType.Element || flagreader.Name == "flags")
{
flagreader.Read();
continue;
}
switch (flagreader.Name)
{
case "flag":
case "status":
if (flagreader.GetAttribute("name") != null && flagreader.GetAttribute("value") != null)
{
string content = flagreader.GetAttribute("value");
switch (flagreader.GetAttribute("name"))
{
case "nodump":
logger.Log("Nodump detected: " + (xtr.GetAttribute("name") != null && xtr.GetAttribute("name") != "" ?
"\"" + xtr.GetAttribute("name") + "\"" : "ROM NAME NOT FOUND"));
nodump = true;
break;
}
}
break;
}
flagreader.Read();
}
}
// Take care of hex-sized files
size = -1;
if (xtr.GetAttribute("size") != null && xtr.GetAttribute("size").Contains("0x"))
{
size = Convert.ToInt64(xtr.GetAttribute("size"), 16);
}
else if (xtr.GetAttribute("size") != null)
{
Int64.TryParse(xtr.GetAttribute("size"), out size);
}
// If the rom is continue or ignore, add the size to the previous rom
if (xtr.GetAttribute("loadflag") == "continue" || xtr.GetAttribute("loadflag") == "ignore")
{
int index = datdata.Roms[key].Count() - 1;
RomData lastrom = datdata.Roms[key][index];
lastrom.Size += size;
datdata.Roms[key].RemoveAt(index);
datdata.Roms[key].Add(lastrom);
continue;
}
// Sanitize the hashes from null, hex sizes, and "true blank" strings
crc = (xtr.GetAttribute("crc") != null ? xtr.GetAttribute("crc").ToLowerInvariant().Trim() : "");
crc = (crc.StartsWith("0x") ? crc.Remove(0, 2) : crc);
crc = (crc == "-" ? "" : crc);
crc = (crc == "" ? "" : crc.PadLeft(8, '0'));
md5 = (xtr.GetAttribute("md5") != null ? xtr.GetAttribute("md5").ToLowerInvariant().Trim() : "");
md5 = (md5.StartsWith("0x") ? md5.Remove(0, 2) : md5);
md5 = (md5 == "-" ? "" : md5);
md5 = (md5 == "" ? "" : md5.PadLeft(32, '0'));
sha1 = (xtr.GetAttribute("sha1") != null ? xtr.GetAttribute("sha1").ToLowerInvariant().Trim() : "");
sha1 = (sha1.StartsWith("0x") ? sha1.Remove(0, 2) : sha1);
sha1 = (sha1 == "-" ? "" : sha1);
sha1 = (sha1 == "" ? "" : sha1.PadLeft(40, '0'));
// If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info
if (xtr.GetAttribute("type") == "rom" && (size == 0 || size == -1) && ((crc == CRCZero || crc == "") || md5 == MD5Zero || sha1 == SHA1Zero))
{
size = SizeZero;
crc = CRCZero;
md5 = MD5Zero;
sha1 = SHA1Zero;
}
// If the file has no size and it's not the above case, skip and log
else if (xtr.GetAttribute("type") == "rom" && (size == 0 || size == -1))
{
logger.Warning("Incomplete entry for \"" + xtr.GetAttribute("name") + "\" will be output as nodump");
nodump = true;
}
// Get the name of the game from the parent
tempname = String.Join("\\", parent);
// If we have a SuperDAT and we aren't keeping names
if (superdat && !keep)
{
tempname = Regex.Match(tempname, @".*?\\(.*)").Groups[1].Value;
}
// Only add the rom if there's useful information in it
if (!(crc == "" && md5 == "" && sha1 == "") || nodump)
{
// If we got to this point and it's a disk, log it because some tools don't like disks
if (xtr.GetAttribute("type") == "disk")
{
logger.Log("Disk found: \"" + xtr.GetAttribute("name") + "\"");
}
// Get the new values to add
key = size + "-" + crc;
RomData value = new RomData
{
Game = tempname,
Name = xtr.GetAttribute("name"),
Type = xtr.GetAttribute("type"),
SystemID = sysid,
SourceID = srcid,
Size = size,
CRC = crc,
MD5 = md5,
SHA1 = sha1,
System = filename,
Nodump = nodump,
};
if (datdata.Roms.ContainsKey(key))
{
datdata.Roms[key].Add(value);
}
else
{
List<RomData> newvalue = new List<RomData>();
newvalue.Add(value);
datdata.Roms.Add(key, newvalue);
}
}
xtr.Read();
break;
default: default:
xtr.Read(); xtr.Read();
break; break;