SabreDAT!

This commit creates output that is compatible with the new SabreDAT format, created by me and inspired by Logiqx XML DATs and the SuperDAT format. It uses a file-folder structure instead of rom-game structure, making it more versitile.  It still cannot be read in currently, though it would be read in as a SuperDAT since it is the closest equivalent (so all non-file paths will be part of the game). Also, finding which type of XML DAT it is will be a bit difficult, so detection will have to improve.
This commit is contained in:
Matt Nadareski
2016-05-18 22:22:49 -07:00
parent 690b2628f6
commit 1006e36712
5 changed files with 134 additions and 14 deletions

View File

@@ -56,6 +56,7 @@ namespace SabreTools
convertMiss = false, convertMiss = false,
convertCMP = false, convertCMP = false,
convertRC = false, convertRC = false,
convertSD = false,
convertXml = false, convertXml = false,
dedup = false, dedup = false,
diff = false, diff = false,
@@ -127,6 +128,10 @@ namespace SabreTools
case "--convert-rc": case "--convert-rc":
convertRC = true; convertRC = true;
break; break;
case "-cs":
case "--convert-sd":
convertSD = true;
break;
case "-cx": case "-cx":
case "--convert-xml": case "--convert-xml":
convertXml = true; convertXml = true;
@@ -310,7 +315,7 @@ namespace SabreTools
} }
// If more than one switch is enabled or help is set, show the help screen // If more than one switch is enabled or help is set, show the help screen
if (help || !(add ^ convertMiss ^ convertCMP ^ convertRC ^ convertXml ^ extsplit ^ generate ^ genall ^ if (help || !(add ^ convertMiss ^ convertCMP ^ convertRC ^ convertSD ^ convertXml ^ extsplit ^ generate ^ genall ^
import ^ listsrc ^ listsys ^ (merge || diff) ^ rem ^ trim)) import ^ listsrc ^ listsys ^ (merge || diff) ^ rem ^ trim))
{ {
Build.Help(); Build.Help();
@@ -319,7 +324,7 @@ namespace SabreTools
} }
// If a switch that requires a filename is set and no file is, show the help screen // If a switch that requires a filename is set and no file is, show the help screen
if (inputs.Count == 0 && (convertMiss || convertCMP || convertRC || convertXml || extsplit || import || (merge || diff) || trim)) if (inputs.Count == 0 && (convertMiss || convertCMP || convertRC || convertSD || convertXml || extsplit || import || (merge || diff) || trim))
{ {
Build.Help(); Build.Help();
logger.Close(); logger.Close();
@@ -388,6 +393,15 @@ namespace SabreTools
} }
} }
// Convert any DAT to SabreDAT
else if (convertSD)
{
foreach (string input in inputs)
{
InitConvert(input, OutputFormat.SabreDat, outdir);
}
}
// Convert any DAT to XML DAT // Convert any DAT to XML DAT
else if (convertXml) else if (convertXml)
{ {
@@ -652,10 +666,10 @@ Make a selection:
Make a selection: Make a selection:
1) Convert or clean DAT or folder of DATs 1) Convert or clean DAT or folder of DATs
3) Convert DAT to missfile 2) Convert DAT to missfile
4) Trim all entries in DAT and merge into a single game 3) Trim all entries in DAT and merge into a single game
5) Merge, diff, and/or dedup 2 or more DAT files 4) Merge, diff, and/or dedup 2 or more DAT files
6) Split DAT using 2 extensions 5) Split DAT using 2 extensions
B) Go back to the previous menu B) Go back to the previous menu
"); ");
Console.Write("Enter selection: "); Console.Write("Enter selection: ");
@@ -725,6 +739,7 @@ Make a selection:
1) Xml 1) Xml
2) ClrMamePro 2) ClrMamePro
3) RomCenter 3) RomCenter
4) SabreDAT
"); ");
Console.Write("Please enter your selection: "); Console.Write("Please enter your selection: ");
subsel = Console.ReadLine(); subsel = Console.ReadLine();
@@ -740,6 +755,9 @@ Make a selection:
case "3": case "3":
outputFormat = OutputFormat.RomCenter; outputFormat = OutputFormat.RomCenter;
break; break;
case "4":
outputFormat = OutputFormat.SabreDat;
break;
default: default:
subsel = ""; subsel = "";
break; break;
@@ -751,6 +769,8 @@ Make a selection:
InitConvert(input, outputFormat, outdir); InitConvert(input, outputFormat, outdir);
Console.Write("\nPress any key to continue..."); Console.Write("\nPress any key to continue...");
Console.ReadKey(); Console.ReadKey();
input = ""; outdir = "";
outputFormat = OutputFormat.Xml;
break; break;
} }
} }
@@ -1326,7 +1346,7 @@ Make a selection:
Roms = new Dictionary<string, List<RomData>>(), Roms = new Dictionary<string, List<RomData>>(),
MergeRoms = false, MergeRoms = false,
}; };
datdata = RomManipulation.Parse(filename, 0, 0, datdata, logger); datdata = RomManipulation.Parse(filename, 0, 0, datdata, logger, true);
// Sometimes the description doesn't match the filename, change this // Sometimes the description doesn't match the filename, change this
if (datdata.Description != Path.GetFileNameWithoutExtension(filename)) if (datdata.Description != Path.GetFileNameWithoutExtension(filename))
@@ -1335,7 +1355,8 @@ Make a selection:
} }
// If the extension matches, append ".new" to the filename // If the extension matches, append ".new" to the filename
if (outdir == "" && Path.GetExtension(filename) == (datdata.OutputFormat == OutputFormat.Xml ? ".xml" : ".dat")) string extension = (datdata.OutputFormat == OutputFormat.Xml || datdata.OutputFormat == OutputFormat.SabreDat ? ".xml" : ".dat");
if (outdir == "" && Path.GetExtension(filename) == extension)
{ {
datdata.Description += ".new"; datdata.Description += ".new";
} }
@@ -1365,7 +1386,7 @@ Make a selection:
Roms = new Dictionary<string, List<RomData>>(), Roms = new Dictionary<string, List<RomData>>(),
MergeRoms = false, MergeRoms = false,
}; };
datdata = RomManipulation.Parse(file, 0, 0, datdata, logger); datdata = RomManipulation.Parse(file, 0, 0, datdata, logger, true);
// Sometimes the description doesn't match the filename, change this // Sometimes the description doesn't match the filename, change this
if (datdata.Description != Path.GetFileNameWithoutExtension(file)) if (datdata.Description != Path.GetFileNameWithoutExtension(file))
@@ -1374,7 +1395,8 @@ Make a selection:
} }
// If the extension matches, append ".new" to the filename // If the extension matches, append ".new" to the filename
if (outdir == "" && Path.GetExtension(file) == (datdata.OutputFormat == OutputFormat.Xml ? ".xml" : ".dat")) string extension = (datdata.OutputFormat == OutputFormat.Xml || datdata.OutputFormat == OutputFormat.SabreDat ? ".xml" : ".dat");
if (outdir == "" && Path.GetExtension(file) == extension)
{ {
datdata.Description += ".new"; datdata.Description += ".new";
} }

View File

@@ -98,6 +98,8 @@ Options:
-ae=, --add-ext= Add an extension to each item -ae=, --add-ext= Add an extension to each item
-re=, --rep-ext= Replace all extensions with specified -re=, --rep-ext= Replace all extensions with specified
-ro, --romba Output roms in Romba format (requires SHA-1) -ro, --romba Output roms in Romba format (requires SHA-1)
-cs, --convert-sd Convert any DAT to SabreDAT
-out= Output directory
-cr, --convert-rc Convert any DAT to RomCenter -cr, --convert-rc Convert any DAT to RomCenter
-out= Output directory -out= Output directory
-cx, --convert-xml Convert any DAT to XML -cx, --convert-xml Convert any DAT to XML

View File

@@ -104,5 +104,6 @@ namespace SabreTools.Helper
RomCenter, RomCenter,
DOSCenter, DOSCenter,
MissFile, MissFile,
SabreDat,
} }
} }

View File

@@ -72,11 +72,12 @@ namespace SabreTools.Helper
Directory.CreateDirectory(outDir); Directory.CreateDirectory(outDir);
// (currently uses current time, change to "last updated time") // (currently uses current time, change to "last updated time")
logger.User("Opening file for writing: " + outDir + datdata.Description + (datdata.OutputFormat == OutputFormat.Xml ? ".xml" : ".dat")); string extension = (datdata.OutputFormat == OutputFormat.Xml || datdata.OutputFormat == OutputFormat.SabreDat ? ".xml" : ".dat");
logger.User("Opening file for writing: " + outDir + datdata.Description + extension);
try try
{ {
FileStream fs = File.Create(outDir + datdata.Description + (datdata.OutputFormat == OutputFormat.Xml ? ".xml" : ".dat")); FileStream fs = File.Create(outDir + datdata.Description + extension);
StreamWriter sw = new StreamWriter(fs, Encoding.UTF8); StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
string header = ""; string header = "";
@@ -108,6 +109,26 @@ namespace SabreTools.Helper
"version=" + HttpUtility.HtmlEncode(datdata.Description) + "\n" + "version=" + HttpUtility.HtmlEncode(datdata.Description) + "\n" +
"[GAMES]\n"; "[GAMES]\n";
break; break;
case OutputFormat.SabreDat:
header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!DOCTYPE datafile PUBLIC \"-//Logiqx//DTD ROM Management Datafile//EN\" \"http://www.logiqx.com/Dats/datafile.dtd\">\n\n" +
"<datafile>\n" +
"\t<header>\n" +
"\t\t<name>" + HttpUtility.HtmlEncode(datdata.Name) + "</name>\n" +
"\t\t<description>" + HttpUtility.HtmlEncode(datdata.Description) + "</description>\n" +
"\t\t<category>" + HttpUtility.HtmlEncode(datdata.Category) + "</category>\n" +
"\t\t<version>" + HttpUtility.HtmlEncode(datdata.Version) + "</version>\n" +
"\t\t<date>" + HttpUtility.HtmlEncode(datdata.Date) + "</date>\n" +
"\t\t<author>" + HttpUtility.HtmlEncode(datdata.Author) + "</author>\n" +
"\t\t<comment>" + HttpUtility.HtmlEncode(datdata.Comment) + "</comment>\n" +
(datdata.Type != null && datdata.Type != "" && datdata.ForcePacking != ForcePacking.Unzip ?
"\t\t<flags>\n" +
(datdata.Type != null && datdata.Type != "" ? "\t\t\t<flag name=\"type\" value=\"" + datdata.Type + "\"/>\n" : "") +
(datdata.ForcePacking == ForcePacking.Unzip ? "\t\t\t<flag name=\"forcepacking\" value=\"unzip\"/>\n" : "") +
"\t\t</flags>\n" : "") +
"\t</header>\n" +
"\t<data>\n";
break;
case OutputFormat.Xml: case OutputFormat.Xml:
header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!DOCTYPE datafile PUBLIC \"-//Logiqx//DTD ROM Management Datafile//EN\" \"http://www.logiqx.com/Dats/datafile.dtd\">\n\n" + "<!DOCTYPE datafile PUBLIC \"-//Logiqx//DTD ROM Management Datafile//EN\" \"http://www.logiqx.com/Dats/datafile.dtd\">\n\n" +
@@ -130,12 +151,17 @@ namespace SabreTools.Helper
sw.Write(header); sw.Write(header);
// Write out each of the machines and roms // Write out each of the machines and roms
int depth = 2, last = -1;
string lastgame = null; string lastgame = null;
List<string> splitpath = new List<string>();
foreach (List<RomData> roms in sortable.Values) foreach (List<RomData> roms in sortable.Values)
{ {
foreach (RomData rom in roms) foreach (RomData rom in roms)
{ {
string state = ""; string state = "";
List<string> newsplit = rom.Game.Split('\\').ToList();
// If we have a different game and we're not at the start of the list, output the end of last item
if (lastgame != null && lastgame.ToLowerInvariant() != rom.Game.ToLowerInvariant()) if (lastgame != null && lastgame.ToLowerInvariant() != rom.Game.ToLowerInvariant())
{ {
switch (datdata.OutputFormat) switch (datdata.OutputFormat)
@@ -143,12 +169,43 @@ namespace SabreTools.Helper
case OutputFormat.ClrMamePro: case OutputFormat.ClrMamePro:
state += ")\n"; state += ")\n";
break; break;
case OutputFormat.SabreDat:
if (splitpath != null)
{
for (int i = 0; i < newsplit.Count && i < splitpath.Count; i++)
{
// Always keep track of the last seen item
last = i;
// If we find a difference, break
if (newsplit[i] != splitpath[i])
{
break;
}
}
// Now that we have the last known position, take down all open folders
for (int i = depth - 1; i > last + 1; i--)
{
// Print out the number of tabs and the end folder
for (int j = 0; j < i; j++)
{
state += "\t";
}
state += "</folder>\n";
}
// Reset the current depth
depth = 2 + last;
}
break;
case OutputFormat.Xml: case OutputFormat.Xml:
state += "\t</machine>\n"; state += "\t</machine>\n";
break; break;
} }
} }
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.Game.ToLowerInvariant()) if (lastgame == null || lastgame.ToLowerInvariant() != rom.Game.ToLowerInvariant())
{ {
switch (datdata.OutputFormat) switch (datdata.OutputFormat)
@@ -157,6 +214,18 @@ namespace SabreTools.Helper
state += "game (\n\tname \"" + rom.Game + "\"\n" + state += "game (\n\tname \"" + rom.Game + "\"\n" +
"\tdescription \"" + rom.Game + "\"\n"; "\tdescription \"" + rom.Game + "\"\n";
break; break;
case OutputFormat.SabreDat:
for (int i = (last == -1 ? 0 : last); i < newsplit.Count; i++)
{
for (int j = 0; j < depth - last + i - (lastgame == null ? 1 : 0); j++)
{
state += "\t";
}
state += "<folder name=\"" + HttpUtility.HtmlEncode(newsplit[i]) + "\" description=\"" +
HttpUtility.HtmlEncode(newsplit[i]) + "\">\n";
}
depth = depth - (last == -1 ? 0 : last) + newsplit.Count;
break;
case OutputFormat.Xml: case OutputFormat.Xml:
state += "\t<machine name=\"" + HttpUtility.HtmlEncode(rom.Game) + "\">\n" + state += "\t<machine name=\"" + HttpUtility.HtmlEncode(rom.Game) + "\">\n" +
"\t\t<description>" + HttpUtility.HtmlEncode(rom.Game) + "</description>\n"; "\t\t<description>" + HttpUtility.HtmlEncode(rom.Game) + "</description>\n";
@@ -229,6 +298,19 @@ namespace SabreTools.Helper
"¬" + rom.CRC.ToLowerInvariant() + "¬" + rom.CRC.ToLowerInvariant() +
"¬" + (rom.Size != -1 ? rom.Size.ToString() : "") + "¬¬¬\n"; "¬" + (rom.Size != -1 ? rom.Size.ToString() : "") + "¬¬¬\n";
break; break;
case OutputFormat.SabreDat:
for (int i = 0; i < depth; i++)
{
state += "\t";
}
state += "<file type=\"" + rom.Type + "\" name=\"" + HttpUtility.HtmlEncode(rom.Name) + "\"" +
(rom.Size != -1 ? " size=\"" + rom.Size + "\"" : "") +
(rom.CRC != "" ? " crc=\"" + rom.CRC.ToLowerInvariant() + "\"" : "") +
(rom.MD5 != "" ? " md5=\"" + rom.MD5.ToLowerInvariant() + "\"" : "") +
(rom.SHA1 != "" ? " sha1=\"" + rom.SHA1.ToLowerInvariant() + "\"" : "") +
(rom.Nodump ? " status=\"nodump\"" : "") +
"/>\n";
break;
case OutputFormat.Xml: case OutputFormat.Xml:
state += "\t\t<" + rom.Type + " name=\"" + HttpUtility.HtmlEncode(rom.Name) + "\"" + state += "\t\t<" + rom.Type + " name=\"" + HttpUtility.HtmlEncode(rom.Name) + "\"" +
(rom.Size != -1 ? " size=\"" + rom.Size + "\"" : "") + (rom.Size != -1 ? " size=\"" + rom.Size + "\"" : "") +
@@ -240,6 +322,7 @@ namespace SabreTools.Helper
break; break;
} }
splitpath = newsplit;
lastgame = rom.Game; lastgame = rom.Game;
sw.Write(state); sw.Write(state);
@@ -252,6 +335,18 @@ namespace SabreTools.Helper
case OutputFormat.ClrMamePro: case OutputFormat.ClrMamePro:
footer = ")"; footer = ")";
break; break;
case OutputFormat.SabreDat:
for (int i = depth; i >= 2; i--)
{
// Print out the number of tabs and the end folder
for (int j = 0; j < i; j++)
{
footer += "\t";
}
footer += "</folder>\n";
}
footer += "\t</data>\n</datafile>";
break;
case OutputFormat.Xml: case OutputFormat.Xml:
footer = "\t</machine>\n</datafile>"; footer = "\t</machine>\n</datafile>";
break; break;

View File

@@ -98,7 +98,7 @@ namespace SabreTools.Helper
/// <param name="datdata">The DatData object representing found roms to this point</param> /// <param name="datdata">The DatData object representing found roms to this point</param>
/// <param name="logger">Logger object for console and/or file output</param> /// <param name="logger">Logger object for console and/or file output</param>
/// <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) public static DatData Parse(string filename, int sysid, int srcid, DatData datdata, Logger logger, bool keep = false)
{ {
XmlTextReader xtr = GetXmlTextReader(filename, logger); XmlTextReader xtr = GetXmlTextReader(filename, logger);
bool superdat = false, shouldbreak = false; bool superdat = false, shouldbreak = false;
@@ -270,7 +270,7 @@ namespace SabreTools.Helper
tempname = xtr.GetAttribute("name"); tempname = xtr.GetAttribute("name");
} }
if (superdat) if (superdat && !keep)
{ {
tempname = Regex.Match(tempname, @".*?\\(.*)").Groups[1].Value; tempname = Regex.Match(tempname, @".*?\\(.*)").Groups[1].Value;
} }