Cleanup and overhaul (#21)

* Syntax cleanup

* More minor cleanup, use Linq

* Fix broken features by using correct values

* Feature flags the same

* Features are modular

* No AlphaFS, more .NET versions

* Fix appveyor

* Put back identifiers, for some reason

* String interpolation, modernization

* Better use of GetField

* XmlTextWriter to remove possible issues

* Fix header for OpenMSX
This commit is contained in:
Matt Nadareski
2020-06-10 22:37:19 -07:00
committed by GitHub
parent f01e47444c
commit 4ad77d6be6
75 changed files with 6945 additions and 7249 deletions

View File

@@ -1,19 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamReader = System.IO.StreamReader;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -119,13 +111,13 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
@@ -161,16 +153,14 @@ namespace SabreTools.Library.DatFiles
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != item.MachineName.ToLowerInvariant())
{
WriteDatItem(sw, item, ignoreblanks);
}
// If we have a "null" game (created by DATFromDir or something similar), log it to file
if (item.ItemType == ItemType.Rom
&& ((Rom)item).Size == -1
&& ((Rom)item).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", item.MachineName);
Globals.Logger.Verbose($"Empty folder found: {item.MachineName}");
item.Name = (item.Name == "null" ? "-" : item.Name);
((Rom)item).Size = Constants.SizeZero;
@@ -181,7 +171,7 @@ namespace SabreTools.Library.DatFiles
}
}
Globals.Logger.Verbose("File written!" + Environment.NewLine);
Globals.Logger.Verbose($"File written!{Environment.NewLine}");
sw.Dispose();
fs.Dispose();
}
@@ -222,44 +212,42 @@ namespace SabreTools.Library.DatFiles
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(StreamWriter sw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && (((Rom)datItem).Size == 0 || ((Rom)datItem).Size == -1)))
return true;
}
try
{
// No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{
rom.MachineName = rom.MachineName.Substring(1);
}
datItem.MachineName = datItem.MachineName.TrimStart(Path.DirectorySeparatorChar);
string state = (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName : "") + ";"
+ (!ExcludeFields[(int)Field.Description] ? rom.MachineDescription : "") + ";"
+ FileName + ";"
+ (!ExcludeFields[(int)Field.CloneOf] ? rom.CloneOf : "") + ";"
+ (!ExcludeFields[(int)Field.Year] ? rom.Year : "") + ";"
+ (!ExcludeFields[(int)Field.Manufacturer] ? rom.Manufacturer : "") + ";"
/* + rom.Category */ + ";"
/* + rom.Players */ + ";"
/* + rom.Rotation */ + ";"
/* + rom.Control */ + ";"
/* + rom.Status */ + ";"
/* + rom.DisplayCount */ + ";"
/* + rom.DisplayType */ + ";"
/* + rom.AltRomname */ + ";"
/* + rom.AltTitle */ + ";"
+ (!ExcludeFields[(int)Field.Comment] ? rom.Comment : "") + ";"
/* + rom.Buttons */ + "\n";
// Pre-process the item name
ProcessItemName(datItem, true);
string state = string.Empty;
state += $"{datItem.GetField(Field.MachineName, ExcludeFields)};";
state += $"{datItem.GetField(Field.Description, ExcludeFields)};";
state += $"{FileName};";
state += $"{datItem.GetField(Field.CloneOf, ExcludeFields)};";
state += $"{datItem.GetField(Field.Year, ExcludeFields)};";
state += $"{datItem.GetField(Field.Manufacturer, ExcludeFields)};";
state += ";"; // $"{datItem.GetField(Field.Category, ExcludeFields)};";
state += ";"; // $"{datItem.GetField(Field.Players, ExcludeFields)};";
state += ";"; // $"{datItem.GetField(Field.Rotation, ExcludeFields)};";
state += ";"; // $"{datItem.GetField(Field.Control, ExcludeFields)};";
state += ";"; // $"{datItem.GetField(Field.Status, ExcludeFields)};";
state += ";"; // $"{datItem.GetField(Field.DisplayCount, ExcludeFields)};";
state += ";"; // $"{datItem.GetField(Field.DisplayType, ExcludeFields)};";
state += ";"; // $"{datItem.GetField(Field.AltRomname, ExcludeFields)};";
state += ";"; // $"{datItem.GetField(Field.AltTitle, ExcludeFields)};";
state += $"{datItem.GetField(Field.Comment, ExcludeFields)};";
state += ";"; // $"{datItem.GetField(Field.Buttons, ExcludeFields)};";
sw.Write(state);
sw.Flush();

View File

@@ -1,20 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamReader = System.IO.StreamReader;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -64,9 +56,7 @@ namespace SabreTools.Library.DatFiles
// Comments in CMP DATs start with a #
if (line.Trim().StartsWith("#"))
{
continue;
}
// If the line is the header or a game
if (Regex.IsMatch(line, Constants.HeaderPatternCMP))
@@ -86,11 +76,11 @@ namespace SabreTools.Library.DatFiles
|| normalizedValue == "game" // Used by most CMP DATs
|| normalizedValue == "machine") // Possibly used by MAME CMP DATs
{
ReadSet(sr, false, filename, sysid, srcid, keep, clean, remUnicode);
ReadSet(sr, false, filename, sysid, srcid, clean, remUnicode);
}
else if (normalizedValue == "resource") // Used by some other DATs to denote a BIOS set
{
ReadSet(sr, true, filename, sysid, srcid, keep, clean, remUnicode);
ReadSet(sr, true, filename, sysid, srcid, clean, remUnicode);
}
}
}
@@ -109,9 +99,7 @@ namespace SabreTools.Library.DatFiles
// If there's no subtree to the header, skip it
if (reader == null || reader.EndOfStream)
{
return;
}
// Otherwise, add what is possible
string line = reader.ReadLine();
@@ -126,16 +114,15 @@ namespace SabreTools.Library.DatFiles
// Get all header items (ONLY OVERWRITE IF THERE'S NO DATA)
GroupCollection gc = Regex.Match(line, Constants.ItemPatternCMP).Groups;
string itemval = gc[2].Value.Replace("\"", "");
string itemval = gc[2].Value.Replace("\"", string.Empty);
if (line.Trim().StartsWith("Name:"))
{
Name = (String.IsNullOrWhiteSpace(Name) ? line.Substring(6) : Name);
Name = (string.IsNullOrWhiteSpace(Name) ? line.Substring(6) : Name);
superdat = superdat || itemval.Contains(" - SuperDAT");
if (keep && superdat)
{
Type = (String.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
}
Type = (string.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
line = reader.ReadLine();
continue;
@@ -145,79 +132,76 @@ namespace SabreTools.Library.DatFiles
{
case "name":
case "Name:":
Name = (String.IsNullOrWhiteSpace(Name) ? itemval : Name);
Name = (string.IsNullOrWhiteSpace(Name) ? itemval : Name);
superdat = superdat || itemval.Contains(" - SuperDAT");
if (keep && superdat)
{
Type = (String.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
}
Type = (string.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
break;
case "description":
case "Description:":
Description = (String.IsNullOrWhiteSpace(Description) ? itemval : Description);
Description = (string.IsNullOrWhiteSpace(Description) ? itemval : Description);
break;
case "rootdir":
case "Rootdir:":
RootDir = (String.IsNullOrWhiteSpace(RootDir) ? itemval : RootDir);
RootDir = (string.IsNullOrWhiteSpace(RootDir) ? itemval : RootDir);
break;
case "category":
case "Category:":
Category = (String.IsNullOrWhiteSpace(Category) ? itemval : Category);
Category = (string.IsNullOrWhiteSpace(Category) ? itemval : Category);
break;
case "version":
case "Version:":
Version = (String.IsNullOrWhiteSpace(Version) ? itemval : Version);
Version = (string.IsNullOrWhiteSpace(Version) ? itemval : Version);
break;
case "date":
case "Date:":
Date = (String.IsNullOrWhiteSpace(Date) ? itemval : Date);
Date = (string.IsNullOrWhiteSpace(Date) ? itemval : Date);
break;
case "author":
case "Author:":
Author = (String.IsNullOrWhiteSpace(Author) ? itemval : Author);
Author = (string.IsNullOrWhiteSpace(Author) ? itemval : Author);
break;
case "email":
case "Email:":
Email = (String.IsNullOrWhiteSpace(Email) ? itemval : Email);
Email = (string.IsNullOrWhiteSpace(Email) ? itemval : Email);
break;
case "homepage":
case "Homepage:":
Homepage = (String.IsNullOrWhiteSpace(Homepage) ? itemval : Homepage);
Homepage = (string.IsNullOrWhiteSpace(Homepage) ? itemval : Homepage);
break;
case "url":
case "Url:":
Url = (String.IsNullOrWhiteSpace(Url) ? itemval : Url);
Url = (string.IsNullOrWhiteSpace(Url) ? itemval : Url);
break;
case "comment":
case "Comment:":
Comment = (String.IsNullOrWhiteSpace(Comment) ? itemval : Comment);
Comment = (string.IsNullOrWhiteSpace(Comment) ? itemval : Comment);
break;
case "header":
case "Header:":
Header = (String.IsNullOrWhiteSpace(Header) ? itemval : Header);
Header = (string.IsNullOrWhiteSpace(Header) ? itemval : Header);
break;
case "type":
case "Type:":
Type = (String.IsNullOrWhiteSpace(Type) ? itemval : Type);
Type = (string.IsNullOrWhiteSpace(Type) ? itemval : Type);
superdat = superdat || itemval.Contains("SuperDAT");
break;
case "forcemerging":
if (ForceMerging == ForceMerging.None)
{
ForceMerging = Utilities.GetForceMerging(itemval);
}
break;
case "forcezipping":
if (ForcePacking == ForcePacking.None)
{
ForcePacking = Utilities.GetForcePacking(itemval);
}
break;
case "forcepacking":
if (ForcePacking == ForcePacking.None)
{
ForcePacking = Utilities.GetForcePacking(itemval);
}
break;
}
@@ -233,7 +217,6 @@ namespace SabreTools.Library.DatFiles
/// <param name="filename">Name of the file to be parsed</param>
/// <param name="sysid">System ID for the DAT</param>
/// <param name="srcid">Source ID for the DAT</param>
/// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param>
/// <param name="clean">True if game names are sanitized, false otherwise (default)</param>
/// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param>
private void ReadSet(
@@ -246,7 +229,6 @@ namespace SabreTools.Library.DatFiles
int srcid,
// Miscellaneous
bool keep,
bool clean,
bool remUnicode)
{
@@ -259,9 +241,7 @@ namespace SabreTools.Library.DatFiles
// If there's no subtree to the header, skip it
if (reader == null || reader.EndOfStream)
{
return;
}
// Otherwise, add what is possible
string line = reader.ReadLine();
@@ -287,21 +267,13 @@ namespace SabreTools.Library.DatFiles
containsItems = true;
ItemType temptype = ItemType.Rom;
if (line.Trim().StartsWith("rom ("))
{
temptype = ItemType.Rom;
}
else if (line.Trim().StartsWith("disk ("))
{
temptype = ItemType.Disk;
}
else if (line.Trim().StartsWith("file ("))
{
temptype = ItemType.Rom;
}
else if (line.Trim().StartsWith("sample"))
{
temptype = ItemType.Sample;
}
// Create the proper DatItem based on the type
DatItem item = Utilities.GetDatItem(temptype);
@@ -316,7 +288,7 @@ namespace SabreTools.Library.DatFiles
// If we have a sample, treat it special
if (temptype == ItemType.Sample)
{
line = line.Trim().Remove(0, 6).Trim().Replace("\"", ""); // Remove "sample" from the input string
line = line.Trim().Remove(0, 6).Trim().Replace("\"", string.Empty); // Remove "sample" from the input string
item.Name = line;
// Now process and add the sample
@@ -348,7 +320,7 @@ namespace SabreTools.Library.DatFiles
&& linegc[i] != "sha384"
&& linegc[i] != "sha512")
{
item.Name += " " + linegc[i];
item.Name += $" {linegc[i]}";
}
// Perform correction
@@ -361,58 +333,57 @@ namespace SabreTools.Library.DatFiles
{
long tempsize = -1;
if (!Int64.TryParse(linegc[++i], out tempsize))
{
tempsize = 0;
}
((Rom)item).Size = tempsize;
}
// Get the date from the next part
else if (linegc[i] == "date")
{
((Rom)item).Date = linegc[++i].Replace("\"", "") + " " + linegc[++i].Replace("\"", "");
((Rom)item).Date = $"{linegc[++i].Replace("\"", string.Empty)} {linegc[++i].Replace("\"", string.Empty)}";
}
// Get the CRC from the next part
else if (linegc[i] == "crc")
{
((Rom)item).CRC = linegc[++i].Replace("\"", "").ToLowerInvariant();
((Rom)item).CRC = linegc[++i].Replace("\"", string.Empty).ToLowerInvariant();
}
// Get the MD5 from the next part
else if (linegc[i] == "md5")
{
((Rom)item).MD5 = linegc[++i].Replace("\"", "").ToLowerInvariant();
((Rom)item).MD5 = linegc[++i].Replace("\"", string.Empty).ToLowerInvariant();
}
// Get the RIPEMD160 from the next part
else if (linegc[i] == "ripemd160")
{
((Rom)item).RIPEMD160 = linegc[++i].Replace("\"", "").ToLowerInvariant();
((Rom)item).RIPEMD160 = linegc[++i].Replace("\"", string.Empty).ToLowerInvariant();
}
// Get the SHA1 from the next part
else if (linegc[i] == "sha1")
{
((Rom)item).SHA1 = linegc[++i].Replace("\"", "").ToLowerInvariant();
((Rom)item).SHA1 = linegc[++i].Replace("\"", string.Empty).ToLowerInvariant();
}
// Get the SHA256 from the next part
else if (linegc[i] == "sha256")
{
((Rom)item).SHA256 = linegc[++i].Replace("\"", "").ToLowerInvariant();
((Rom)item).SHA256 = linegc[++i].Replace("\"", string.Empty).ToLowerInvariant();
}
// Get the SHA384 from the next part
else if (linegc[i] == "sha384")
{
((Rom)item).SHA384 = linegc[++i].Replace("\"", "").ToLowerInvariant();
((Rom)item).SHA384 = linegc[++i].Replace("\"", string.Empty).ToLowerInvariant();
}
// Get the SHA512 from the next part
else if (linegc[i] == "sha512")
{
((Rom)item).SHA512 = linegc[++i].Replace("\"", "").ToLowerInvariant();
((Rom)item).SHA512 = linegc[++i].Replace("\"", string.Empty).ToLowerInvariant();
}
}
@@ -426,7 +397,7 @@ namespace SabreTools.Library.DatFiles
for (int i = 0; i < linegc.Length; i++)
{
// Look at the current item and use it if possible
string quoteless = linegc[i].Replace("\"", "");
string quoteless = linegc[i].Replace("\"", string.Empty);
switch (quoteless)
{
//If the item is empty, we automatically skip it because it's a fluke
@@ -440,189 +411,188 @@ namespace SabreTools.Library.DatFiles
case "verified":
ItemStatus tempStandaloneStatus = Utilities.GetItemStatus(quoteless);
if (item.ItemType == ItemType.Rom)
{
((Rom)item).ItemStatus = tempStandaloneStatus;
}
else if (item.ItemType == ItemType.Disk)
{
((Disk)item).ItemStatus = tempStandaloneStatus;
}
break;
// Regular attributes
case "name":
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
item.Name = quoteless;
break;
case "size":
if (item.ItemType == ItemType.Rom)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
if (Int64.TryParse(quoteless, out long size))
{
((Rom)item).Size = size;
}
else
{
((Rom)item).Size = -1;
}
}
break;
case "crc":
if (item.ItemType == ItemType.Rom)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Rom)item).CRC = Utilities.CleanHashData(quoteless, Constants.CRCLength);
}
break;
case "md5":
if (item.ItemType == ItemType.Rom)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Rom)item).MD5 = Utilities.CleanHashData(quoteless, Constants.MD5Length);
}
else if (item.ItemType == ItemType.Disk)
{
i++;
quoteless = linegc[i].Replace("\"", "");
quoteless = linegc[i].Replace("\"", string.Empty);
((Disk)item).MD5 = Utilities.CleanHashData(quoteless, Constants.MD5Length);
}
break;
case "ripemd160":
if (item.ItemType == ItemType.Rom)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Rom)item).RIPEMD160 = Utilities.CleanHashData(quoteless, Constants.RIPEMD160Length);
}
else if (item.ItemType == ItemType.Disk)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Disk)item).RIPEMD160 = Utilities.CleanHashData(quoteless, Constants.RIPEMD160Length);
}
break;
case "sha1":
if (item.ItemType == ItemType.Rom)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Rom)item).SHA1 = Utilities.CleanHashData(quoteless, Constants.SHA1Length);
}
else if (item.ItemType == ItemType.Disk)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Disk)item).SHA1 = Utilities.CleanHashData(quoteless, Constants.SHA1Length);
}
break;
case "sha256":
if (item.ItemType == ItemType.Rom)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Rom)item).SHA256 = Utilities.CleanHashData(quoteless, Constants.SHA256Length);
}
else if (item.ItemType == ItemType.Disk)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Disk)item).SHA256 = Utilities.CleanHashData(quoteless, Constants.SHA256Length);
}
break;
case "sha384":
if (item.ItemType == ItemType.Rom)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Rom)item).SHA384 = Utilities.CleanHashData(quoteless, Constants.SHA384Length);
}
else if (item.ItemType == ItemType.Disk)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Disk)item).SHA384 = Utilities.CleanHashData(quoteless, Constants.SHA384Length);
}
break;
case "sha512":
if (item.ItemType == ItemType.Rom)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Rom)item).SHA512 = Utilities.CleanHashData(quoteless, Constants.SHA512Length);
}
else if (item.ItemType == ItemType.Disk)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Disk)item).SHA512 = Utilities.CleanHashData(quoteless, Constants.SHA512Length);
}
break;
case "status":
case "flags":
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
ItemStatus tempFlagStatus = Utilities.GetItemStatus(quoteless);
if (item.ItemType == ItemType.Rom)
{
((Rom)item).ItemStatus = tempFlagStatus;
}
else if (item.ItemType == ItemType.Disk)
{
((Disk)item).ItemStatus = tempFlagStatus;
}
break;
case "date":
if (item.ItemType == ItemType.Rom)
{
// If we have quotes in the next item, assume only one item
if (linegc[i + 1].Contains("\""))
{
quoteless = linegc[++i].Replace("\"", "");
}
quoteless = linegc[++i].Replace("\"", string.Empty);
// Otherwise, we assume we need to read the next two items
else
{
quoteless = linegc[++i].Replace("\"", "") + " " + linegc[++i].Replace("\"", "");
}
quoteless = $"{linegc[++i].Replace("\"", string.Empty)} {linegc[++i].Replace("\"", string.Empty)}";
((Rom)item).Date = quoteless;
}
else if (item.ItemType == ItemType.Release)
{
// If we have quotes in the next item, assume only one item
if (linegc[i + 1].Contains("\""))
{
quoteless = linegc[++i].Replace("\"", "");
}
quoteless = linegc[++i].Replace("\"", string.Empty);
// Otherwise, we assume we need to read the next two items
else
{
quoteless = linegc[++i].Replace("\"", "") + " " + linegc[++i].Replace("\"", "");
}
quoteless = $"{linegc[++i].Replace("\"", string.Empty)} {linegc[++i].Replace("\"", string.Empty)}";
((Release)item).Date = quoteless;
}
break;
case "default":
if (item.ItemType == ItemType.BiosSet)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((BiosSet)item).Default = Utilities.GetYesNo(quoteless.ToLowerInvariant());
}
else if (item.ItemType == ItemType.Release)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Release)item).Default = Utilities.GetYesNo(quoteless.ToLowerInvariant());
}
break;
case "description":
if (item.ItemType == ItemType.BiosSet)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((BiosSet)item).Description = quoteless.ToLowerInvariant();
}
break;
case "region":
if (item.ItemType == ItemType.Release)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Release)item).Region = quoteless.ToLowerInvariant();
}
break;
case "language":
if (item.ItemType == ItemType.Release)
{
quoteless = linegc[++i].Replace("\"", "");
quoteless = linegc[++i].Replace("\"", string.Empty);
((Release)item).Language = quoteless.ToLowerInvariant();
}
break;
}
}
@@ -636,7 +606,7 @@ namespace SabreTools.Library.DatFiles
// Set-specific lines have a known pattern
GroupCollection setgc = Regex.Match(line, Constants.ItemPatternCMP).Groups;
string itemval = setgc[2].Value.Replace("\"", "");
string itemval = setgc[2].Value.Replace("\"", string.Empty);
switch (setgc[1].Value)
{
@@ -676,6 +646,7 @@ namespace SabreTools.Library.DatFiles
System = filename,
SourceID = srcid,
};
blank.CopyMachineInformation(machine);
// Now process and add the rom
@@ -693,13 +664,13 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
@@ -735,22 +706,18 @@ namespace SabreTools.Library.DatFiles
// 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.MachineName.ToLowerInvariant())
{
WriteEndGame(sw, rom);
}
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{
WriteStartGame(sw, rom);
}
// If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
// If we're in a mode that doesn't allow for actual empty folders, add the blank info
rom.Name = (rom.Name == "null" ? "-" : rom.Name);
@@ -775,7 +742,7 @@ namespace SabreTools.Library.DatFiles
// Write the file footer out
WriteFooter(sw);
Globals.Logger.Verbose("File written!" + Environment.NewLine);
Globals.Logger.Verbose($"File written!{Environment.NewLine}");
sw.Dispose();
fs.Dispose();
}
@@ -797,24 +764,48 @@ namespace SabreTools.Library.DatFiles
{
try
{
string header = "clrmamepro (\n" +
"\tname \"" + Name + "\"\n" +
"\tdescription \"" + Description + "\"\n" +
(!String.IsNullOrWhiteSpace(Category) ? "\tcategory \"" + Category + "\"\n" : "") +
"\tversion \"" + Version + "\"\n" +
(!String.IsNullOrWhiteSpace(Date) ? "\tdate \"" + Date + "\"\n" : "") +
"\tauthor \"" + Author + "\"\n" +
(!String.IsNullOrWhiteSpace(Email) ? "\temail \"" + Email + "\"\n" : "") +
(!String.IsNullOrWhiteSpace(Homepage) ? "\thomepage \"" + Homepage + "\"\n" : "") +
(!String.IsNullOrWhiteSpace(Url) ? "\turl \"" + Url + "\"\n" : "") +
(!String.IsNullOrWhiteSpace(Comment) ? "\tcomment \"" + Comment + "\"\n" : "") +
(ForcePacking == ForcePacking.Unzip ? "\tforcezipping no\n" : "") +
(ForcePacking == ForcePacking.Zip ? "\tforcezipping yes\n" : "") +
(ForceMerging == ForceMerging.Full ? "\tforcemerging full\n" : "") +
(ForceMerging == ForceMerging.Split ? "\tforcemerging split\n" : "") +
(ForceMerging == ForceMerging.Merged ? "\tforcemerging merged\n" : "") +
(ForceMerging == ForceMerging.NonMerged ? "\tforcemerging nonmerged\n" : "") +
")\n";
string header = "clrmamepro (\n";
header += $"\tname \"{Name}\"\n";
header += $"\tdescription \"{Description}\"\n";
if (!string.IsNullOrWhiteSpace(Category))
header += $"\tcategory \"{Category}\"\n";
header += $"\tversion \"{Version}\"\n";
if (!string.IsNullOrWhiteSpace(Date))
header += $"\tdate \"{Date}\"\n";
header += $"\tauthor \"{Author}\"\n";
if (!string.IsNullOrWhiteSpace(Email))
header += $"\temail \"{Email}\"\n";
if (!string.IsNullOrWhiteSpace(Homepage))
header += $"\thomepage \"{Homepage}\"\n";
if (!string.IsNullOrWhiteSpace(Url))
header += $"\turl \"{Url}\"\n";
if (!string.IsNullOrWhiteSpace(Comment))
header += $"\tcomment \"{Comment}\"\n";
switch (ForcePacking)
{
case ForcePacking.Unzip:
header += "\tforcezipping no\n";
break;
case ForcePacking.Zip:
header += "\tforcezipping yes\n";
break;
}
switch (ForceMerging)
{
case ForceMerging.Full:
header += "\tforcemerging full\n";
break;
case ForceMerging.Split:
header += "\tforcemerging split\n";
break;
case ForceMerging.Merged:
header += "\tforcemerging merged\n";
break;
case ForceMerging.NonMerged:
header += "\tforcemerging nonmerged\n";
break;
}
header += ")\n";
// Write the header out
sw.Write(header);
@@ -833,25 +824,31 @@ namespace SabreTools.Library.DatFiles
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteStartGame(StreamWriter sw, DatItem rom)
private bool WriteStartGame(StreamWriter sw, DatItem datItem)
{
try
{
// No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{
rom.MachineName = rom.MachineName.Substring(1);
}
datItem.MachineName = datItem.MachineName.TrimStart(Path.DirectorySeparatorChar);
string state = (rom.MachineType == MachineType.Bios ? "resource" : "game") + " (\n\tname \"" + (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName : "") + "\"\n" +
(!ExcludeFields[(int)Field.RomOf] && String.IsNullOrWhiteSpace(rom.RomOf) ? "" : "\tromof \"" + rom.RomOf + "\"\n") +
(!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? "" : "\tcloneof \"" + rom.CloneOf + "\"\n") +
(!ExcludeFields[(int)Field.SampleOf] && String.IsNullOrWhiteSpace(rom.SampleOf) ? "" : "\tsampleof \"" + rom.SampleOf + "\"\n") +
(!ExcludeFields[(int)Field.Description] ? "\tdescription \"" + (String.IsNullOrWhiteSpace(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription) + "\"\n" : "") +
(!ExcludeFields[(int)Field.Year] && String.IsNullOrWhiteSpace(rom.Year) ? "" : "\tyear " + rom.Year + "\n") +
(!ExcludeFields[(int)Field.Manufacturer] && String.IsNullOrWhiteSpace(rom.Manufacturer) ? "" : "\tmanufacturer \"" + rom.Manufacturer + "\"\n");
// Build the state based on excluded fields
string state = (datItem.MachineType == MachineType.Bios ? "resource" : "game");
state += $" (\n\tname \"{datItem.MachineName}\"\n";
state += $"\tromof \"{datItem.RomOf}\"\n";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CloneOf, ExcludeFields)))
state += $"\tcloneof \"{datItem.CloneOf}\"\n";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SampleOf, ExcludeFields)))
state += $"\tsampleof \"{datItem.SampleOf}\"\n";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Description, ExcludeFields)))
state += $"\tdescription \"{datItem.MachineDescription}\"\n";
else if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Description, ExcludeFields)))
state += $"\tdescription \"{datItem.MachineName}\"\n";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Year, ExcludeFields)))
state += $"\tyear \"{datItem.Year}\"\n";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Manufacturer, ExcludeFields)))
state += $"\tmanufacturer \"{datItem.Manufacturer}\"\n";
sw.Write(state);
sw.Flush();
@@ -869,13 +866,19 @@ namespace SabreTools.Library.DatFiles
/// Write out Game end using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteEndGame(StreamWriter sw, DatItem rom)
private bool WriteEndGame(StreamWriter sw, DatItem datItem)
{
try
{
string state = (!ExcludeFields[(int)Field.SampleOf] && String.IsNullOrWhiteSpace(rom.SampleOf) ? "" : "\tsampleof \"" + rom.SampleOf + "\"\n") + ")\n";
string state = string.Empty;
// Build the state based on excluded fields
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SampleOf, ExcludeFields)))
state += $"\tsampleof \"{datItem.SampleOf}\"\n";
state += ")\n";
sw.Write(state);
sw.Flush();
@@ -894,78 +897,103 @@ namespace SabreTools.Library.DatFiles
/// </summary>
/// <param name="datFile">DatFile to write out from</param>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(StreamWriter sw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "";
string state = string.Empty;
// Pre-process the item name
ProcessItemName(rom, true);
ProcessItemName(datItem, true);
switch (rom.ItemType)
// Build the state based on excluded fields
switch (datItem.ItemType)
{
case ItemType.Archive:
state += "\tarchive ( name\"" + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\""
+ " )\n";
state += $"\tarchive ( name\"{datItem.GetField(Field.Name, ExcludeFields)}\"";
state += " )\n";
break;
case ItemType.BiosSet:
state += "\tbiosset ( name\"" + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\""
+ (!ExcludeFields[(int)Field.BiosDescription] && !String.IsNullOrWhiteSpace(((BiosSet)rom).Description) ? " description \"" + ((BiosSet)rom).Description + "\"" : "")
+ (!ExcludeFields[(int)Field.Default] && ((BiosSet)rom).Default != null
? "default " + ((BiosSet)rom).Default.ToString().ToLowerInvariant()
: "")
+ " )\n";
var biosSet = datItem as BiosSet;
state += $"\tbiosset ( name\"{datItem.GetField(Field.Name, ExcludeFields)}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.BiosDescription, ExcludeFields)))
state += $" description \"{biosSet.Description}\"";
if (!ExcludeFields[(int)Field.Default] && biosSet.Default != null)
state += $" default \"{biosSet.Default.ToString().ToLowerInvariant()}\"";
state += " )\n";
break;
case ItemType.Disk:
state += "\tdisk ( name \"" + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\""
+ (!ExcludeFields[(int)Field.MD5] && !String.IsNullOrWhiteSpace(((Disk)rom).MD5) ? " md5 " + ((Disk)rom).MD5.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.RIPEMD160] && !String.IsNullOrWhiteSpace(((Disk)rom).RIPEMD160) ? " ripemd160 " + ((Disk)rom).RIPEMD160.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.SHA1] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA1) ? " sha1 " + ((Disk)rom).SHA1.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.SHA256] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA256) ? " sha256 " + ((Disk)rom).SHA256.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.SHA384] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA384) ? " sha384 " + ((Disk)rom).SHA384.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.SHA512] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA512) ? " sha512 " + ((Disk)rom).SHA512.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus != ItemStatus.None ? " flags " + ((Disk)rom).ItemStatus.ToString().ToLowerInvariant() : "")
+ " )\n";
var disk = datItem as Disk;
state += $"\tdisk ( name \"{datItem.GetField(Field.Name, ExcludeFields)}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
state += $" md5 \"{disk.MD5.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RIPEMD160, ExcludeFields)))
state += $" ripemd160 \"{disk.RIPEMD160.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
state += $" sha1 \"{disk.SHA1.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA256, ExcludeFields)))
state += $" sha256 \"{disk.SHA256.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA384, ExcludeFields)))
state += $" sha384 \"{disk.SHA384.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA512, ExcludeFields)))
state += $" sha512 \"{disk.SHA512.ToLowerInvariant()}\"";
if (!ExcludeFields[(int)Field.Status] && disk.ItemStatus != ItemStatus.None)
state += $" flags \"{disk.ItemStatus.ToString().ToLowerInvariant()}\"";
state += " )\n";
break;
case ItemType.Release:
state += "\trelease ( name\"" + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\""
+ (!ExcludeFields[(int)Field.Region] && !String.IsNullOrWhiteSpace(((Release)rom).Region) ? " region \"" + ((Release)rom).Region + "\"" : "")
+ (!ExcludeFields[(int)Field.Language] && !String.IsNullOrWhiteSpace(((Release)rom).Language) ? " language \"" + ((Release)rom).Language + "\"" : "")
+ (!ExcludeFields[(int)Field.Date] && !String.IsNullOrWhiteSpace(((Release)rom).Date) ? " date \"" + ((Release)rom).Date + "\"" : "")
+ (!ExcludeFields[(int)Field.Default] && ((Release)rom).Default != null
? "default " + ((Release)rom).Default.ToString().ToLowerInvariant()
: "")
+ " )\n";
var release = datItem as Release;
state += $"\trelease ( name\"{datItem.GetField(Field.Name, ExcludeFields)}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Region, ExcludeFields)))
state += $" region \"{release.Region}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Language, ExcludeFields)))
state += $" language \"{release.Language}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Date, ExcludeFields)))
state += $" date \"{release.Date}\"";
if (!ExcludeFields[(int)Field.Default] && release.Default != null)
state += $" default \"{release.Default.ToString().ToLowerInvariant()}\"";
state += " )\n";
break;
case ItemType.Rom:
state += "\trom ( name \"" + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\""
+ (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? " size " + ((Rom)rom).Size : "")
+ (!ExcludeFields[(int)Field.CRC] && !String.IsNullOrWhiteSpace(((Rom)rom).CRC) ? " crc " + ((Rom)rom).CRC.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.MD5] && !String.IsNullOrWhiteSpace(((Rom)rom).MD5) ? " md5 " + ((Rom)rom).MD5.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.RIPEMD160] && !String.IsNullOrWhiteSpace(((Rom)rom).RIPEMD160) ? " ripemd160 " + ((Rom)rom).RIPEMD160.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.SHA1] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA1) ? " sha1 " + ((Rom)rom).SHA1.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.SHA256] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA256) ? " sha256 " + ((Rom)rom).SHA256.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.SHA384] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA384) ? " sha384 " + ((Rom)rom).SHA384.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.SHA512] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA512) ? " sha512 " + ((Rom)rom).SHA512.ToLowerInvariant() : "")
+ (!ExcludeFields[(int)Field.Date] && !String.IsNullOrWhiteSpace(((Rom)rom).Date) ? " date \"" + ((Rom)rom).Date + "\"" : "")
+ (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus != ItemStatus.None ? " flags " + ((Rom)rom).ItemStatus.ToString().ToLowerInvariant() : "")
+ " )\n";
var rom = datItem as Rom;
state += $"\trom ( name \"{datItem.GetField(Field.Name, ExcludeFields)}\"";
if (!ExcludeFields[(int)Field.Size] && rom.Size != -1)
state += $" size \"{rom.Size}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CRC, ExcludeFields)))
state += $" crc \"{rom.CRC.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
state += $" md5 \"{rom.MD5.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RIPEMD160, ExcludeFields)))
state += $" ripemd160 \"{rom.RIPEMD160.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
state += $" sha1 \"{rom.SHA1.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA256, ExcludeFields)))
state += $" sha256 \"{rom.SHA256.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA384, ExcludeFields)))
state += $" sha384 \"{rom.SHA384.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA512, ExcludeFields)))
state += $" sha512 \"{rom.SHA512.ToLowerInvariant()}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Date, ExcludeFields)))
state += $" date \"{rom.Date}\"";
if (!ExcludeFields[(int)Field.Status] && rom.ItemStatus != ItemStatus.None)
state += $" flags \"{rom.ItemStatus.ToString().ToLowerInvariant()}\"";
state += " )\n";
break;
case ItemType.Sample:
state += "\tsample ( name\"" + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\""
+ " )\n";
state += $"\tsample ( name\"{datItem.GetField(Field.Name, ExcludeFields)}\"";
state += " )\n";
break;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
using System;
using SabreTools.Library.Data;
namespace SabreTools.Library.DatFiles

View File

@@ -1,5 +1,4 @@
using System;
using SabreTools.Library.Data;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
namespace SabreTools.Library.DatFiles
@@ -14,7 +13,7 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Object used to lock stats updates
/// </summary>
private object _lockObject = new object();
private readonly object _lockObject = new object();
#endregion
@@ -155,12 +154,12 @@ namespace SabreTools.Library.DatFiles
this.DiskCount += 1;
if (((Disk)item).ItemStatus != ItemStatus.Nodump)
{
this.MD5Count += (String.IsNullOrWhiteSpace(((Disk)item).MD5) ? 0 : 1);
this.RIPEMD160Count += (String.IsNullOrWhiteSpace(((Disk)item).RIPEMD160) ? 0 : 1);
this.SHA1Count += (String.IsNullOrWhiteSpace(((Disk)item).SHA1) ? 0 : 1);
this.SHA256Count += (String.IsNullOrWhiteSpace(((Disk)item).SHA256) ? 0 : 1);
this.SHA384Count += (String.IsNullOrWhiteSpace(((Disk)item).SHA384) ? 0 : 1);
this.SHA512Count += (String.IsNullOrWhiteSpace(((Disk)item).SHA512) ? 0 : 1);
this.MD5Count += (string.IsNullOrWhiteSpace(((Disk)item).MD5) ? 0 : 1);
this.RIPEMD160Count += (string.IsNullOrWhiteSpace(((Disk)item).RIPEMD160) ? 0 : 1);
this.SHA1Count += (string.IsNullOrWhiteSpace(((Disk)item).SHA1) ? 0 : 1);
this.SHA256Count += (string.IsNullOrWhiteSpace(((Disk)item).SHA256) ? 0 : 1);
this.SHA384Count += (string.IsNullOrWhiteSpace(((Disk)item).SHA384) ? 0 : 1);
this.SHA512Count += (string.IsNullOrWhiteSpace(((Disk)item).SHA512) ? 0 : 1);
}
this.BaddumpCount += (((Disk)item).ItemStatus == ItemStatus.BadDump ? 1 : 0);
@@ -176,13 +175,13 @@ namespace SabreTools.Library.DatFiles
if (((Rom)item).ItemStatus != ItemStatus.Nodump)
{
this.TotalSize += ((Rom)item).Size;
this.CRCCount += (String.IsNullOrWhiteSpace(((Rom)item).CRC) ? 0 : 1);
this.MD5Count += (String.IsNullOrWhiteSpace(((Rom)item).MD5) ? 0 : 1);
this.RIPEMD160Count += (String.IsNullOrWhiteSpace(((Rom)item).RIPEMD160) ? 0 : 1);
this.SHA1Count += (String.IsNullOrWhiteSpace(((Rom)item).SHA1) ? 0 : 1);
this.SHA256Count += (String.IsNullOrWhiteSpace(((Rom)item).SHA256) ? 0 : 1);
this.SHA384Count += (String.IsNullOrWhiteSpace(((Rom)item).SHA384) ? 0 : 1);
this.SHA512Count += (String.IsNullOrWhiteSpace(((Rom)item).SHA512) ? 0 : 1);
this.CRCCount += (string.IsNullOrWhiteSpace(((Rom)item).CRC) ? 0 : 1);
this.MD5Count += (string.IsNullOrWhiteSpace(((Rom)item).MD5) ? 0 : 1);
this.RIPEMD160Count += (string.IsNullOrWhiteSpace(((Rom)item).RIPEMD160) ? 0 : 1);
this.SHA1Count += (string.IsNullOrWhiteSpace(((Rom)item).SHA1) ? 0 : 1);
this.SHA256Count += (string.IsNullOrWhiteSpace(((Rom)item).SHA256) ? 0 : 1);
this.SHA384Count += (string.IsNullOrWhiteSpace(((Rom)item).SHA384) ? 0 : 1);
this.SHA512Count += (string.IsNullOrWhiteSpace(((Rom)item).SHA512) ? 0 : 1);
}
this.BaddumpCount += (((Rom)item).ItemStatus == ItemStatus.BadDump ? 1 : 0);
@@ -257,12 +256,12 @@ namespace SabreTools.Library.DatFiles
this.DiskCount -= 1;
if (((Disk)item).ItemStatus != ItemStatus.Nodump)
{
this.MD5Count -= (String.IsNullOrWhiteSpace(((Disk)item).MD5) ? 0 : 1);
this.RIPEMD160Count -= (String.IsNullOrWhiteSpace(((Disk)item).RIPEMD160) ? 0 : 1);
this.SHA1Count -= (String.IsNullOrWhiteSpace(((Disk)item).SHA1) ? 0 : 1);
this.SHA256Count -= (String.IsNullOrWhiteSpace(((Disk)item).SHA256) ? 0 : 1);
this.SHA384Count -= (String.IsNullOrWhiteSpace(((Disk)item).SHA384) ? 0 : 1);
this.SHA512Count -= (String.IsNullOrWhiteSpace(((Disk)item).SHA512) ? 0 : 1);
this.MD5Count -= (string.IsNullOrWhiteSpace(((Disk)item).MD5) ? 0 : 1);
this.RIPEMD160Count -= (string.IsNullOrWhiteSpace(((Disk)item).RIPEMD160) ? 0 : 1);
this.SHA1Count -= (string.IsNullOrWhiteSpace(((Disk)item).SHA1) ? 0 : 1);
this.SHA256Count -= (string.IsNullOrWhiteSpace(((Disk)item).SHA256) ? 0 : 1);
this.SHA384Count -= (string.IsNullOrWhiteSpace(((Disk)item).SHA384) ? 0 : 1);
this.SHA512Count -= (string.IsNullOrWhiteSpace(((Disk)item).SHA512) ? 0 : 1);
}
this.BaddumpCount -= (((Disk)item).ItemStatus == ItemStatus.BadDump ? 1 : 0);
@@ -278,13 +277,13 @@ namespace SabreTools.Library.DatFiles
if (((Rom)item).ItemStatus != ItemStatus.Nodump)
{
this.TotalSize -= ((Rom)item).Size;
this.CRCCount -= (String.IsNullOrWhiteSpace(((Rom)item).CRC) ? 0 : 1);
this.MD5Count -= (String.IsNullOrWhiteSpace(((Rom)item).MD5) ? 0 : 1);
this.RIPEMD160Count -= (String.IsNullOrWhiteSpace(((Rom)item).RIPEMD160) ? 0 : 1);
this.SHA1Count -= (String.IsNullOrWhiteSpace(((Rom)item).SHA1) ? 0 : 1);
this.SHA256Count -= (String.IsNullOrWhiteSpace(((Rom)item).SHA256) ? 0 : 1);
this.SHA384Count -= (String.IsNullOrWhiteSpace(((Rom)item).SHA384) ? 0 : 1);
this.SHA512Count -= (String.IsNullOrWhiteSpace(((Rom)item).SHA512) ? 0 : 1);
this.CRCCount -= (string.IsNullOrWhiteSpace(((Rom)item).CRC) ? 0 : 1);
this.MD5Count -= (string.IsNullOrWhiteSpace(((Rom)item).MD5) ? 0 : 1);
this.RIPEMD160Count -= (string.IsNullOrWhiteSpace(((Rom)item).RIPEMD160) ? 0 : 1);
this.SHA1Count -= (string.IsNullOrWhiteSpace(((Rom)item).SHA1) ? 0 : 1);
this.SHA256Count -= (string.IsNullOrWhiteSpace(((Rom)item).SHA256) ? 0 : 1);
this.SHA384Count -= (string.IsNullOrWhiteSpace(((Rom)item).SHA384) ? 0 : 1);
this.SHA512Count -= (string.IsNullOrWhiteSpace(((Rom)item).SHA512) ? 0 : 1);
}
this.BaddumpCount -= (((Rom)item).ItemStatus == ItemStatus.BadDump ? 1 : 0);

View File

@@ -1,19 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -68,13 +61,13 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
@@ -112,22 +105,18 @@ namespace SabreTools.Library.DatFiles
// 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.MachineName.ToLowerInvariant())
{
WriteEndGame(sw, rom);
}
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{
WriteStartGame(sw, rom);
}
// If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
rom.Name = (rom.Name == "null" ? "-" : rom.Name);
((Rom)rom).Size = Constants.SizeZero;
@@ -151,7 +140,7 @@ namespace SabreTools.Library.DatFiles
// Write the file footer out
WriteFooter(sw);
Globals.Logger.Verbose("File written!" + Environment.NewLine);
Globals.Logger.Verbose($"File written!{Environment.NewLine}");
sw.Dispose();
fs.Dispose();
}
@@ -173,15 +162,15 @@ namespace SabreTools.Library.DatFiles
{
try
{
string header = "DOSCenter (\n" +
"\tName: " + Name + "\n" +
"\tDescription: " + Description + "\n" +
"\tVersion: " + Version + "\n" +
"\tDate: " + Date + "\n" +
"\tAuthor: " + Author + "\n" +
"\tHomepage: " + Homepage + "\n" +
"\tComment: " + Comment + "\n" +
")\n";
string header = "DOSCenter (\n";
header += $"\tName: {Name}\n";
header += $"\tDescription: {Description}\n";
header += $"\tVersion: {Version}\n";
header += $"\tDate: {Date}\n";
header += $"\tAuthor: {Author}\n";
header += $"\tHomepage: {Homepage}\n";
header += $"\tComment: {Comment}\n";
header += ")\n";
// Write the header out
sw.Write(header);
@@ -200,19 +189,17 @@ namespace SabreTools.Library.DatFiles
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteStartGame(StreamWriter sw, DatItem rom)
private bool WriteStartGame(StreamWriter sw, DatItem datItem)
{
try
{
// No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{
rom.MachineName = rom.MachineName.Substring(1);
}
datItem.MachineName = datItem.MachineName.TrimStart(Path.DirectorySeparatorChar);
string state = "game (\n\tname \"" + (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName + ".zip" : "") + "\"\n";
// Build the state based on excluded fields
string state = $"game (\n\tname \"{datItem.GetField(Field.MachineName, ExcludeFields)}.zip\n";
sw.Write(state);
sw.Flush();
@@ -230,13 +217,19 @@ namespace SabreTools.Library.DatFiles
/// Write out Game end using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteEndGame(StreamWriter sw, DatItem rom)
private bool WriteEndGame(StreamWriter sw, DatItem datItem)
{
try
{
string state = (!ExcludeFields[(int)Field.SampleOf] && String.IsNullOrWhiteSpace(rom.SampleOf) ? "" : "\tsampleof \"" + rom.SampleOf + "\"\n") + ")\n";
string state = string.Empty;
// Build the state based on excluded fields
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SampleOf, ExcludeFields)))
state += $"\tsampleof \"{datItem.SampleOf}\"\n";
state += ")\n";
sw.Write(state);
sw.Flush();
@@ -254,27 +247,24 @@ namespace SabreTools.Library.DatFiles
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(StreamWriter sw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "";
string state = string.Empty;
// Pre-process the item name
ProcessItemName(rom, true);
ProcessItemName(datItem, true);
switch (rom.ItemType)
// Build the state based on excluded fields
switch (datItem.ItemType)
{
case ItemType.Archive:
case ItemType.BiosSet:
@@ -284,11 +274,15 @@ namespace SabreTools.Library.DatFiles
// We don't output these at all for DosCenter
break;
case ItemType.Rom:
state += "\tfile ( name " + (!ExcludeFields[(int)Field.Name] ? ((Rom)rom).Name : "")
+ (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? " size " + ((Rom)rom).Size : "")
+ (!ExcludeFields[(int)Field.Date] && !String.IsNullOrWhiteSpace(((Rom)rom).Date) ? " date " + ((Rom)rom).Date : "")
+ (!ExcludeFields[(int)Field.CRC] && !String.IsNullOrWhiteSpace(((Rom)rom).CRC) ? " crc " + ((Rom)rom).CRC.ToLowerInvariant() : "")
+ " )\n";
var rom = datItem as Rom;
state += $"\file ( name \"{datItem.GetField(Field.Name, ExcludeFields)}\"";
if (!ExcludeFields[(int)Field.Size] && rom.Size != -1)
state += $" size \"{rom.Size}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Date, ExcludeFields)))
state += $" date \"{rom.Date}\"";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CRC, ExcludeFields)))
state += $" crc \"{rom.CRC.ToLowerInvariant()}\"";
state += " )\n";
break;
}

View File

@@ -1,19 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamReader = System.IO.StreamReader;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -103,13 +95,13 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
@@ -142,7 +134,7 @@ namespace SabreTools.Library.DatFiles
&& ((Rom)item).Size == -1
&& ((Rom)item).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", item.MachineName);
Globals.Logger.Verbose($"Empty folder found: {item.MachineName}");
item.Name = (item.Name == "null" ? "-" : item.Name);
((Rom)item).Size = Constants.SizeZero;
@@ -152,7 +144,7 @@ namespace SabreTools.Library.DatFiles
}
}
Globals.Logger.Verbose("File written!" + Environment.NewLine);
Globals.Logger.Verbose($"File written!{Environment.NewLine}");
sw.Dispose();
fs.Dispose();
}
@@ -169,35 +161,46 @@ namespace SabreTools.Library.DatFiles
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(StreamWriter sw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
// No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
rom.MachineName = rom.MachineName.Substring(1);
datItem.MachineName = datItem.MachineName.TrimStart(Path.DirectorySeparatorChar);
// If the DatItem isn't a rom, we don't output it
if (rom.ItemType != ItemType.Rom)
return true;
// Pre-process the item name
ProcessItemName(datItem, true);
Rom temp = rom as Rom;
string state = (!ExcludeFields[(int)Field.SHA256] ? temp.SHA256 : "") + "\t"
+ (!ExcludeFields[(int)Field.MachineName] ? temp.MachineName + "/" : "")
+ temp.Name + "\t"
+ (!ExcludeFields[(int)Field.SHA1] ? temp.SHA1 : "") + "\t"
+ (!ExcludeFields[(int)Field.MD5] ? temp.MD5 : "") + "\t"
+ (!ExcludeFields[(int)Field.CRC] ? temp.CRC : "") + "\n";
string state = string.Empty;
// Build the state based on excluded fields
switch (datItem.ItemType)
{
case ItemType.Archive:
case ItemType.BiosSet:
case ItemType.Disk:
case ItemType.Release:
case ItemType.Sample:
// We don't output these at all for Everdrive SMDB
break;
case ItemType.Rom:
var rom = datItem as Rom;
state += $"{rom.GetField(Field.SHA256, ExcludeFields)}\t";
state += $"{rom.GetField(Field.MachineName, ExcludeFields)}/\t";
state += $"{rom.GetField(Field.Name, ExcludeFields)}\t";
state += $"{rom.GetField(Field.SHA1, ExcludeFields)}\t";
state += $"{rom.GetField(Field.MD5, ExcludeFields)}\t";
state += $"{rom.GetField(Field.CRC, ExcludeFields)}";
state += "\n";
break;
}
sw.Write(state);
sw.Flush();

View File

@@ -1,19 +1,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
#endif
namespace SabreTools.Library.DatFiles
{
/// <summary>
/// Represents the filtering operations that need to be performed on a set of items, usually a DAT
/// </summary>
/// TODO: Can this use `Field` instead of explicit filters?
public class Filter
{
#region Pubically facing variables

View File

@@ -155,13 +155,13 @@ namespace SabreTools.Library.DatFiles
{
string needleString = needle as string;
string strawString = straw as string;
if (!String.IsNullOrWhiteSpace(strawString) && needleString != null)
if (!string.IsNullOrWhiteSpace(strawString) && needleString != null)
{
string regexStraw = strawString;
// If the straw has no special characters at all (excluding whitespace), treat it as an exact match
if (regexStraw == Regex.Escape(regexStraw).Replace("\\ ", " "))
regexStraw = "^" + regexStraw + "$";
regexStraw = $"^{regexStraw}$";
// Check if a match is found with the regex
found |= Regex.IsMatch(needleString, regexStraw, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);

View File

@@ -1,19 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamReader = System.IO.StreamReader;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -24,7 +16,7 @@ namespace SabreTools.Library.DatFiles
internal class Hashfile : DatFile
{
// Private instance variables specific to Hashfile DATs
Hash _hash;
private readonly Hash _hash;
/// <summary>
/// Constructor designed for casting a base DatFile
@@ -67,8 +59,8 @@ namespace SabreTools.Library.DatFiles
// Split the line and get the name and hash
string[] split = line.Split(' ');
string name = "";
string hash = "";
string name = string.Empty;
string hash = string.Empty;
// If we have CRC, then it's an SFV file and the name is first are
if ((_hash & Hash.CRC) != 0)
@@ -119,13 +111,13 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
@@ -158,7 +150,7 @@ namespace SabreTools.Library.DatFiles
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
}
// Now, output the rom data
@@ -166,7 +158,7 @@ namespace SabreTools.Library.DatFiles
}
}
Globals.Logger.Verbose("File written!" + Environment.NewLine);
Globals.Logger.Verbose($"File written!{Environment.NewLine}");
sw.Dispose();
fs.Dispose();
}
@@ -183,118 +175,61 @@ namespace SabreTools.Library.DatFiles
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(StreamWriter sw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "";
string state = string.Empty;
// Pre-process the item name
ProcessItemName(rom, true);
ProcessItemName(datItem, true);
// Build the state based on excluded fields
switch (_hash)
{
case Hash.CRC:
if (rom.ItemType == ItemType.Rom)
if (datItem.ItemType == ItemType.Rom)
{
state += (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "")
+ " " + (!ExcludeFields[(int)Field.CRC] ? ((Rom)rom).CRC : "") + "\n";
var rom = datItem as Rom;
if (GameName)
state += $"{rom.GetField(Field.MachineName, ExcludeFields)}{Path.DirectorySeparatorChar}";
state += $"{rom.GetField(Field.Name, ExcludeFields)}";
state += $"{rom.GetField(Field.CRC, ExcludeFields)}";
state += "\n";
}
break;
case Hash.MD5:
if (rom.ItemType == ItemType.Rom)
{
state += (!ExcludeFields[(int)Field.MD5] ? ((Rom)rom).MD5 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
}
else if (rom.ItemType == ItemType.Disk)
{
state += (!ExcludeFields[(int)Field.MD5] ? ((Disk)rom).MD5 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
}
break;
case Hash.RIPEMD160:
if (rom.ItemType == ItemType.Rom)
{
state += (!ExcludeFields[(int)Field.RIPEMD160] ? ((Rom)rom).RIPEMD160 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
}
else if (rom.ItemType == ItemType.Disk)
{
state += (!ExcludeFields[(int)Field.RIPEMD160] ? ((Disk)rom).RIPEMD160 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
}
break;
case Hash.SHA1:
if (rom.ItemType == ItemType.Rom)
{
state += (!ExcludeFields[(int)Field.SHA1] ? ((Rom)rom).SHA1 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
}
else if (rom.ItemType == ItemType.Disk)
{
state += (!ExcludeFields[(int)Field.SHA1] ? ((Disk)rom).SHA1 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
}
break;
case Hash.SHA256:
if (rom.ItemType == ItemType.Rom)
{
state += (!ExcludeFields[(int)Field.SHA256] ? ((Rom)rom).SHA256 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
}
else if (rom.ItemType == ItemType.Disk)
{
state += (!ExcludeFields[(int)Field.SHA256] ? ((Disk)rom).SHA256 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
}
break;
case Hash.SHA384:
if (rom.ItemType == ItemType.Rom)
{
state += (!ExcludeFields[(int)Field.SHA384] ? ((Rom)rom).SHA384 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
}
else if (rom.ItemType == ItemType.Disk)
{
state += (!ExcludeFields[(int)Field.SHA384] ? ((Disk)rom).SHA384 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
}
break;
case Hash.SHA512:
if (rom.ItemType == ItemType.Rom)
Field hashField = Utilities.GetFieldFromHash(_hash);
if (datItem.ItemType == ItemType.Rom)
{
state += (!ExcludeFields[(int)Field.SHA512] ? ((Rom)rom).SHA512 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
var rom = datItem as Rom;
state += $"{rom.GetField(hashField, ExcludeFields)}";
if (GameName)
state += $"{rom.GetField(Field.MachineName, ExcludeFields)}{Path.DirectorySeparatorChar}";
state += $"{rom.GetField(Field.Name, ExcludeFields)}";
state += "\n";
}
else if (rom.ItemType == ItemType.Disk)
else if (datItem.ItemType == ItemType.Disk)
{
state += (!ExcludeFields[(int)Field.SHA512] ? ((Disk)rom).SHA512 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
var disk = datItem as Disk;
state += $"{disk.GetField(hashField, ExcludeFields)}";
if (GameName)
state += $"{disk.GetField(Field.MachineName, ExcludeFields)}{Path.DirectorySeparatorChar}";
state += $"{disk.GetField(Field.Name, ExcludeFields)}";
state += "\n";
}
break;
}

View File

@@ -1,20 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamReader = System.IO.StreamReader;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -66,13 +58,13 @@ namespace SabreTools.Library.DatFiles
Encoding enc = Utilities.GetEncoding(filename);
StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc);
string gamename = "";
string gamename = string.Empty;
while (!sr.EndOfStream)
{
string line = sr.ReadLine().Trim();
// If we have a blank line, we just skip it
if (String.IsNullOrWhiteSpace(line))
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
@@ -86,7 +78,7 @@ namespace SabreTools.Library.DatFiles
// If we have the beginning of a game, set the name of the game
else if (line.StartsWith("ROMs required for"))
{
gamename = Regex.Match(line, @"^ROMs required for \S*? ""(.*?)""\.").Groups[1].Value;
gamename = Regex.Match(line, @"^ROMs required for \S*? string.Empty(.*?)string.Empty\.").Groups[1].Value;
}
// If we have a machine with no required roms (usually internal devices), skip it
@@ -99,20 +91,16 @@ namespace SabreTools.Library.DatFiles
else
{
// First, we preprocess the line so that the rom name is consistently correct
string romname = "";
string romname = string.Empty;
string[] split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
// If the line doesn't have the 4 spaces of padding, check for 3
if (split.Length == 1)
{
split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
}
// If the split is still unsuccessful, log it and skip
if (split.Length == 1)
{
Globals.Logger.Warning("Possibly malformed line: '{0}'", line);
}
Globals.Logger.Warning($"Possibly malformed line: '{line}'");
romname = split[0];
line = line.Substring(romname.Length);
@@ -153,9 +141,7 @@ namespace SabreTools.Library.DatFiles
else if (split.Length == 3)
{
if (!Int64.TryParse(split[0], out long size))
{
size = 0;
}
Rom rom = new Rom()
{
@@ -188,9 +174,7 @@ namespace SabreTools.Library.DatFiles
else if (split.Length == 5 && line.EndsWith("BAD_DUMP"))
{
if (!Int64.TryParse(split[0], out long size))
{
size = 0;
}
Rom rom = new Rom()
{
@@ -210,9 +194,7 @@ namespace SabreTools.Library.DatFiles
else if (split.Length == 5 && line.EndsWith("NO GOOD DUMP KNOWN"))
{
if (!Int64.TryParse(split[0], out long size))
{
size = 0;
}
Rom rom = new Rom()
{
@@ -229,7 +211,7 @@ namespace SabreTools.Library.DatFiles
// If we have something else, it's invalid
else
{
Globals.Logger.Warning("Invalid line detected: '{0} {1}'", romname, line);
Globals.Logger.Warning($"Invalid line detected: '{romname} {line}'");
}
}
}
@@ -246,13 +228,13 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
@@ -285,22 +267,18 @@ namespace SabreTools.Library.DatFiles
// 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.MachineName.ToLowerInvariant())
{
WriteEndGame(sw);
}
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{
WriteStartGame(sw, rom);
}
// If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
rom.Name = (rom.Name == "null" ? "-" : rom.Name);
((Rom)rom).Size = Constants.SizeZero;
@@ -344,13 +322,11 @@ namespace SabreTools.Library.DatFiles
try
{
// No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{
rom.MachineName = rom.MachineName.Substring(1);
}
rom.MachineName = rom.MachineName.TrimStart(Path.DirectorySeparatorChar);
string state = "ROMs required for driver \"" + (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName : "") + "\".\n" +
"Name Size Checksum\n";
// Build the state based on excluded fields
string state = $"ROMs required for driver \"{rom.GetField(Field.MachineName, ExcludeFields)}\".\n";
state += "Name Size Checksum\n";
sw.Write(state);
sw.Flush();
@@ -391,110 +367,94 @@ namespace SabreTools.Library.DatFiles
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(StreamWriter sw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "";
string state = string.Empty;
// Pre-process the item name
ProcessItemName(rom, true);
ProcessItemName(datItem, true);
switch (rom.ItemType)
// Build the state based on excluded fields
switch (datItem.ItemType)
{
case ItemType.Archive:
case ItemType.BiosSet:
case ItemType.Release:
case ItemType.Sample:
// We don't output these at all
// We don't output these at all for Listrom
break;
case ItemType.Disk:
var disk = datItem as Disk;
// The name is padded out to a particular length
if (rom.Name.Length < 43)
{
state += rom.Name.PadRight(43, ' ');
}
if (disk.Name.Length < 43)
state += disk.Name.PadRight(43, ' ');
else
{
state += rom.Name + " ";
}
state += disk.Name + " ";
// If we have a baddump, put the first indicator
if (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus == ItemStatus.BadDump)
{
if (!ExcludeFields[(int)Field.Status] && disk.ItemStatus == ItemStatus.BadDump)
state += " BAD";
}
// If we have a nodump, write out the indicator
if (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus == ItemStatus.Nodump)
{
if (!ExcludeFields[(int)Field.Status] && disk.ItemStatus == ItemStatus.Nodump)
state += " NO GOOD DUMP KNOWN";
}
// Otherwise, write out the SHA-1 hash
else if (!ExcludeFields[(int)Field.SHA1])
{
state += " SHA1(" + ((Disk)rom).SHA1 + ")";
}
else if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
state += $" SHA1({disk.SHA1})";
// If we have a baddump, put the second indicator
if (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus == ItemStatus.BadDump)
{
if (!ExcludeFields[(int)Field.Status] && disk.ItemStatus == ItemStatus.BadDump)
state += " BAD_DUMP";
}
state += "\n";
break;
case ItemType.Rom:
var rom = datItem as Rom;
// The name is padded out to a particular length
if (rom.Name.Length < 40)
{
state += rom.Name.PadRight(43 - (((Rom)rom).Size.ToString().Length), ' ');
}
state += rom.Name.PadRight(43 - rom.Size.ToString().Length, ' ');
else
{
state += rom.Name + " ";
}
// If we don't have a nodump, write out the size
if (((Rom)rom).ItemStatus != ItemStatus.Nodump)
{
state += ((Rom)rom).Size;
}
if (rom.ItemStatus != ItemStatus.Nodump)
state += rom.Size;
// If we have a baddump, put the first indicator
if (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus == ItemStatus.BadDump)
{
if (!ExcludeFields[(int)Field.Status] && rom.ItemStatus == ItemStatus.BadDump)
state += " BAD";
}
// If we have a nodump, write out the indicator
if (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus == ItemStatus.Nodump)
if (!ExcludeFields[(int)Field.Status] && rom.ItemStatus == ItemStatus.Nodump)
{
state += " NO GOOD DUMP KNOWN";
}
// Otherwise, write out the CRC and SHA-1 hashes
else
{
state += (!ExcludeFields[(int)Field.CRC] ? " CRC(" + ((Rom)rom).CRC + ")" : "");
state += (!ExcludeFields[(int)Field.SHA1] ? " SHA1(" + ((Rom)rom).SHA1 + ")" : "");
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CRC, ExcludeFields)))
state += $" CRC({rom.CRC})";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
state += $" SHA1({rom.SHA1})";
}
// If we have a baddump, put the second indicator
if (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus == ItemStatus.BadDump)
{
if (!ExcludeFields[(int)Field.Status] && rom.ItemStatus == ItemStatus.BadDump)
state += " BAD_DUMP";
}
state += "\n";
break;

View File

@@ -1,20 +1,12 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Text;
using System.Xml;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -62,9 +54,7 @@ namespace SabreTools.Library.DatFiles
// If we got a null reader, just return
if (xtr == null)
{
return;
}
// Otherwise, read the file to the end
try
@@ -82,27 +72,30 @@ namespace SabreTools.Library.DatFiles
switch (xtr.Name)
{
case "mame":
Name = (String.IsNullOrWhiteSpace(Name) ? xtr.GetAttribute("build") : Name);
Description = (String.IsNullOrWhiteSpace(Description) ? Name : Name);
Name = (string.IsNullOrWhiteSpace(Name) ? xtr.GetAttribute("build") : Name);
Description = (string.IsNullOrWhiteSpace(Description) ? Name : Name);
// string mame_debug = xtr.GetAttribute("debug"); // (yes|no) "no"
// string mame_mameconfig = xtr.GetAttribute("mameconfig"); CDATA
xtr.Read();
break;
// Handle M1 DATs since they're 99% the same as a SL DAT
case "m1":
Name = (String.IsNullOrWhiteSpace(Name) ? "M1" : Name);
Description = (String.IsNullOrWhiteSpace(Description) ? "M1" : Description);
Version = (String.IsNullOrWhiteSpace(Version) ? xtr.GetAttribute("version") ?? "" : Version);
Name = (string.IsNullOrWhiteSpace(Name) ? "M1" : Name);
Description = (string.IsNullOrWhiteSpace(Description) ? "M1" : Description);
Version = (string.IsNullOrWhiteSpace(Version) ? xtr.GetAttribute("version") ?? string.Empty : Version);
xtr.Read();
break;
// We want to process the entire subtree of the machine
case "game": // Some older DATs still use "game"
case "machine":
ReadMachine(xtr.ReadSubtree(), filename, sysid, srcid, keep, clean, remUnicode);
ReadMachine(xtr.ReadSubtree(), filename, sysid, srcid, clean, remUnicode);
// Skip the machine now that we've processed it
xtr.Skip();
break;
default:
xtr.Read();
break;
@@ -111,7 +104,7 @@ namespace SabreTools.Library.DatFiles
}
catch (Exception ex)
{
Globals.Logger.Warning("Exception found while parsing '{0}': {1}", filename, ex);
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
// For XML errors, just skip the affected node
xtr?.Read();
@@ -127,7 +120,6 @@ namespace SabreTools.Library.DatFiles
/// <param name="filename">Name of the file to be parsed</param>
/// <param name="sysid">System ID for the DAT</param>
/// <param name="srcid">Source ID for the DAT</param>
/// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param>
/// <param name="clean">True if game names are sanitized, false otherwise (default)</param>
/// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param>
private void ReadMachine(
@@ -139,37 +131,30 @@ namespace SabreTools.Library.DatFiles
int srcid,
// Miscellaneous
bool keep,
bool clean,
bool remUnicode)
{
// If we have an empty machine, skip it
if (reader == null)
{
return;
}
// Otherwise, add what is possible
reader.MoveToContent();
string key = "";
string key = string.Empty;
string temptype = reader.Name;
bool containsItems = false;
// Create a new machine
MachineType machineType = MachineType.NULL;
if (Utilities.GetYesNo(reader.GetAttribute("isbios")) == true)
{
machineType |= MachineType.Bios;
}
if (Utilities.GetYesNo(reader.GetAttribute("isdevice")) == true)
{
machineType |= MachineType.Device;
}
if (Utilities.GetYesNo(reader.GetAttribute("ismechanical")) == true)
{
machineType |= MachineType.Mechanical;
}
Machine machine = new Machine
{
@@ -178,11 +163,11 @@ namespace SabreTools.Library.DatFiles
SourceFile = reader.GetAttribute("sourcefile"),
Runnable = Utilities.GetYesNo(reader.GetAttribute("runnable")),
Comment = "",
Comment = string.Empty,
CloneOf = reader.GetAttribute("cloneof") ?? "",
RomOf = reader.GetAttribute("romof") ?? "",
SampleOf = reader.GetAttribute("sampleof") ?? "",
CloneOf = reader.GetAttribute("cloneof") ?? string.Empty,
RomOf = reader.GetAttribute("romof") ?? string.Empty,
SampleOf = reader.GetAttribute("sampleof") ?? string.Empty,
Devices = new List<string>(),
SlotOptions = new List<string>(),
@@ -204,12 +189,15 @@ namespace SabreTools.Library.DatFiles
case "description":
machine.Description = reader.ReadElementContentAsString();
break;
case "year":
machine.Year = reader.ReadElementContentAsString();
break;
case "manufacturer":
machine.Manufacturer = reader.ReadElementContentAsString();
break;
case "biosset":
containsItems = true;
@@ -231,6 +219,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "rom":
containsItems = true;
@@ -264,6 +253,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "disk":
containsItems = true;
@@ -295,15 +285,15 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "device_ref":
string device_ref_name = reader.GetAttribute("name");
if (!machine.Devices.Contains(device_ref_name))
{
machine.Devices.Add(device_ref_name);
}
reader.Read();
break;
case "sample":
containsItems = true;
@@ -323,6 +313,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "chip":
// string chip_name = reader.GetAttribute("name");
// string chip_tag = reader.GetAttribute("tag");
@@ -331,6 +322,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "display":
// string display_tag = reader.GetAttribute("tag");
// string display_type = reader.GetAttribute("type"); // (raster|vector|lcd|svg|unknown)
@@ -349,11 +341,13 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "sound":
// string sound_channels = reader.GetAttribute("channels");
reader.Read();
break;
case "condition":
// string condition_tag = reader.GetAttribute("tag");
// string condition_mask = reader.GetAttribute("mask");
@@ -362,6 +356,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "input":
// bool? input_service = Utilities.GetYesNo(reader.GetAttribute("service"));
// bool? input_tilt = Utilities.GetYesNo(reader.GetAttribute("tilt"));
@@ -384,6 +379,7 @@ namespace SabreTools.Library.DatFiles
reader.Skip();
break;
case "dipswitch":
// string dipswitch_name = reader.GetAttribute("name");
// string dipswitch_tag = reader.GetAttribute("tag");
@@ -401,6 +397,7 @@ namespace SabreTools.Library.DatFiles
reader.Skip();
break;
case "configuration":
// string configuration_name = reader.GetAttribute("name");
// string configuration_tag = reader.GetAttribute("tag");
@@ -418,6 +415,7 @@ namespace SabreTools.Library.DatFiles
reader.Skip();
break;
case "port":
// string port_tag = reader.GetAttribute("tag");
@@ -426,6 +424,7 @@ namespace SabreTools.Library.DatFiles
reader.Skip();
break;
case "adjuster":
// string adjuster_name = reader.GetAttribute("name");
// bool? adjuster_default = Utilities.GetYesNo(reader.GetAttribute("default"));
@@ -446,6 +445,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "feature":
// string feature_type = reader.GetAttribute("type"); // (protection|palette|graphics|sound|controls|keyboard|mouse|microphone|camera|disk|printer|lan|wan|timing)
// string feature_status = reader.GetAttribute("status"); // (unemulated|imperfect)
@@ -469,6 +469,7 @@ namespace SabreTools.Library.DatFiles
reader.Skip();
break;
case "slot":
// string slot_name = reader.GetAttribute("name");
ReadSlot(reader.ReadSubtree(), machine);
@@ -476,6 +477,7 @@ namespace SabreTools.Library.DatFiles
// Skip the slot now that we've processed it
reader.Skip();
break;
case "softwarelist":
// string softwarelist_name = reader.GetAttribute("name");
// string softwarelist_status = reader.GetAttribute("status"); // (original|compatible)
@@ -483,11 +485,13 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "ramoption":
// string ramoption_default = reader.GetAttribute("default");
reader.Read();
break;
default:
reader.Read();
break;
@@ -519,9 +523,7 @@ namespace SabreTools.Library.DatFiles
{
// If we have an empty machine, skip it
if (reader == null)
{
return;
}
// Otherwise, add what is possible
reader.MoveToContent();
@@ -548,6 +550,7 @@ namespace SabreTools.Library.DatFiles
// bool? slotoption_default = Utilities.GetYesNo(reader.GetAttribute("default"));
reader.Read();
break;
default:
reader.Read();
break;
@@ -565,20 +568,21 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
XmlTextWriter xtw = new XmlTextWriter(fs, new UTF8Encoding(false));
xtw.Formatting = Formatting.Indented;
// Write out the header
WriteHeader(sw);
WriteHeader(xtw);
// Write out each of the machines and roms
string lastgame = null;
@@ -607,29 +611,25 @@ namespace SabreTools.Library.DatFiles
// 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.MachineName.ToLowerInvariant())
{
WriteEndGame(sw);
}
WriteEndGame(xtw);
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{
WriteStartGame(sw, rom);
}
WriteStartGame(xtw, rom);
// If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
lastgame = rom.MachineName;
continue;
}
// Now, output the rom data
WriteDatItem(sw, rom, ignoreblanks);
WriteDatItem(xtw, rom, ignoreblanks);
// Set the new data to compare against
lastgame = rom.MachineName;
@@ -637,10 +637,10 @@ namespace SabreTools.Library.DatFiles
}
// Write the file footer out
WriteFooter(sw);
WriteFooter(xtw);
Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose();
xtw.Dispose();
fs.Dispose();
}
catch (Exception ex)
@@ -655,21 +655,20 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DAT header using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteHeader(StreamWriter sw)
private bool WriteHeader(XmlTextWriter xtw)
{
try
{
string header = "<?xml version=\"1.0\"?>\n" +
"<mame build=\"" + WebUtility.HtmlEncode(Name) + "\"" +
// " debug=\"" + Debug + "\"" +
// " mameconfig=\"" + MameConfig + "\"" +
">\n\n";
xtw.WriteStartDocument();
// Write the header out
sw.Write(header);
sw.Flush();
xtw.WriteStartElement("mame");
xtw.WriteAttributeString("build", Name);
//xtw.WriteAttributeString("debug", Debug);
//xtw.WriteAttributeString("mameconfig", MameConfig);
xtw.Flush();
}
catch (Exception ex)
{
@@ -683,51 +682,66 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteStartGame(StreamWriter sw, DatItem rom)
private bool WriteStartGame(XmlTextWriter xtw, DatItem datItem)
{
try
{
// No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
datItem.MachineName = datItem.MachineName.TrimStart(Path.DirectorySeparatorChar);
// Build the state based on excluded fields
xtw.WriteStartElement("machine");
xtw.WriteAttributeString("name", datItem.GetField(Field.MachineName, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SourceFile, ExcludeFields)))
xtw.WriteElementString("sourcefile", datItem.SourceFile);
if (!ExcludeFields[(int)Field.MachineType])
{
rom.MachineName = rom.MachineName.Substring(1);
if ((datItem.MachineType & MachineType.Bios) != 0)
xtw.WriteAttributeString("isbios", "yes");
if ((datItem.MachineType & MachineType.Device) != 0)
xtw.WriteAttributeString("isdevice", "yes");
if ((datItem.MachineType & MachineType.Mechanical) != 0)
xtw.WriteAttributeString("ismechanical", "yes");
}
string state = "\t<machine name=\"" + (!ExcludeFields[(int)Field.MachineName] ? WebUtility.HtmlEncode(rom.MachineName) : "") + "\""
+ (!ExcludeFields[(int)Field.SourceFile] && rom.SourceFile != null ? " sourcefile=\"" + rom.SourceFile + "\"" : "")
+ (!ExcludeFields[(int)Field.MachineType] && (rom.MachineType & MachineType.Bios) != 0 ? " isbios=\"yes\"" : "")
+ (!ExcludeFields[(int)Field.MachineType] && (rom.MachineType & MachineType.Device) != 0 ? " isdevice=\"yes\"" : "")
+ (!ExcludeFields[(int)Field.MachineType] && (rom.MachineType & MachineType.Mechanical) != 0 ? " ismechanical=\"yes\"" : "")
+ (!ExcludeFields[(int)Field.Runnable] && rom.Runnable == true
? " runnable=\"yes\""
: (!ExcludeFields[(int)Field.Runnable] && rom.Runnable == false ? " runnable=\"no\"" : ""))
+ (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) || (rom.MachineName.ToLowerInvariant() == rom.CloneOf.ToLowerInvariant())
? ""
: " cloneof=\"" + WebUtility.HtmlEncode(rom.CloneOf) + "\"")
+ (!ExcludeFields[(int)Field.RomOf] && String.IsNullOrWhiteSpace(rom.RomOf) || (rom.MachineName.ToLowerInvariant() == rom.RomOf.ToLowerInvariant())
? ""
: " romof=\"" + WebUtility.HtmlEncode(rom.RomOf) + "\"")
+ (!ExcludeFields[(int)Field.SampleOf] && String.IsNullOrWhiteSpace(rom.SampleOf) || (rom.MachineName.ToLowerInvariant() == rom.SampleOf.ToLowerInvariant())
? ""
: " sampleof=\"" + WebUtility.HtmlEncode(rom.SampleOf) + "\"")
+ ">\n"
+ (!ExcludeFields[(int)Field.Description] ? "\t\t<description>" + WebUtility.HtmlEncode(rom.MachineDescription) + "</description>\n" : "")
+ (!ExcludeFields[(int)Field.Year] && rom.Year != null ? "\t\t<year>" + WebUtility.HtmlEncode(rom.Year) + "</year>\n" : "")
+ (!ExcludeFields[(int)Field.Publisher] && rom.Publisher != null ? "\t\t<publisher>" + WebUtility.HtmlEncode(rom.Publisher) + "</publisher>\n" : "");
if (!ExcludeFields[(int)Field.Infos] && rom.Infos != null && rom.Infos.Count > 0)
if (!ExcludeFields[(int)Field.Runnable])
{
foreach (Tuple<string, string> kvp in rom.Infos)
if (datItem.Runnable == true)
xtw.WriteAttributeString("runnable", "yes");
else if (datItem.Runnable == false)
xtw.WriteAttributeString("runnable", "no");
}
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CloneOf, ExcludeFields)) && !string.Equals(datItem.MachineName, datItem.CloneOf, StringComparison.OrdinalIgnoreCase))
xtw.WriteAttributeString("cloneof", datItem.CloneOf);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RomOf, ExcludeFields)) && !string.Equals(datItem.MachineName, datItem.RomOf, StringComparison.OrdinalIgnoreCase))
xtw.WriteAttributeString("romof", datItem.RomOf);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SampleOf, ExcludeFields)) && !string.Equals(datItem.MachineName, datItem.SampleOf, StringComparison.OrdinalIgnoreCase))
xtw.WriteAttributeString("sampleof", datItem.SampleOf);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Description, ExcludeFields)))
xtw.WriteElementString("description", datItem.MachineDescription);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Year, ExcludeFields)))
xtw.WriteElementString("year", datItem.Year);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Publisher, ExcludeFields)))
xtw.WriteElementString("publisher", datItem.Publisher);
if (!ExcludeFields[(int)Field.Infos] && datItem.Infos != null && datItem.Infos.Count > 0)
{
foreach (Tuple<string, string> kvp in datItem.Infos)
{
state += "\t\t<info name=\"" + WebUtility.HtmlEncode(kvp.Item1) + "\" value=\"" + WebUtility.HtmlEncode(kvp.Item2) + "\" />\n";
xtw.WriteStartElement("info");
xtw.WriteAttributeString("name", kvp.Item1);
xtw.WriteAttributeString("value", kvp.Item2);
xtw.WriteEndElement();
}
}
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -741,16 +755,16 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteEndGame(StreamWriter sw)
private bool WriteEndGame(XmlTextWriter xtw)
{
try
{
string state = "\t</machine>\n";
// End machine
xtw.WriteEndElement();
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -764,84 +778,109 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(XmlTextWriter xtw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "";
// Pre-process the item name
ProcessItemName(rom, true);
ProcessItemName(datItem, true);
switch (rom.ItemType)
// Build the state based on excluded fields
switch (datItem.ItemType)
{
case ItemType.Archive:
break;
case ItemType.BiosSet: // TODO: Separate out MachineDescription from Description
state += "\t\t<biosset name\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.BiosDescription] && !String.IsNullOrWhiteSpace(((BiosSet)rom).Description) ? " description=\"" + WebUtility.HtmlEncode(((BiosSet)rom).Description) + "\"" : "")
+ (!ExcludeFields[(int)Field.Default] && ((BiosSet)rom).Default != null
? ((BiosSet)rom).Default.ToString().ToLowerInvariant()
: "")
+ "/>\n";
case ItemType.BiosSet:
var biosSet = datItem as BiosSet;
xtw.WriteStartElement("biosset");
xtw.WriteAttributeString("name", biosSet.GetField(Field.Name, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.BiosDescription, ExcludeFields)))
xtw.WriteAttributeString("description", biosSet.Description);
if (!ExcludeFields[(int)Field.Default] && biosSet.Default != null)
xtw.WriteAttributeString("default", biosSet.Default.ToString().ToLowerInvariant());
xtw.WriteEndElement();
break;
case ItemType.Disk:
state += "\t\t<disk name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.MD5] && !String.IsNullOrWhiteSpace(((Disk)rom).MD5) ? " md5=\"" + ((Disk)rom).MD5.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.RIPEMD160] && !String.IsNullOrWhiteSpace(((Disk)rom).RIPEMD160) ? " ripemd160=\"" + ((Disk)rom).RIPEMD160.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA1] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA1) ? " sha1=\"" + ((Disk)rom).SHA1.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA256] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA256) ? " sha256=\"" + ((Disk)rom).SHA256.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA384] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA384) ? " sha384=\"" + ((Disk)rom).SHA384.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA512] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA512) ? " sha512=\"" + ((Disk)rom).SHA512.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Merge] && !String.IsNullOrWhiteSpace(((Disk)rom).MergeTag) ? " merge=\"" + ((Disk)rom).MergeTag + "\"" : "")
+ (!ExcludeFields[(int)Field.Region] && !String.IsNullOrWhiteSpace(((Disk)rom).Region) ? " region=\"" + ((Disk)rom).Region + "\"" : "")
+ (!ExcludeFields[(int)Field.Index] && !String.IsNullOrWhiteSpace(((Disk)rom).Index) ? " index=\"" + ((Disk)rom).Index + "\"" : "")
+ (!ExcludeFields[(int)Field.Writable] && ((Disk)rom).Writable != null ? " writable=\"" + (((Disk)rom).Writable == true ? "yes" : "no") + "\"" : "")
+ (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus != ItemStatus.None ? " status=\"" + ((Disk)rom).ItemStatus.ToString().ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Optional] && ((Disk)rom).Optional != null ? " optional=\"" + (((Disk)rom).Optional == true ? "yes" : "no") + "\"" : "")
+ "/>\n";
break;
case ItemType.Release:
//TODO: Am I missing this?
var disk = datItem as Disk;
xtw.WriteStartElement("disk");
xtw.WriteAttributeString("name", disk.GetField(Field.Name, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
xtw.WriteAttributeString("md5", disk.MD5.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RIPEMD160, ExcludeFields)))
xtw.WriteAttributeString("ripemd160", disk.RIPEMD160.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
xtw.WriteAttributeString("sha1", disk.SHA1.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA256, ExcludeFields)))
xtw.WriteAttributeString("sha256", disk.SHA256.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA384, ExcludeFields)))
xtw.WriteAttributeString("sha384", disk.SHA384.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA512, ExcludeFields)))
xtw.WriteAttributeString("sha512", disk.SHA512.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Merge, ExcludeFields)))
xtw.WriteAttributeString("merge", disk.MergeTag);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Region, ExcludeFields)))
xtw.WriteAttributeString("region", disk.Region);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Index, ExcludeFields)))
xtw.WriteAttributeString("index", disk.Index);
if (!ExcludeFields[(int)Field.Writable] && disk.Writable != null)
xtw.WriteAttributeString("writable", disk.Writable == true ? "yes" : "no");
if (!ExcludeFields[(int)Field.Status] && disk.ItemStatus != ItemStatus.None)
xtw.WriteAttributeString("status", disk.ItemStatus.ToString());
if (!ExcludeFields[(int)Field.Optional] && disk.Optional != null)
xtw.WriteAttributeString("optional", disk.Optional == true ? "yes" : "no");
xtw.WriteEndElement();
break;
case ItemType.Rom:
state += "\t\t<rom name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? " size=\"" + ((Rom)rom).Size + "\"" : "")
+ (!ExcludeFields[(int)Field.CRC] && !String.IsNullOrWhiteSpace(((Rom)rom).CRC) ? " crc=\"" + ((Rom)rom).CRC.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.MD5] && !String.IsNullOrWhiteSpace(((Rom)rom).MD5) ? " md5=\"" + ((Rom)rom).MD5.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.RIPEMD160] && !String.IsNullOrWhiteSpace(((Rom)rom).RIPEMD160) ? " ripemd160=\"" + ((Rom)rom).RIPEMD160.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA1] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA1) ? " sha1=\"" + ((Rom)rom).SHA1.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA256] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA256) ? " sha256=\"" + ((Rom)rom).SHA256.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA384] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA384) ? " sha384=\"" + ((Rom)rom).SHA384.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA512] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA512) ? " sha512=\"" + ((Rom)rom).SHA512.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Bios] && !String.IsNullOrWhiteSpace(((Rom)rom).Bios) ? " bios=\"" + ((Rom)rom).Bios + "\"" : "")
+ (!ExcludeFields[(int)Field.Merge] && !String.IsNullOrWhiteSpace(((Rom)rom).MergeTag) ? " merge=\"" + ((Rom)rom).MergeTag + "\"" : "")
+ (!ExcludeFields[(int)Field.Region] && !String.IsNullOrWhiteSpace(((Rom)rom).Region) ? " region=\"" + ((Rom)rom).Region + "\"" : "")
+ (!ExcludeFields[(int)Field.Offset] && !String.IsNullOrWhiteSpace(((Rom)rom).Offset) ? " offset=\"" + ((Rom)rom).Offset + "\"" : "")
+ (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus != ItemStatus.None ? " status=\"" + ((Rom)rom).ItemStatus.ToString().ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Optional] && ((Rom)rom).Optional != null ? " optional=\"" + (((Rom)rom).Optional == true ? "yes" : "no") + "\"" : "")
+ "/>\n";
var rom = datItem as Rom;
xtw.WriteStartElement("rom");
xtw.WriteAttributeString("name", rom.GetField(Field.Name, ExcludeFields));
if (!ExcludeFields[(int)Field.Size] && rom.Size != -1)
xtw.WriteAttributeString("size", rom.Size.ToString());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
xtw.WriteAttributeString("crc", rom.CRC.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
xtw.WriteAttributeString("md5", rom.MD5.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RIPEMD160, ExcludeFields)))
xtw.WriteAttributeString("ripemd160", rom.RIPEMD160.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
xtw.WriteAttributeString("sha1", rom.SHA1.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA256, ExcludeFields)))
xtw.WriteAttributeString("sha256", rom.SHA256.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA384, ExcludeFields)))
xtw.WriteAttributeString("sha384", rom.SHA384.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA512, ExcludeFields)))
xtw.WriteAttributeString("sha512", rom.SHA512.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Bios, ExcludeFields)))
xtw.WriteAttributeString("bios", rom.Bios);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Merge, ExcludeFields)))
xtw.WriteAttributeString("merge", rom.MergeTag);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Region, ExcludeFields)))
xtw.WriteAttributeString("region", rom.Region);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Offset, ExcludeFields)))
xtw.WriteAttributeString("offset", rom.Offset);
if (!ExcludeFields[(int)Field.Status] && rom.ItemStatus != ItemStatus.None)
xtw.WriteAttributeString("status", rom.ItemStatus.ToString().ToLowerInvariant());
if (!ExcludeFields[(int)Field.Optional] && rom.Optional != null)
xtw.WriteAttributeString("optional", rom.Optional == true ? "yes" : "no");
xtw.WriteEndElement();
break;
case ItemType.Sample:
state += "\t\t<sample name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ "/>\n";
xtw.WriteStartElement("sample");
xtw.WriteAttributeString("name", datItem.GetField(Field.Name, ExcludeFields));
xtw.WriteEndElement();
break;
}
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -855,17 +894,19 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DAT footer using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteFooter(StreamWriter sw)
private bool WriteFooter(XmlTextWriter xtw)
{
try
{
string footer = "\t</machine>\n</mame>\n";
// End machine
xtw.WriteEndElement();
// Write the footer out
sw.Write(footer);
sw.Flush();
// End mame
xtw.WriteEndElement();
xtw.Flush();
}
catch (Exception ex)
{

View File

@@ -1,22 +1,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -29,17 +21,17 @@ namespace SabreTools.Library.DatFiles
internal class Logiqx : DatFile
{
// Private instance variables specific to Logiqx DATs
bool _depreciated;
private readonly bool _deprecated;
/// <summary>
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
/// <param name="depreciated">True if the output uses "game", false if the output uses "machine"</param>
public Logiqx(DatFile datFile, bool depreciated)
/// <param name="deprecated">True if the output uses "game", false if the output uses "machine"</param>
public Logiqx(DatFile datFile, bool deprecated)
: base(datFile, cloneHeader: false)
{
_depreciated = depreciated;
_deprecated = deprecated;
}
/// <summary>
@@ -69,9 +61,7 @@ namespace SabreTools.Library.DatFiles
// If we got a null reader, just return
if (xtr == null)
{
return;
}
// Otherwise, read the file to the end
try
@@ -84,9 +74,7 @@ namespace SabreTools.Library.DatFiles
{
// If we're ending a dir, remove the last item from the dirs list, if possible
if (xtr.Name == "dir" && dirs.Count > 0)
{
dirs.RemoveAt(dirs.Count - 1);
}
xtr.Read();
continue;
@@ -100,6 +88,7 @@ namespace SabreTools.Library.DatFiles
// string debug = xtr.GetAttribute("debug"); // (yes|no) "no"
xtr.Read();
break;
// We want to process the entire subtree of the header
case "header":
ReadHeader(xtr.ReadSubtree(), keep);
@@ -107,12 +96,14 @@ namespace SabreTools.Library.DatFiles
// Skip the header node now that we've processed it
xtr.Skip();
break;
// Unique to RomVault-created DATs
case "dir":
Type = "SuperDAT";
dirs.Add(xtr.GetAttribute("name") ?? "");
dirs.Add(xtr.GetAttribute("name") ?? string.Empty);
xtr.Read();
break;
// We want to process the entire subtree of the game
case "machine": // New-style Logiqx
case "game": // Old-style Logiqx
@@ -121,6 +112,7 @@ namespace SabreTools.Library.DatFiles
// Skip the machine now that we've processed it
xtr.Skip();
break;
default:
xtr.Read();
break;
@@ -129,7 +121,7 @@ namespace SabreTools.Library.DatFiles
}
catch (Exception ex)
{
Globals.Logger.Warning("Exception found while parsing '{0}': {1}", filename, ex);
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
// For XML errors, just skip the affected node
xtr?.Read();
@@ -149,9 +141,7 @@ namespace SabreTools.Library.DatFiles
// If there's no subtree to the header, skip it
if (reader == null)
{
return;
}
// Otherwise, add what is possible
reader.MoveToContent();
@@ -166,111 +156,127 @@ namespace SabreTools.Library.DatFiles
}
// Get all header items (ONLY OVERWRITE IF THERE'S NO DATA)
string content = "";
string content = string.Empty;
switch (reader.Name)
{
case "name":
content = reader.ReadElementContentAsString(); ;
Name = (String.IsNullOrWhiteSpace(Name) ? content : Name);
Name = (string.IsNullOrWhiteSpace(Name) ? content : Name);
superdat = superdat || content.Contains(" - SuperDAT");
if (keep && superdat)
{
Type = (String.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
Type = (string.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
}
break;
case "description":
content = reader.ReadElementContentAsString();
Description = (String.IsNullOrWhiteSpace(Description) ? content : Description);
Description = (string.IsNullOrWhiteSpace(Description) ? content : Description);
break;
case "rootdir": // This is exclusive to TruRip XML
content = reader.ReadElementContentAsString();
RootDir = (String.IsNullOrWhiteSpace(RootDir) ? content : RootDir);
RootDir = (string.IsNullOrWhiteSpace(RootDir) ? content : RootDir);
break;
case "category":
content = reader.ReadElementContentAsString();
Category = (String.IsNullOrWhiteSpace(Category) ? content : Category);
Category = (string.IsNullOrWhiteSpace(Category) ? content : Category);
break;
case "version":
content = reader.ReadElementContentAsString();
Version = (String.IsNullOrWhiteSpace(Version) ? content : Version);
Version = (string.IsNullOrWhiteSpace(Version) ? content : Version);
break;
case "date":
content = reader.ReadElementContentAsString();
Date = (String.IsNullOrWhiteSpace(Date) ? content.Replace(".", "/") : Date);
Date = (string.IsNullOrWhiteSpace(Date) ? content.Replace(".", "/") : Date);
break;
case "author":
content = reader.ReadElementContentAsString();
Author = (String.IsNullOrWhiteSpace(Author) ? content : Author);
Author = (string.IsNullOrWhiteSpace(Author) ? content : Author);
break;
case "email":
content = reader.ReadElementContentAsString();
Email = (String.IsNullOrWhiteSpace(Email) ? content : Email);
Email = (string.IsNullOrWhiteSpace(Email) ? content : Email);
break;
case "homepage":
content = reader.ReadElementContentAsString();
Homepage = (String.IsNullOrWhiteSpace(Homepage) ? content : Homepage);
Homepage = (string.IsNullOrWhiteSpace(Homepage) ? content : Homepage);
break;
case "url":
content = reader.ReadElementContentAsString();
Url = (String.IsNullOrWhiteSpace(Url) ? content : Url);
Url = (string.IsNullOrWhiteSpace(Url) ? content : Url);
break;
case "comment":
content = reader.ReadElementContentAsString();
Comment = (String.IsNullOrWhiteSpace(Comment) ? content : Comment);
Comment = (string.IsNullOrWhiteSpace(Comment) ? content : Comment);
break;
case "type": // This is exclusive to TruRip XML
content = reader.ReadElementContentAsString();
Type = (String.IsNullOrWhiteSpace(Type) ? content : Type);
Type = (string.IsNullOrWhiteSpace(Type) ? content : Type);
superdat = superdat || content.Contains("SuperDAT");
break;
case "clrmamepro":
if (String.IsNullOrWhiteSpace(Header))
{
if (string.IsNullOrWhiteSpace(Header))
Header = reader.GetAttribute("header");
}
if (ForceMerging == ForceMerging.None)
{
ForceMerging = Utilities.GetForceMerging(reader.GetAttribute("forcemerging"));
}
if (ForceNodump == ForceNodump.None)
{
ForceNodump = Utilities.GetForceNodump(reader.GetAttribute("forcenodump"));
}
if (ForcePacking == ForcePacking.None)
{
ForcePacking = Utilities.GetForcePacking(reader.GetAttribute("forcepacking"));
}
reader.Read();
break;
case "romcenter":
if (reader.GetAttribute("plugin") != null)
{
// CDATA
}
if (reader.GetAttribute("rommode") != null)
{
// (merged|split|unmerged) "split"
}
if (reader.GetAttribute("biosmode") != null)
{
// merged|split|unmerged) "split"
}
if (reader.GetAttribute("samplemode") != null)
{
// (merged|unmerged) "merged"
}
if (reader.GetAttribute("lockrommode") != null)
{
// (yes|no) "no"
}
if (reader.GetAttribute("lockbiosmode") != null)
{
// (yes|no) "no"
}
if (reader.GetAttribute("locksamplemode") != null)
{
// (yes|no) "no"
}
reader.Read();
break;
default:
@@ -307,33 +313,27 @@ namespace SabreTools.Library.DatFiles
{
// If we have an empty machine, skip it
if (reader == null)
{
return;
}
// Otherwise, add what is possible
reader.MoveToContent();
string key = "";
string key = string.Empty;
string temptype = reader.Name;
bool containsItems = false;
// Create a new machine
MachineType machineType = MachineType.NULL;
if (Utilities.GetYesNo(reader.GetAttribute("isbios")) == true)
{
machineType |= MachineType.Bios;
}
if (Utilities.GetYesNo(reader.GetAttribute("isdevice")) == true) // Listxml-specific, used by older DATs
{
machineType |= MachineType.Device;
}
if (Utilities.GetYesNo(reader.GetAttribute("ismechanical")) == true) // Listxml-specific, used by older DATs
{
machineType |= MachineType.Mechanical;
}
string dirsString = (dirs != null && dirs.Count() > 0 ? string.Join("/", dirs) + "/" : "");
if (Utilities.GetYesNo(reader.GetAttribute("isdevice")) == true) // Listxml-specific, used by older DATs
machineType |= MachineType.Device;
if (Utilities.GetYesNo(reader.GetAttribute("ismechanical")) == true) // Listxml-specific, used by older DATs
machineType |= MachineType.Mechanical;
string dirsString = (dirs != null && dirs.Count() > 0 ? string.Join("/", dirs) + "/" : string.Empty);
Machine machine = new Machine
{
Name = dirsString + reader.GetAttribute("name"),
@@ -343,11 +343,11 @@ namespace SabreTools.Library.DatFiles
RebuildTo = reader.GetAttribute("rebuildto"),
Runnable = Utilities.GetYesNo(reader.GetAttribute("runnable")), // Listxml-specific, used by older DATs
Comment = "",
Comment = string.Empty,
CloneOf = reader.GetAttribute("cloneof") ?? "",
RomOf = reader.GetAttribute("romof") ?? "",
SampleOf = reader.GetAttribute("sampleof") ?? "",
CloneOf = reader.GetAttribute("cloneof") ?? string.Empty,
RomOf = reader.GetAttribute("romof") ?? string.Empty,
SampleOf = reader.GetAttribute("sampleof") ?? string.Empty,
MachineType = (machineType == MachineType.NULL ? MachineType.None : machineType),
};
@@ -355,10 +355,8 @@ namespace SabreTools.Library.DatFiles
if (Type == "SuperDAT" && !keep)
{
string tempout = Regex.Match(machine.Name, @".*?\\(.*)").Groups[1].Value;
if (!String.IsNullOrWhiteSpace(tempout))
{
if (!string.IsNullOrWhiteSpace(tempout))
machine.Name = tempout;
}
}
while (!reader.EOF)
@@ -376,24 +374,30 @@ namespace SabreTools.Library.DatFiles
case "comment": // There can be multiple comments by spec
machine.Comment += reader.ReadElementContentAsString();
break;
case "description":
machine.Description = reader.ReadElementContentAsString();
break;
case "year":
machine.Year = reader.ReadElementContentAsString();
break;
case "manufacturer":
machine.Manufacturer = reader.ReadElementContentAsString();
break;
case "publisher": // Not technically supported but used by some legacy DATs
machine.Publisher = reader.ReadElementContentAsString();
break;
case "trurip": // This is special metadata unique to TruRip
ReadTruRip(reader.ReadSubtree(), machine);
// Skip the trurip node now that we've processed it
reader.Skip();
break;
case "release":
containsItems = true;
@@ -413,6 +417,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "biosset":
containsItems = true;
@@ -434,6 +439,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "rom":
containsItems = true;
@@ -464,6 +470,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "disk":
containsItems = true;
@@ -491,6 +498,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "sample":
containsItems = true;
@@ -510,6 +518,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
case "archive":
containsItems = true;
@@ -529,6 +538,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
default:
reader.Read();
break;
@@ -560,9 +570,7 @@ namespace SabreTools.Library.DatFiles
{
// If we have an empty trurip, skip it
if (reader == null)
{
return;
}
// Otherwise, add what is possible
reader.MoveToContent();
@@ -577,60 +585,74 @@ namespace SabreTools.Library.DatFiles
}
// Get the information from the trurip
string content = "";
string content = string.Empty;
switch (reader.Name)
{
case "titleid":
content = reader.ReadElementContentAsString();
// string titleid = content;
break;
case "publisher":
machine.Publisher = reader.ReadElementContentAsString();
break;
case "developer": // Manufacturer is as close as this gets
machine.Manufacturer = reader.ReadElementContentAsString();
break;
case "year":
machine.Year = reader.ReadElementContentAsString();
break;
case "genre":
content = reader.ReadElementContentAsString();
// string genre = content;
break;
case "subgenre":
content = reader.ReadElementContentAsString();
// string subgenre = content;
break;
case "ratings":
content = reader.ReadElementContentAsString();
// string ratings = content;
break;
case "score":
content = reader.ReadElementContentAsString();
// string score = content;
break;
case "players":
content = reader.ReadElementContentAsString();
// string players = content;
break;
case "enabled":
content = reader.ReadElementContentAsString();
// string enabled = content;
break;
case "crc":
content = reader.ReadElementContentAsString();
// string crc = Utilities.GetYesNo(content);
break;
case "source":
machine.SourceFile = reader.ReadElementContentAsString();
break;
case "cloneof":
machine.CloneOf = reader.ReadElementContentAsString();
break;
case "relatedto":
content = reader.ReadElementContentAsString();
// string relatedto = content;
break;
default:
reader.Read();
break;
@@ -648,20 +670,21 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
XmlTextWriter xtw = new XmlTextWriter(fs, new UTF8Encoding(false));
xtw.Formatting = Formatting.Indented;
// Write out the header
WriteHeader(sw);
WriteHeader(xtw);
// Write out each of the machines and roms
string lastgame = null;
@@ -690,22 +713,18 @@ namespace SabreTools.Library.DatFiles
// 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.MachineName.ToLowerInvariant())
{
WriteEndGame(sw);
}
WriteEndGame(xtw);
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{
WriteStartGame(sw, rom);
}
WriteStartGame(xtw, rom);
// If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
rom.Name = (rom.Name == "null" ? "-" : rom.Name);
((Rom)rom).Size = Constants.SizeZero;
@@ -719,7 +738,7 @@ namespace SabreTools.Library.DatFiles
}
// Now, output the rom data
WriteDatItem(sw, rom, ignoreblanks);
WriteDatItem(xtw, rom, ignoreblanks);
// Set the new data to compare against
lastgame = rom.MachineName;
@@ -727,10 +746,10 @@ namespace SabreTools.Library.DatFiles
}
// Write the file footer out
WriteFooter(sw);
WriteFooter(xtw);
Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose();
xtw.Dispose();
fs.Dispose();
}
catch (Exception ex)
@@ -745,47 +764,91 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DAT header using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteHeader(StreamWriter sw)
private bool WriteHeader(XmlTextWriter xtw)
{
try
{
string 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>" + WebUtility.HtmlEncode(Name) + "</name>\n" +
"\t\t<description>" + WebUtility.HtmlEncode(Description) + "</description>\n" +
(!String.IsNullOrWhiteSpace(RootDir) ? "\t\t<rootdir>" + WebUtility.HtmlEncode(RootDir) + "</rootdir>\n" : "") +
(!String.IsNullOrWhiteSpace(Category) ? "\t\t<category>" + WebUtility.HtmlEncode(Category) + "</category>\n" : "") +
"\t\t<version>" + WebUtility.HtmlEncode(Version) + "</version>\n" +
(!String.IsNullOrWhiteSpace(Date) ? "\t\t<date>" + WebUtility.HtmlEncode(Date) + "</date>\n" : "") +
"\t\t<author>" + WebUtility.HtmlEncode(Author) + "</author>\n" +
(!String.IsNullOrWhiteSpace(Email) ? "\t\t<email>" + WebUtility.HtmlEncode(Email) + "</email>\n" : "") +
(!String.IsNullOrWhiteSpace(Homepage) ? "\t\t<homepage>" + WebUtility.HtmlEncode(Homepage) + "</homepage>\n" : "") +
(!String.IsNullOrWhiteSpace(Url) ? "\t\t<url>" + WebUtility.HtmlEncode(Url) + "</url>\n" : "") +
(!String.IsNullOrWhiteSpace(Comment) ? "\t\t<comment>" + WebUtility.HtmlEncode(Comment) + "</comment>\n" : "") +
(!String.IsNullOrWhiteSpace(Type) ? "\t\t<type>" + WebUtility.HtmlEncode(Type) + "</type>\n" : "") +
(ForcePacking != ForcePacking.None || ForceMerging != ForceMerging.None || ForceNodump != ForceNodump.None || !String.IsNullOrWhiteSpace(Header) ?
"\t\t<clrmamepro" +
(ForcePacking == ForcePacking.Unzip ? " forcepacking=\"unzip\"" : "") +
(ForcePacking == ForcePacking.Zip ? " forcepacking=\"zip\"" : "") +
(ForceMerging == ForceMerging.Full ? " forcemerging=\"full\"" : "") +
(ForceMerging == ForceMerging.Split ? " forcemerging=\"split\"" : "") +
(ForceMerging == ForceMerging.Merged ? " forcemerging=\"merged\"" : "") +
(ForceMerging == ForceMerging.NonMerged ? " forcemerging=\"nonmerged\"" : "") +
(ForceNodump == ForceNodump.Ignore ? " forcenodump=\"ignore\"" : "") +
(ForceNodump == ForceNodump.Obsolete ? " forcenodump=\"obsolete\"" : "") +
(ForceNodump == ForceNodump.Required ? " forcenodump=\"required\"" : "") +
(!String.IsNullOrWhiteSpace(Header) ? " header=\"" + Header + "\"" : "") +
" />\n"
: "") +
"\t</header>\n";
xtw.WriteStartDocument();
xtw.WriteDocType("datafile", "-//Logiqx//DTD ROM Management Datafile//EN", "http://www.logiqx.com/Dats/datafile.dtd", null);
xtw.WriteStartElement("datafile");
xtw.WriteStartElement("header");
xtw.WriteElementString("name", Name);
xtw.WriteElementString("description", Description);
if (!string.IsNullOrWhiteSpace(RootDir))
xtw.WriteElementString("rootdir", RootDir);
if (!string.IsNullOrWhiteSpace(Category))
xtw.WriteElementString("category", Category);
xtw.WriteElementString("version", Version);
if (!string.IsNullOrWhiteSpace(Date))
xtw.WriteElementString("date", Date);
xtw.WriteElementString("author", Author);
if (!string.IsNullOrWhiteSpace(Email))
xtw.WriteElementString("email", Email);
if (!string.IsNullOrWhiteSpace(Homepage))
xtw.WriteElementString("homepage", Homepage);
if (!string.IsNullOrWhiteSpace(Url))
xtw.WriteElementString("url", Url);
if (!string.IsNullOrWhiteSpace(Comment))
xtw.WriteElementString("comment", Comment);
if (!string.IsNullOrWhiteSpace(Type))
xtw.WriteElementString("type", Type);
// Write the header out
sw.Write(header);
sw.Flush();
if (ForcePacking != ForcePacking.None
|| ForceMerging != ForceMerging.None
|| ForceNodump != ForceNodump.None
|| !string.IsNullOrWhiteSpace(Header))
{
xtw.WriteStartElement("clrmamepro");
switch (ForcePacking)
{
case ForcePacking.Unzip:
xtw.WriteAttributeString("forcepacking", "unzip");
break;
case ForcePacking.Zip:
xtw.WriteAttributeString("forcepacking", "zip");
break;
}
switch (ForceMerging)
{
case ForceMerging.Full:
xtw.WriteAttributeString("forcemerging", "full");
break;
case ForceMerging.Split:
xtw.WriteAttributeString("forcemerging", "split");
break;
case ForceMerging.Merged:
xtw.WriteAttributeString("forcemerging", "merged");
break;
case ForceMerging.NonMerged:
xtw.WriteAttributeString("forcemerging", "nonmerged");
break;
}
switch (ForceNodump)
{
case ForceNodump.Ignore:
xtw.WriteAttributeString("forcenodump", "ignore");
break;
case ForceNodump.Obsolete:
xtw.WriteAttributeString("forcenodump", "obsolete");
break;
case ForceNodump.Required:
xtw.WriteAttributeString("forcenodump", "required");
break;
}
if (!string.IsNullOrWhiteSpace(Header))
xtw.WriteAttributeString("header", Header);
xtw.WriteEndElement();
}
xtw.Flush();
}
catch (Exception ex)
{
@@ -799,44 +862,56 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteStartGame(StreamWriter sw, DatItem rom)
private bool WriteStartGame(XmlTextWriter xtw, DatItem datItem)
{
try
{
// No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
datItem.MachineName = datItem.MachineName.TrimStart(Path.DirectorySeparatorChar);
// Build the state based on excluded fields
xtw.WriteStartElement(_deprecated ? "game" : "machine");
xtw.WriteAttributeString("name", datItem.GetField(Field.MachineName, ExcludeFields));
if (!ExcludeFields[(int)Field.MachineType])
{
rom.MachineName = rom.MachineName.Substring(1);
if ((datItem.MachineType & MachineType.Bios) != 0)
xtw.WriteAttributeString("isbios", "yes");
if ((datItem.MachineType & MachineType.Device) != 0)
xtw.WriteAttributeString("isdevice", "yes");
if ((datItem.MachineType & MachineType.Mechanical) != 0)
xtw.WriteAttributeString("ismechanical", "yes");
}
string state = "\t<" + (_depreciated ? "game" : "machine") + " name=\"" + (!ExcludeFields[(int)Field.MachineName] ? WebUtility.HtmlEncode(rom.MachineName) : "") + "\""
+ (!ExcludeFields[(int)Field.MachineType] && (rom.MachineType & MachineType.Bios) != 0 ? " isbios=\"yes\"" : "")
+ (!ExcludeFields[(int)Field.MachineType] && (rom.MachineType & MachineType.Device) != 0 ? " isdevice=\"yes\"" : "")
+ (!ExcludeFields[(int)Field.MachineType] && (rom.MachineType & MachineType.Mechanical) != 0 ? " ismechanical=\"yes\"" : "")
+ (!ExcludeFields[(int)Field.Runnable] && rom.Runnable == true
? " runnable=\"yes\""
: (!ExcludeFields[(int)Field.Runnable] && rom.Runnable == false ? " runnable=\"no\"" : ""))
+ (!ExcludeFields[(int)Field.CloneOf] && !String.IsNullOrWhiteSpace(rom.CloneOf) && (rom.MachineName.ToLowerInvariant() != rom.CloneOf.ToLowerInvariant())
? " cloneof=\"" + WebUtility.HtmlEncode(rom.CloneOf) + "\""
: "")
+ (!ExcludeFields[(int)Field.RomOf] && !String.IsNullOrWhiteSpace(rom.RomOf) && (rom.MachineName.ToLowerInvariant() != rom.RomOf.ToLowerInvariant())
? " romof=\"" + WebUtility.HtmlEncode(rom.RomOf) + "\""
: "")
+ (!ExcludeFields[(int)Field.SampleOf] && !String.IsNullOrWhiteSpace(rom.SampleOf) && (rom.MachineName.ToLowerInvariant() != rom.SampleOf.ToLowerInvariant())
? " sampleof=\"" + WebUtility.HtmlEncode(rom.SampleOf) + "\""
: "")
+ ">\n"
+ (!ExcludeFields[(int)Field.Comment] && !String.IsNullOrWhiteSpace(rom.Comment) ? "\t\t<comment>" + WebUtility.HtmlEncode(rom.Comment) + "</comment>\n" : "")
+ (!ExcludeFields[(int)Field.Description] ? "\t\t<description>" + WebUtility.HtmlEncode((String.IsNullOrWhiteSpace(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription)) + "</description>\n" : "")
+ (!ExcludeFields[(int)Field.Year] && !String.IsNullOrWhiteSpace(rom.Year) ? "\t\t<year>" + WebUtility.HtmlEncode(rom.Year) + "</year>\n" : "")
+ (!ExcludeFields[(int)Field.Publisher] && !String.IsNullOrWhiteSpace(rom.Publisher) ? "\t\t<publisher>" + WebUtility.HtmlEncode(rom.Publisher) + "</publisher>\n" : "")
+ (!ExcludeFields[(int)Field.Manufacturer] && !String.IsNullOrWhiteSpace(rom.Manufacturer) ? "\t\t<manufacturer>" + WebUtility.HtmlEncode(rom.Manufacturer) + "</manufacturer>\n" : "");
if (!ExcludeFields[(int)Field.Runnable] && datItem.Runnable != null)
{
if (datItem.Runnable == true)
xtw.WriteAttributeString("runnable", "yes");
else if (datItem.Runnable == false)
xtw.WriteAttributeString("runnable", "no");
}
sw.Write(state);
sw.Flush();
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CloneOf, ExcludeFields)) && !string.Equals(datItem.MachineName, datItem.CloneOf, StringComparison.OrdinalIgnoreCase))
xtw.WriteAttributeString("cloneof", datItem.CloneOf);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RomOf, ExcludeFields)) && !string.Equals(datItem.MachineName, datItem.RomOf, StringComparison.OrdinalIgnoreCase))
xtw.WriteAttributeString("romof", datItem.RomOf);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SampleOf, ExcludeFields)) && !string.Equals(datItem.MachineName, datItem.SampleOf, StringComparison.OrdinalIgnoreCase))
xtw.WriteAttributeString("sampleof", datItem.SampleOf);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Comment, ExcludeFields)))
xtw.WriteElementString("comment", datItem.Comment);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Description, ExcludeFields)))
xtw.WriteElementString("description", datItem.MachineDescription);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Year, ExcludeFields)))
xtw.WriteElementString("year", datItem.Year);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Publisher, ExcludeFields)))
xtw.WriteElementString("publisher", datItem.Publisher);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Manufacturer, ExcludeFields)))
xtw.WriteElementString("manufacturer", datItem.Manufacturer);
xtw.Flush();
}
catch (Exception ex)
{
@@ -850,16 +925,16 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out Game end using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteEndGame(StreamWriter sw)
private bool WriteEndGame(XmlTextWriter xtw)
{
try
{
string state = "\t</" + (_depreciated ? "game" : "machine") + ">\n";
// End machine
xtw.WriteEndElement();
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -873,84 +948,112 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(XmlTextWriter xtw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "";
// Pre-process the item name
ProcessItemName(rom, true);
ProcessItemName(datItem, true);
switch (rom.ItemType)
// Build the state based on excluded fields
switch (datItem.ItemType)
{
case ItemType.Archive:
state += "\t\t<archive name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ "/>\n";
xtw.WriteStartElement("archive");
xtw.WriteAttributeString("name", datItem.GetField(Field.Name, ExcludeFields));
xtw.WriteEndElement();
break;
case ItemType.BiosSet:
state += "\t\t<biosset name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.BiosDescription] && !String.IsNullOrWhiteSpace(((BiosSet)rom).Description) ? " description=\"" + WebUtility.HtmlEncode(((BiosSet)rom).Description) + "\"" : "")
+ (!ExcludeFields[(int)Field.Default] && ((BiosSet)rom).Default != null
? ((BiosSet)rom).Default.ToString().ToLowerInvariant()
: "")
+ "/>\n";
var biosSet = datItem as BiosSet;
xtw.WriteStartElement("biosset");
xtw.WriteAttributeString("name", biosSet.GetField(Field.Name, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.BiosDescription, ExcludeFields)))
xtw.WriteAttributeString("description", biosSet.Description);
if (!ExcludeFields[(int)Field.Default] && biosSet.Default != null)
xtw.WriteAttributeString("default", biosSet.Default.ToString().ToLowerInvariant());
xtw.WriteEndElement();
break;
case ItemType.Disk:
state += "\t\t<disk name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.MD5] && !String.IsNullOrWhiteSpace(((Disk)rom).MD5) ? " md5=\"" + ((Disk)rom).MD5.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.RIPEMD160] && !String.IsNullOrWhiteSpace(((Disk)rom).RIPEMD160) ? " ripemd160=\"" + ((Disk)rom).RIPEMD160.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA1] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA1) ? " sha1=\"" + ((Disk)rom).SHA1.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA256] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA256) ? " sha256=\"" + ((Disk)rom).SHA256.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA384] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA384) ? " sha384=\"" + ((Disk)rom).SHA384.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA512] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA512) ? " sha512=\"" + ((Disk)rom).SHA512.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus != ItemStatus.None ? " status=\"" + ((Disk)rom).ItemStatus.ToString().ToLowerInvariant() + "\"" : "")
+ "/>\n";
var disk = datItem as Disk;
xtw.WriteStartElement("disk");
xtw.WriteAttributeString("name", disk.GetField(Field.Name, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
xtw.WriteAttributeString("md5", disk.MD5.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RIPEMD160, ExcludeFields)))
xtw.WriteAttributeString("ripemd160", disk.RIPEMD160.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
xtw.WriteAttributeString("sha1", disk.SHA1.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA256, ExcludeFields)))
xtw.WriteAttributeString("sha256", disk.SHA256.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA384, ExcludeFields)))
xtw.WriteAttributeString("sha384", disk.SHA384.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA512, ExcludeFields)))
xtw.WriteAttributeString("sha512", disk.SHA512.ToLowerInvariant());
if (!ExcludeFields[(int)Field.Status] && disk.ItemStatus != ItemStatus.None)
xtw.WriteAttributeString("status", disk.ItemStatus.ToString().ToLowerInvariant());
xtw.WriteEndElement();
break;
case ItemType.Release:
state += "\t\t<release name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.Region] && !String.IsNullOrWhiteSpace(((Release)rom).Region) ? " region=\"" + WebUtility.HtmlEncode(((Release)rom).Region) + "\"" : "")
+ (!ExcludeFields[(int)Field.Language] && !String.IsNullOrWhiteSpace(((Release)rom).Language) ? " language=\"" + WebUtility.HtmlEncode(((Release)rom).Language) + "\"" : "")
+ (!ExcludeFields[(int)Field.Date] && !String.IsNullOrWhiteSpace(((Release)rom).Date) ? " date=\"" + WebUtility.HtmlEncode(((Release)rom).Date) + "\"" : "")
+ (!ExcludeFields[(int)Field.Default] && ((Release)rom).Default != null
? ((Release)rom).Default.ToString().ToLowerInvariant()
: "")
+ "/>\n";
var release = datItem as Release;
xtw.WriteStartElement("release");
xtw.WriteAttributeString("name", release.GetField(Field.Name, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Region, ExcludeFields)))
xtw.WriteAttributeString("region", release.Region);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Language, ExcludeFields)))
xtw.WriteAttributeString("language", release.Language);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Date, ExcludeFields)))
xtw.WriteAttributeString("date", release.Date);
if (!ExcludeFields[(int)Field.Default] && release.Default != null)
xtw.WriteAttributeString("default", release.Default.ToString().ToLowerInvariant());
xtw.WriteEndElement();
break;
case ItemType.Rom:
state += "\t\t<rom name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? " size=\"" + ((Rom)rom).Size + "\"" : "")
+ (!ExcludeFields[(int)Field.CRC] && !String.IsNullOrWhiteSpace(((Rom)rom).CRC) ? " crc=\"" + ((Rom)rom).CRC.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.MD5] && !String.IsNullOrWhiteSpace(((Rom)rom).MD5) ? " md5=\"" + ((Rom)rom).MD5.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.RIPEMD160] && !String.IsNullOrWhiteSpace(((Rom)rom).RIPEMD160) ? " ripemd160=\"" + ((Rom)rom).RIPEMD160.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA1] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA1) ? " sha1=\"" + ((Rom)rom).SHA1.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA256] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA256) ? " sha256=\"" + ((Rom)rom).SHA256.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA384] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA384) ? " sha384=\"" + ((Rom)rom).SHA384.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA512] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA512) ? " sha512=\"" + ((Rom)rom).SHA512.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Date] && !String.IsNullOrWhiteSpace(((Rom)rom).Date) ? " date=\"" + ((Rom)rom).Date + "\"" : "")
+ (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus != ItemStatus.None ? " status=\"" + ((Rom)rom).ItemStatus.ToString().ToLowerInvariant() + "\"" : "")
+ "/>\n";
var rom = datItem as Rom;
xtw.WriteStartElement("rom");
xtw.WriteAttributeString("name", rom.GetField(Field.Name, ExcludeFields));
if (!ExcludeFields[(int)Field.Size] && rom.Size != -1)
xtw.WriteAttributeString("size", rom.Size.ToString());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
xtw.WriteAttributeString("crc", rom.CRC.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
xtw.WriteAttributeString("md5", rom.MD5.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RIPEMD160, ExcludeFields)))
xtw.WriteAttributeString("ripemd160", rom.RIPEMD160.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
xtw.WriteAttributeString("sha1", rom.SHA1.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA256, ExcludeFields)))
xtw.WriteAttributeString("sha256", rom.SHA256.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA384, ExcludeFields)))
xtw.WriteAttributeString("sha384", rom.SHA384.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA512, ExcludeFields)))
xtw.WriteAttributeString("sha512", rom.SHA512.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Date, ExcludeFields)))
xtw.WriteAttributeString("date", rom.Date);
if (!ExcludeFields[(int)Field.Status] && rom.ItemStatus != ItemStatus.None)
xtw.WriteAttributeString("status", rom.ItemStatus.ToString().ToLowerInvariant());
xtw.WriteEndElement();
break;
case ItemType.Sample:
state += "\t\t<sample name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ "/>\n";
xtw.WriteStartElement("sample");
xtw.WriteAttributeString("name", datItem.GetField(Field.Name, ExcludeFields));
xtw.WriteEndElement();
break;
}
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -964,17 +1067,19 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DAT footer using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteFooter(StreamWriter sw)
private bool WriteFooter(XmlTextWriter xtw)
{
try
{
string footer = "\t</" + (_depreciated ? "game" : "machine") + ">\n</datafile>\n";
// End machine
xtw.WriteEndElement();
// Write the footer out
sw.Write(footer);
sw.Flush();
// End datafile
xtw.WriteEndElement();
xtw.Flush();
}
catch (Exception ex)
{

View File

@@ -1,18 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -65,13 +58,13 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
@@ -107,7 +100,7 @@ namespace SabreTools.Library.DatFiles
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
lastgame = rom.MachineName;
continue;
}
@@ -137,43 +130,39 @@ namespace SabreTools.Library.DatFiles
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="lastgame">The name of the last game to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, string lastgame, bool ignoreblanks = false)
private bool WriteDatItem(StreamWriter sw, DatItem datItem, string lastgame, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "";
string state = string.Empty;
// Process the item name
ProcessItemName(rom, false, forceRomName: false);
ProcessItemName(datItem, false, forceRomName: false);
// If we're in Romba mode, the state is consistent
if (Romba)
{
state += (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
state += $"{datItem.GetField(Field.SHA1, ExcludeFields)}\n";
}
// Otherwise, use any flags
else
{
if (!UseRomName && rom.MachineName != lastgame)
if (!UseRomName && datItem.MachineName != lastgame)
{
state += (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
lastgame = rom.MachineName;
state += $"{datItem.GetField(Field.MachineName, ExcludeFields)}\n";
lastgame = datItem.MachineName;
}
else if (UseRomName)
{
state += (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
state += $"{datItem.GetField(Field.Name, ExcludeFields)}\n";
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,12 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Text;
using System.Xml;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -62,9 +54,7 @@ namespace SabreTools.Library.DatFiles
// If we got a null reader, just return
if (xtr == null)
{
return;
}
// Otherwise, read the file to the end
try
@@ -82,11 +72,12 @@ namespace SabreTools.Library.DatFiles
switch (xtr.Name)
{
case "softwaredb":
Name = (String.IsNullOrWhiteSpace(Name) ? "openMSX Software List" : Name);
Description = (String.IsNullOrWhiteSpace(Description) ? Name : Name);
Name = (string.IsNullOrWhiteSpace(Name) ? "openMSX Software List" : Name);
Description = (string.IsNullOrWhiteSpace(Description) ? Name : Name);
// string timestamp = xtr.GetAttribute("timestamp"); // CDATA
xtr.Read();
break;
// We want to process the entire subtree of the software
case "software":
ReadSoftware(xtr.ReadSubtree(), filename, sysid, srcid, keep, clean, remUnicode);
@@ -94,6 +85,7 @@ namespace SabreTools.Library.DatFiles
// Skip the software now that we've processed it
xtr.Skip();
break;
default:
xtr.Read();
break;
@@ -102,7 +94,7 @@ namespace SabreTools.Library.DatFiles
}
catch (Exception ex)
{
Globals.Logger.Warning("Exception found while parsing '{0}': {1}", filename, ex);
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
// For XML errors, just skip the affected node
xtr?.Read();
@@ -136,9 +128,7 @@ namespace SabreTools.Library.DatFiles
{
// If we have an empty machine, skip it
if (reader == null)
{
return;
}
// Otherwise, add what is possible
reader.MoveToContent();
@@ -164,24 +154,30 @@ namespace SabreTools.Library.DatFiles
case "title":
machine.Name = reader.ReadElementContentAsString();
break;
case "genmsxid":
// string id = reader.ReadElementContentAsString();
reader.Read();
break;
case "system":
// string system = reader.ReadElementContentAsString();
reader.Read();
break;
case "company":
machine.Manufacturer = reader.ReadElementContentAsString();
break;
case "year":
machine.Year = reader.ReadElementContentAsString();
break;
case "country":
// string country = reader.ReadElementContentAsString();
reader.Read();
break;
case "dump":
containsItems = ReadDump(reader.ReadSubtree(), machine, diskno, filename, sysid, srcid, keep, clean, remUnicode);
diskno++;
@@ -189,6 +185,7 @@ namespace SabreTools.Library.DatFiles
// Skip the dump now that we've processed it
reader.Skip();
break;
default:
reader.Read();
break;
@@ -258,23 +255,27 @@ namespace SabreTools.Library.DatFiles
// Skip the rom now that we've processed it
reader.Skip();
break;
case "megarom":
containsItems = ReadMegaRom(reader.ReadSubtree(), machine, diskno, filename, sysid, srcid, keep, clean, remUnicode);
// Skip the megarom now that we've processed it
reader.Skip();
break;
case "sccpluscart":
containsItems = ReadSccPlusCart(reader.ReadSubtree(), machine, diskno, filename, sysid, srcid, keep, clean, remUnicode);
// Skip the sccpluscart now that we've processed it
reader.Skip();
break;
case "original":
// bool value = Utilities.GetYesNo(reader.GetAttribute("value");
// string original = reader.ReadElementContentAsString();
reader.Read();
break;
default:
reader.Read();
break;
@@ -311,7 +312,7 @@ namespace SabreTools.Library.DatFiles
bool clean,
bool remUnicode)
{
string hash = "", offset = "", type = "", remark = "";
string hash = string.Empty, offset = string.Empty, type = string.Empty, remark = string.Empty;
bool containsItems = false;
while (!reader.EOF)
@@ -330,15 +331,19 @@ namespace SabreTools.Library.DatFiles
containsItems = true;
hash = reader.ReadElementContentAsString();
break;
case "start":
offset = reader.ReadElementContentAsString();
break;
case "type":
type = reader.ReadElementContentAsString();
break;
case "remark":
remark = reader.ReadElementContentAsString();
break;
default:
reader.Read();
break;
@@ -348,7 +353,7 @@ namespace SabreTools.Library.DatFiles
// Create and add the new rom
Rom rom = new Rom
{
Name = machine.Name + "_" + diskno + (!String.IsNullOrWhiteSpace(remark) ? " " + remark : ""),
Name = machine.Name + "_" + diskno + (!string.IsNullOrWhiteSpace(remark) ? " " + remark : string.Empty),
Offset = offset,
Size = -1,
SHA1 = Utilities.CleanHashData(hash, Constants.SHA1Length),
@@ -387,7 +392,7 @@ namespace SabreTools.Library.DatFiles
bool clean,
bool remUnicode)
{
string hash = "", offset = "", type = "", remark = "";
string hash = string.Empty, offset = string.Empty, type = string.Empty, remark = string.Empty;
bool containsItems = false;
while (!reader.EOF)
@@ -406,15 +411,19 @@ namespace SabreTools.Library.DatFiles
containsItems = true;
hash = reader.ReadElementContentAsString();
break;
case "start":
offset = reader.ReadElementContentAsString();
break;
case "type":
type = reader.ReadElementContentAsString();
break;
case "remark":
remark = reader.ReadElementContentAsString();
break;
default:
reader.Read();
break;
@@ -424,7 +433,7 @@ namespace SabreTools.Library.DatFiles
// Create and add the new rom
Rom rom = new Rom
{
Name = machine.Name + "_" + diskno + (!String.IsNullOrWhiteSpace(remark) ? " " + remark : ""),
Name = machine.Name + "_" + diskno + (!string.IsNullOrWhiteSpace(remark) ? " " + remark : string.Empty),
Offset = offset,
Size = -1,
SHA1 = Utilities.CleanHashData(hash, Constants.SHA1Length),
@@ -463,7 +472,7 @@ namespace SabreTools.Library.DatFiles
bool clean,
bool remUnicode)
{
string hash = "", boot = "", remark = "";
string hash = string.Empty, boot = string.Empty, remark = string.Empty;
bool containsItems = false;
while (!reader.EOF)
@@ -481,13 +490,16 @@ namespace SabreTools.Library.DatFiles
case "boot":
boot = reader.ReadElementContentAsString();
break;
case "hash":
containsItems = true;
hash = reader.ReadElementContentAsString();
break;
case "remark":
remark = reader.ReadElementContentAsString();
break;
default:
reader.Read();
break;
@@ -497,7 +509,7 @@ namespace SabreTools.Library.DatFiles
// Create and add the new rom
Rom rom = new Rom
{
Name = machine.Name + "_" + diskno + (!String.IsNullOrWhiteSpace(remark) ? " " + remark : ""),
Name = machine.Name + "_" + diskno + (!string.IsNullOrWhiteSpace(remark) ? " " + remark : string.Empty),
Size = -1,
SHA1 = Utilities.CleanHashData(hash, Constants.SHA1Length),
};
@@ -518,20 +530,21 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
XmlTextWriter xtw = new XmlTextWriter(fs, new UTF8Encoding(false));
xtw.Formatting = Formatting.Indented;
// Write out the header
WriteHeader(sw);
WriteHeader(xtw);
// Write out each of the machines and roms
string lastgame = null;
@@ -560,29 +573,25 @@ namespace SabreTools.Library.DatFiles
// 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.MachineName.ToLowerInvariant())
{
WriteEndGame(sw);
}
WriteEndGame(xtw);
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{
WriteStartGame(sw, rom);
}
WriteStartGame(xtw, rom);
// If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
lastgame = rom.MachineName;
continue;
}
// Now, output the rom data
WriteDatItem(sw, rom, ignoreblanks);
WriteDatItem(xtw, rom, ignoreblanks);
// Set the new data to compare against
lastgame = rom.MachineName;
@@ -590,10 +599,10 @@ namespace SabreTools.Library.DatFiles
}
// Write the file footer out
WriteFooter(sw);
WriteFooter(xtw);
Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose();
xtw.Dispose();
fs.Dispose();
}
catch (Exception ex)
@@ -608,32 +617,28 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DAT header using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteHeader(StreamWriter sw)
private bool WriteHeader(XmlTextWriter xtw)
{
try
{
string header = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE softwaredb SYSTEM \"softwaredb1.dtd\">\n" +
"<softwaredb" +
// " timestamp=\"" + timestamp + "\"" +
">\n" +
@"<!-- Credits -->
<![CDATA[
The softwaredb.xml file contains information about rom mapper types
xtw.WriteStartDocument();
xtw.WriteDocType("softwaredb", null, "softwaredb1.dtd", null);
Copyright 2003 Nicolas Beyaert (Initial Database)
Copyright 2004-2013 BlueMSX Team
Copyright 2005-2018 openMSX Team
Generation MSXIDs by www.generation-msx.nl
xtw.WriteStartElement("softwaredb");
//xtw.WriteAttributeString("timestamp", timestamp);
]]>
";
// TODO: Figure out how to fix the issue with removed formatting after this point
//xtw.WriteComment("Credits");
//xtw.WriteCData(@"The softwaredb.xml file contains information about rom mapper types
// Write the header out
sw.Write(header);
sw.Flush();
//Copyright 2003 Nicolas Beyaert (Initial Database)
//Copyright 2004-2013 BlueMSX Team
//Copyright 2005-2018 openMSX Team
//Generation MSXIDs by www.generation-msx.nl");
xtw.Flush();
}
catch (Exception ex)
{
@@ -647,29 +652,26 @@ Generation MSXIDs by www.generation-msx.nl
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteStartGame(StreamWriter sw, DatItem rom)
private bool WriteStartGame(XmlTextWriter xtw, DatItem datItem)
{
try
{
// No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{
rom.MachineName = rom.MachineName.Substring(1);
}
datItem.MachineName = datItem.MachineName.TrimStart(Path.DirectorySeparatorChar);
string state = "<software>\n"
+ "\t<title>" + (!ExcludeFields[(int)Field.MachineName] ? WebUtility.HtmlEncode(rom.MachineName) : "") + "</title>\n"
// + "\t<genmsxid>" + msxid + "</genmsxid>\n"
// + "\t<system>" + system + "</system>\n"
+ "\t<company>" + (!ExcludeFields[(int)Field.Manufacturer] ? rom.Manufacturer : "") + "</company>\n"
+ "\t<year>" + (!ExcludeFields[(int)Field.Year] ? rom.Year : "") + "</year>\n";
// + "\t<country>" + country + "</country>\n";
// Build the state based on excluded fields
xtw.WriteStartElement("software");
xtw.WriteElementString("title", datItem.GetField(Field.MachineName, ExcludeFields));
//xtw.WriteElementString("genmsxid", msxid);
//xtw.WriteElementString("system", system));
xtw.WriteElementString("company", datItem.GetField(Field.Manufacturer, ExcludeFields));
xtw.WriteElementString("year", datItem.GetField(Field.Year, ExcludeFields));
//xtw.WriteElementString("country", country);
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -683,16 +685,16 @@ Generation MSXIDs by www.generation-msx.nl
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteEndGame(StreamWriter sw)
private bool WriteEndGame(XmlTextWriter xtw)
{
try
{
string state = "</software>\n";
// End software
xtw.WriteEndElement();
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -706,53 +708,49 @@ Generation MSXIDs by www.generation-msx.nl
/// <summary>
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(XmlTextWriter xtw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "";
// Pre-process the item name
ProcessItemName(rom, true);
ProcessItemName(datItem, true);
switch (rom.ItemType)
// Build the state based on excluded fields
switch (datItem.ItemType)
{
case ItemType.Archive:
break;
case ItemType.BiosSet:
break;
case ItemType.Disk:
break;
case ItemType.Release:
break;
case ItemType.Rom: // Currently this encapsulates rom, megarom, and sccpluscart
state += "\t\t<dump>"
// + "<original value=\"true\">GoodMSX</original>"
+ "<rom>"
+ (!ExcludeFields[(int)Field.Offset] && !String.IsNullOrWhiteSpace(((Rom)rom).Offset) ? "<start>" + ((Rom)rom).Offset + "</start>" : "")
// + "<type>Normal</type>"
+ "<hash>" + (!ExcludeFields[(int)Field.SHA1] ? ((Rom)rom).SHA1 : "") + "</hash>"
// + "<remark></remark>"
+ "</rom></dump>\n";
break;
case ItemType.Sample:
var rom = datItem as Rom;
xtw.WriteStartElement("dump");
//xtw.WriteStartElement("original");
//xtw.WriteAttributeString("value", "true");
//xtw.WriteString("GoodMSX");
//xtw.WriteEndElement();
xtw.WriteStartElement("rom");
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Offset, ExcludeFields)))
xtw.WriteElementString("start", rom.Offset);
//xtw.WriteElementString("type", "Normal");
xtw.WriteElementString("hash", rom.GetField(Field.SHA1, ExcludeFields).ToLowerInvariant());
//xtw.WriteElementString("remark", "");
// End rom
xtw.WriteEndElement();
// End dump
xtw.WriteEndElement();
break;
}
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -766,17 +764,19 @@ Generation MSXIDs by www.generation-msx.nl
/// <summary>
/// Write out DAT footer using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteFooter(StreamWriter sw)
private bool WriteFooter(XmlTextWriter xtw)
{
try
{
string footer = "</software>\n</softwaredb>\n";
// End software
xtw.WriteEndElement();
// Write the footer out
sw.Write(footer);
sw.Flush();
// End softwaredb
xtw.WriteEndElement();
xtw.Flush();
}
catch (Exception ex)
{

View File

@@ -1,20 +1,11 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Text;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamReader = System.IO.StreamReader;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -22,6 +13,7 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Represents parsing and writing of a RomCenter DAT
/// </summary>
/// TODO: Port over the INI parser from DICUI to make this flow a little better
internal class RomCenter : DatFile
{
/// <summary>
@@ -57,7 +49,7 @@ namespace SabreTools.Library.DatFiles
Encoding enc = Utilities.GetEncoding(filename);
StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc);
string blocktype = "";
string blocktype = string.Empty;
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
@@ -67,87 +59,93 @@ namespace SabreTools.Library.DatFiles
{
blocktype = "credits";
}
// If the line is the start of the dat section
else if (line.ToLowerInvariant().StartsWith("[dat]"))
{
blocktype = "dat";
}
// If the line is the start of the emulator section
else if (line.ToLowerInvariant().StartsWith("[emulator]"))
{
blocktype = "emulator";
}
// If the line is the start of the game section
else if (line.ToLowerInvariant().StartsWith("[games]"))
{
blocktype = "games";
}
// Otherwise, it's not a section and it's data, so get out all data
else
{
// If we have an author
if (line.ToLowerInvariant().StartsWith("author="))
{
Author = (String.IsNullOrWhiteSpace(Author) ? line.Split('=')[1] : Author);
Author = (string.IsNullOrWhiteSpace(Author) ? line.Split('=')[1] : Author);
}
// If we have one of the three version tags
else if (line.ToLowerInvariant().StartsWith("version="))
{
switch (blocktype)
{
case "credits":
Version = (String.IsNullOrWhiteSpace(Version) ? line.Split('=')[1] : Version);
Version = (string.IsNullOrWhiteSpace(Version) ? line.Split('=')[1] : Version);
break;
case "emulator":
Description = (String.IsNullOrWhiteSpace(Description) ? line.Split('=')[1] : Description);
Description = (string.IsNullOrWhiteSpace(Description) ? line.Split('=')[1] : Description);
break;
}
}
// If we have a URL
else if (line.ToLowerInvariant().StartsWith("url="))
{
Url = (String.IsNullOrWhiteSpace(Url) ? line.Split('=')[1] : Url);
Url = (string.IsNullOrWhiteSpace(Url) ? line.Split('=')[1] : Url);
}
// If we have a comment
else if (line.ToLowerInvariant().StartsWith("comment="))
{
Comment = (String.IsNullOrWhiteSpace(Comment) ? line.Split('=')[1] : Comment);
Comment = (string.IsNullOrWhiteSpace(Comment) ? line.Split('=')[1] : Comment);
}
// If we have the split flag
else if (line.ToLowerInvariant().StartsWith("split="))
{
if (Int32.TryParse(line.Split('=')[1], out int split))
{
if (split == 1 && ForceMerging == ForceMerging.None)
{
ForceMerging = ForceMerging.Split;
}
}
}
// If we have the merge tag
else if (line.ToLowerInvariant().StartsWith("merge="))
{
if (Int32.TryParse(line.Split('=')[1], out int merge))
{
if (merge == 1 && ForceMerging == ForceMerging.None)
{
ForceMerging = ForceMerging.Full;
}
}
}
// If we have the refname tag
else if (line.ToLowerInvariant().StartsWith("refname="))
{
Name = (String.IsNullOrWhiteSpace(Name) ? line.Split('=')[1] : Name);
Name = (string.IsNullOrWhiteSpace(Name) ? line.Split('=')[1] : Name);
}
// If we have a rom
else if (line.StartsWith("¬"))
{
// Some old RC DATs have this behavior
if (line.Contains("¬N¬O"))
{
line = line.Replace("¬N¬O", "") + "¬¬";
}
line = line.Replace("¬N¬O", string.Empty) + "¬¬";
/*
The rominfo order is as follows:
@@ -165,9 +163,7 @@ namespace SabreTools.Library.DatFiles
// Try getting the size separately
if (!Int64.TryParse(rominfo[7], out long size))
{
size = 0;
}
Rom rom = new Rom
{
@@ -204,13 +200,13 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
@@ -250,7 +246,7 @@ namespace SabreTools.Library.DatFiles
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
rom.Name = (rom.Name == "null" ? "-" : rom.Name);
((Rom)rom).Size = Constants.SizeZero;
@@ -293,18 +289,18 @@ namespace SabreTools.Library.DatFiles
{
try
{
string header = header = "[CREDITS]\n" +
"author=" + Author + "\n" +
"version=" + Version + "\n" +
"comment=" + Comment + "\n" +
"[DAT]\n" +
"version=2.50\n" +
"split=" + (ForceMerging == ForceMerging.Split ? "1" : "0") + "\n" +
"merge=" + (ForceMerging == ForceMerging.Full || ForceMerging == ForceMerging.Merged ? "1" : "0") + "\n" +
"[EMULATOR]\n" +
"refname=" + Name + "\n" +
"version=" + Description + "\n" +
"[GAMES]\n";
string header = "[CREDITS]\n";
header += $"author={Author}\n";
header += $"version={Version}\n";
header += $"comment={Comment}\n";
header += "[DAT]\n";
header += "version=2.50\n";
header += $"split={(ForceMerging == ForceMerging.Split ? "1" : "0")}\n";
header += $"merge={(ForceMerging == ForceMerging.Full || ForceMerging == ForceMerging.Merged ? "1" : "0")}\n";
header += "[EMULATOR]\n";
header += $"refname={Name}\n";
header += $"version={Description}\n";
header += "[GAMES]\n";
// Write the header out
sw.Write(header);
@@ -323,44 +319,59 @@ namespace SabreTools.Library.DatFiles
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(StreamWriter sw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "";
string state = string.Empty;
// Pre-process the item name
ProcessItemName(rom, true);
ProcessItemName(datItem, true);
if (rom.ItemType == ItemType.Rom)
// Build the state based on excluded fields
switch (datItem.ItemType)
{
state += "¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? WebUtility.HtmlEncode(rom.CloneOf) : "") +
"¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? WebUtility.HtmlEncode(rom.CloneOf) : "") +
"¬" + (!ExcludeFields[(int)Field.MachineName] ? WebUtility.HtmlEncode(rom.MachineName) : "") +
"¬" + (!ExcludeFields[(int)Field.Description] ? WebUtility.HtmlEncode((String.IsNullOrWhiteSpace(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription)) : "") +
"¬" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") +
"¬" + (!ExcludeFields[(int)Field.CRC] ? ((Rom)rom).CRC.ToLowerInvariant() : "") +
"¬" + (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? ((Rom)rom).Size.ToString() : "") + "¬¬¬\n";
}
else if (rom.ItemType == ItemType.Disk)
{
state += "¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? WebUtility.HtmlEncode(rom.CloneOf) : "") +
"¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? WebUtility.HtmlEncode(rom.CloneOf) : "") +
"¬" + (!ExcludeFields[(int)Field.MachineName] ? WebUtility.HtmlEncode(rom.MachineName) : "") +
"¬" + (!ExcludeFields[(int)Field.Description] ? WebUtility.HtmlEncode((String.IsNullOrWhiteSpace(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription)) : "") +
"¬" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") +
"¬¬¬¬¬\n";
case ItemType.Disk:
state += "¬";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CloneOf, ExcludeFields)))
state += datItem.CloneOf;
state += "¬";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CloneOf, ExcludeFields)))
state += datItem.CloneOf;
state += $"¬{datItem.GetField(Field.MachineName, ExcludeFields)}";
if (string.IsNullOrWhiteSpace(datItem.MachineDescription))
state += $"¬{datItem.GetField(Field.MachineName, ExcludeFields)}";
else
state += $"¬{datItem.GetField(Field.Description, ExcludeFields)}";
state += $"¬{datItem.GetField(Field.Name, ExcludeFields)}";
state += "¬¬¬¬¬\n";
break;
case ItemType.Rom:
var rom = datItem as Rom;
state += "¬";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CloneOf, ExcludeFields)))
state += datItem.CloneOf;
state += "¬";
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CloneOf, ExcludeFields)))
state += datItem.CloneOf;
state += $"¬{datItem.GetField(Field.MachineName, ExcludeFields)}";
if (string.IsNullOrWhiteSpace(datItem.MachineDescription))
state += $"¬{datItem.GetField(Field.MachineName, ExcludeFields)}";
else
state += $"¬{datItem.GetField(Field.Description, ExcludeFields)}";
state += $"¬{datItem.GetField(Field.Name, ExcludeFields)}";
state += $"¬{datItem.GetField(Field.CRC, ExcludeFields)}";
state += $"¬{datItem.GetField(Field.Size, ExcludeFields)}";
state += "¬¬¬\n";
break;
}
sw.Write(state);

View File

@@ -1,21 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Xml;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -57,7 +49,7 @@ namespace SabreTools.Library.DatFiles
{
// Prepare all internal variables
bool empty = true;
string key = "";
string key = string.Empty;
List<string> parent = new List<string>();
Encoding enc = Utilities.GetEncoding(filename);
@@ -65,9 +57,7 @@ namespace SabreTools.Library.DatFiles
// If we got a null reader, just return
if (xtr == null)
{
return;
}
// Otherwise, read the file to the end
try
@@ -81,7 +71,7 @@ namespace SabreTools.Library.DatFiles
// If we didn't find any items in the folder, make sure to add the blank rom
if (empty)
{
string tempgame = String.Join("\\", parent);
string tempgame = string.Join("\\", parent);
Rom rom = new Rom("null", tempgame, omitFromScan: Hash.DeepHashes); // TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually
// Now process and add the rom
@@ -92,7 +82,7 @@ namespace SabreTools.Library.DatFiles
int parentcount = parent.Count;
if (parentcount == 0)
{
Globals.Logger.Verbose("Empty parent '{0}' found in '{1}'", String.Join("\\", parent), filename);
Globals.Logger.Verbose($"Empty parent '{string.Join("\\", parent)}' found in '{filename}'");
empty = true;
}
@@ -101,9 +91,7 @@ namespace SabreTools.Library.DatFiles
{
parent.RemoveAt(parent.Count - 1);
if (keep && parentcount > 1)
{
Type = (String.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
}
Type = (string.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
}
}
@@ -123,6 +111,7 @@ namespace SabreTools.Library.DatFiles
// Skip the header node now that we've processed it
xtr.Skip();
break;
case "dir":
case "directory":
empty = ReadDirectory(xtr.ReadSubtree(), parent, filename, sysid, srcid, keep, clean, remUnicode);
@@ -138,7 +127,7 @@ namespace SabreTools.Library.DatFiles
}
catch (Exception ex)
{
Globals.Logger.Warning("Exception found while parsing '{0}': {1}", filename, ex);
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
// For XML errors, just skip the affected node
xtr?.Read();
@@ -158,9 +147,7 @@ namespace SabreTools.Library.DatFiles
// If there's no subtree to the header, skip it
if (reader == null)
{
return;
}
// Otherwise, read what we can from the header
while (!reader.EOF)
@@ -173,55 +160,64 @@ namespace SabreTools.Library.DatFiles
}
// Get all header items (ONLY OVERWRITE IF THERE'S NO DATA)
string content = "";
string content = string.Empty;
switch (reader.Name)
{
case "name":
content = reader.ReadElementContentAsString(); ;
Name = (String.IsNullOrWhiteSpace(Name) ? content : Name);
Name = (string.IsNullOrWhiteSpace(Name) ? content : Name);
superdat = superdat || content.Contains(" - SuperDAT");
if (keep && superdat)
{
Type = (String.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
Type = (string.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
}
break;
case "description":
content = reader.ReadElementContentAsString();
Description = (String.IsNullOrWhiteSpace(Description) ? content : Description);
Description = (string.IsNullOrWhiteSpace(Description) ? content : Description);
break;
case "rootdir":
content = reader.ReadElementContentAsString();
RootDir = (String.IsNullOrWhiteSpace(RootDir) ? content : RootDir);
RootDir = (string.IsNullOrWhiteSpace(RootDir) ? content : RootDir);
break;
case "category":
content = reader.ReadElementContentAsString();
Category = (String.IsNullOrWhiteSpace(Category) ? content : Category);
Category = (string.IsNullOrWhiteSpace(Category) ? content : Category);
break;
case "version":
content = reader.ReadElementContentAsString();
Version = (String.IsNullOrWhiteSpace(Version) ? content : Version);
Version = (string.IsNullOrWhiteSpace(Version) ? content : Version);
break;
case "date":
content = reader.ReadElementContentAsString();
Date = (String.IsNullOrWhiteSpace(Date) ? content.Replace(".", "/") : Date);
Date = (string.IsNullOrWhiteSpace(Date) ? content.Replace(".", "/") : Date);
break;
case "author":
content = reader.ReadElementContentAsString();
Author = (String.IsNullOrWhiteSpace(Author) ? content : Author);
Email = (String.IsNullOrWhiteSpace(Email) ? reader.GetAttribute("email") : Email);
Homepage = (String.IsNullOrWhiteSpace(Homepage) ? reader.GetAttribute("homepage") : Homepage);
Url = (String.IsNullOrWhiteSpace(Url) ? reader.GetAttribute("url") : Url);
Author = (string.IsNullOrWhiteSpace(Author) ? content : Author);
Email = (string.IsNullOrWhiteSpace(Email) ? reader.GetAttribute("email") : Email);
Homepage = (string.IsNullOrWhiteSpace(Homepage) ? reader.GetAttribute("homepage") : Homepage);
Url = (string.IsNullOrWhiteSpace(Url) ? reader.GetAttribute("url") : Url);
break;
case "comment":
content = reader.ReadElementContentAsString();
Comment = (String.IsNullOrWhiteSpace(Comment) ? content : Comment);
Comment = (string.IsNullOrWhiteSpace(Comment) ? content : Comment);
break;
case "flags":
ReadFlags(reader.ReadSubtree(), superdat);
// Skip the flags node now that we've processed it
reader.Skip();
break;
default:
reader.Read();
break;
@@ -255,21 +251,17 @@ namespace SabreTools.Library.DatFiles
// Prepare all internal variables
XmlReader flagreader;
bool empty = true;
string key = "", date = "";
string key = string.Empty, date = string.Empty;
long size = -1;
ItemStatus its = ItemStatus.None;
// If there's no subtree to the header, skip it
if (reader == null)
{
return empty;
}
string foldername = (reader.GetAttribute("name") ?? "");
if (!String.IsNullOrWhiteSpace(foldername))
{
string foldername = (reader.GetAttribute("name") ?? string.Empty);
if (!string.IsNullOrWhiteSpace(foldername))
parent.Add(foldername);
}
// Otherwise, read what we can from the directory
while (!reader.EOF)
@@ -280,7 +272,7 @@ namespace SabreTools.Library.DatFiles
// If we didn't find any items in the folder, make sure to add the blank rom
if (empty)
{
string tempgame = String.Join("\\", parent);
string tempgame = string.Join("\\", parent);
Rom rom = new Rom("null", tempgame, omitFromScan: Hash.DeepHashes); // TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually
// Now process and add the rom
@@ -291,7 +283,7 @@ namespace SabreTools.Library.DatFiles
int parentcount = parent.Count;
if (parentcount == 0)
{
Globals.Logger.Verbose("Empty parent '{0}' found in '{1}'", String.Join("\\", parent), filename);
Globals.Logger.Verbose($"Empty parent '{string.Join("\\", parent)}' found in '{filename}'");
empty = true;
}
@@ -300,9 +292,7 @@ namespace SabreTools.Library.DatFiles
{
parent.RemoveAt(parent.Count - 1);
if (keep && parentcount > 1)
{
Type = (String.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
}
Type = (string.IsNullOrWhiteSpace(Type) ? "SuperDAT" : Type);
}
}
@@ -314,7 +304,7 @@ namespace SabreTools.Library.DatFiles
}
// Get all directory items
string content = "";
string content = string.Empty;
switch (reader.Name)
{
// Directories can contain directories
@@ -325,6 +315,7 @@ namespace SabreTools.Library.DatFiles
// Skip the directory node now that we've processed it
reader.Read();
break;
case "file":
empty = false;
@@ -371,7 +362,7 @@ namespace SabreTools.Library.DatFiles
Machine dir = new Machine();
// Get the name of the game from the parent
dir.Name = String.Join("\\", parent);
dir.Name = string.Join("\\", parent);
dir.Description = dir.Name;
DatItem datItem;
@@ -387,6 +378,7 @@ namespace SabreTools.Library.DatFiles
SourceID = srcid,
};
break;
case "biosset":
datItem = new BiosSet
{
@@ -399,6 +391,7 @@ namespace SabreTools.Library.DatFiles
SourceID = srcid,
};
break;
case "disk":
datItem = new Disk
{
@@ -416,6 +409,7 @@ namespace SabreTools.Library.DatFiles
SourceID = srcid,
};
break;
case "release":
datItem = new Release
{
@@ -430,6 +424,7 @@ namespace SabreTools.Library.DatFiles
SourceID = srcid,
};
break;
case "rom":
datItem = new Rom
{
@@ -450,6 +445,7 @@ namespace SabreTools.Library.DatFiles
SourceID = srcid,
};
break;
case "sample":
datItem = new Sample
{
@@ -460,6 +456,7 @@ namespace SabreTools.Library.DatFiles
SourceID = srcid,
};
break;
default:
// By default, create a new Blank, just in case
datItem = new Blank();
@@ -487,13 +484,11 @@ namespace SabreTools.Library.DatFiles
private void ReadFlags(XmlReader reader, bool superdat)
{
// Prepare all internal variables
string content = "";
string content = string.Empty;
// If we somehow have a null flag section, skip it
if (reader == null)
{
return;
}
while (!reader.EOF)
{
@@ -513,21 +508,24 @@ namespace SabreTools.Library.DatFiles
switch (reader.GetAttribute("name").ToLowerInvariant())
{
case "type":
Type = (String.IsNullOrWhiteSpace(Type) ? content : Type);
Type = (string.IsNullOrWhiteSpace(Type) ? content : Type);
superdat = superdat || content.Contains("SuperDAT");
break;
case "forcemerging":
if (ForceMerging == ForceMerging.None)
{
ForceMerging = Utilities.GetForceMerging(content);
}
break;
case "forcenodump":
if (ForceNodump == ForceNodump.None)
{
ForceNodump = Utilities.GetForceNodump(content);
}
break;
case "forcepacking":
if (ForcePacking == ForcePacking.None)
{
@@ -536,8 +534,10 @@ namespace SabreTools.Library.DatFiles
break;
}
}
reader.Read();
break;
default:
reader.Read();
break;
@@ -556,20 +556,21 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
XmlTextWriter xtw = new XmlTextWriter(fs, new UTF8Encoding(false));
xtw.Formatting = Formatting.Indented;
// Write out the header
WriteHeader(sw);
WriteHeader(xtw);
// Write out each of the machines and roms
int depth = 2, last = -1;
@@ -602,22 +603,18 @@ namespace SabreTools.Library.DatFiles
// 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.MachineName.ToLowerInvariant())
{
depth = WriteEndGame(sw, splitpath, newsplit, depth, out last);
}
depth = WriteEndGame(xtw, splitpath, newsplit, depth, out last);
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{
depth = WriteStartGame(sw, rom, newsplit, lastgame, depth, last);
}
depth = WriteStartGame(xtw, rom, newsplit, lastgame, depth, last);
// If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
splitpath = newsplit;
lastgame = rom.MachineName;
@@ -625,7 +622,7 @@ namespace SabreTools.Library.DatFiles
}
// Now, output the rom data
WriteDatItem(sw, rom, depth, ignoreblanks);
WriteDatItem(xtw, rom, depth, ignoreblanks);
// Set the new data to compare against
splitpath = newsplit;
@@ -634,10 +631,10 @@ namespace SabreTools.Library.DatFiles
}
// Write the file footer out
WriteFooter(sw, depth);
WriteFooter(xtw, depth);
Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose();
xtw.Dispose();
fs.Dispose();
}
catch (Exception ex)
@@ -652,44 +649,119 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DAT header using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteHeader(StreamWriter sw)
private bool WriteHeader(XmlTextWriter xtw)
{
try
{
string header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!DOCTYPE sabredat SYSTEM \"newdat.xsd\">\n\n" +
"<datafile>\n" +
"\t<header>\n" +
"\t\t<name>" + WebUtility.HtmlEncode(Name) + "</name>\n" +
"\t\t<description>" + WebUtility.HtmlEncode(Description) + "</description>\n" +
(!String.IsNullOrWhiteSpace(RootDir) ? "\t\t<rootdir>" + WebUtility.HtmlEncode(RootDir) + "</rootdir>\n" : "") +
(!String.IsNullOrWhiteSpace(Category) ? "\t\t<category>" + WebUtility.HtmlEncode(Category) + "</category>\n" : "") +
"\t\t<version>" + WebUtility.HtmlEncode(Version) + "</version>\n" +
(!String.IsNullOrWhiteSpace(Date) ? "\t\t<date>" + WebUtility.HtmlEncode(Date) + "</date>\n" : "") +
"\t\t<author>" + WebUtility.HtmlEncode(Author) + "</author>\n" +
(!String.IsNullOrWhiteSpace(Comment) ? "\t\t<comment>" + WebUtility.HtmlEncode(Comment) + "</comment>\n" : "") +
(!String.IsNullOrWhiteSpace(Type) || ForcePacking != ForcePacking.None || ForceMerging != ForceMerging.None || ForceNodump != ForceNodump.None ?
"\t\t<flags>\n" +
(!String.IsNullOrWhiteSpace(Type) ? "\t\t\t<flag name=\"type\" value=\"" + WebUtility.HtmlEncode(Type) + "\"/>\n" : "") +
(ForcePacking == ForcePacking.Unzip ? "\t\t\t<flag name=\"forcepacking\" value=\"unzip\"/>\n" : "") +
(ForcePacking == ForcePacking.Zip ? "\t\t\t<flag name=\"forcepacking\" value=\"zip\"/>\n" : "") +
(ForceMerging == ForceMerging.Full ? "\t\t\t<flag name=\"forcemerging\" value=\"full\"/>\n" : "") +
(ForceMerging == ForceMerging.Split ? "\t\t\t<flag name=\"forcemerging\" value=\"split\"/>\n" : "") +
(ForceMerging == ForceMerging.Merged ? "\t\t\t<flag name=\"forcemerging\" value=\"merged\"/>\n" : "") +
(ForceMerging == ForceMerging.NonMerged ? "\t\t\t<flag name=\"forcemerging\" value=\"nonmerged\"/>\n" : "") +
(ForceNodump == ForceNodump.Ignore ? "\t\t\t<flag name=\"forcenodump\" value=\"ignore\"/>\n" : "") +
(ForceNodump == ForceNodump.Obsolete ? "\t\t\t<flag name=\"forcenodump\" value=\"obsolete\"/>\n" : "") +
(ForceNodump == ForceNodump.Required ? "\t\t\t<flag name=\"forcenodump\" value=\"required\"/>\n" : "") +
"\t\t</flags>\n"
: "") +
"\t</header>\n" +
"\t<data>\n";
xtw.WriteStartDocument();
xtw.WriteDocType("sabredat", null, "newdat.xsd", null);
// Write the header out
sw.Write(header);
sw.Flush();
xtw.WriteStartElement("datafile");
xtw.WriteStartElement("header");
xtw.WriteElementString("name", Name);
xtw.WriteElementString("description", Description);
if (!string.IsNullOrWhiteSpace(RootDir))
xtw.WriteElementString("rootdir", RootDir);
if (!string.IsNullOrWhiteSpace(Category))
xtw.WriteElementString("category", Category);
xtw.WriteElementString("version", Version);
if (!string.IsNullOrWhiteSpace(Date))
xtw.WriteElementString("date", Date);
xtw.WriteElementString("author", Author);
if (!string.IsNullOrWhiteSpace(Comment))
xtw.WriteElementString("comment", Comment);
if (!string.IsNullOrWhiteSpace(Type) || ForcePacking != ForcePacking.None || ForceMerging != ForceMerging.None || ForceNodump != ForceNodump.None)
{
xtw.WriteStartElement("flags");
if (!string.IsNullOrWhiteSpace(Type))
{
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "type");
xtw.WriteAttributeString("value", Type);
xtw.WriteEndElement();
}
switch (ForcePacking)
{
case ForcePacking.Unzip:
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "forcepacking");
xtw.WriteAttributeString("value", "unzip");
xtw.WriteEndElement();
break;
case ForcePacking.Zip:
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "forcepacking");
xtw.WriteAttributeString("value", "zip");
xtw.WriteEndElement();
break;
}
switch (ForceMerging)
{
case ForceMerging.Full:
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "forcemerging");
xtw.WriteAttributeString("value", "full");
xtw.WriteEndElement();
break;
case ForceMerging.Split:
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "forcemerging");
xtw.WriteAttributeString("value", "split");
xtw.WriteEndElement();
break;
case ForceMerging.Merged:
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "forcemerging");
xtw.WriteAttributeString("value", "merged");
xtw.WriteEndElement();
break;
case ForceMerging.NonMerged:
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "forcemerging");
xtw.WriteAttributeString("value", "nonmerged");
xtw.WriteEndElement();
break;
}
switch (ForceNodump)
{
case ForceNodump.Ignore:
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "forcenodump");
xtw.WriteAttributeString("value", "ignore");
xtw.WriteEndElement();
break;
case ForceNodump.Obsolete:
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "forcenodump");
xtw.WriteAttributeString("value", "obsolete");
xtw.WriteEndElement();
break;
case ForceNodump.Required:
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "forcenodump");
xtw.WriteAttributeString("value", "required");
xtw.WriteEndElement();
break;
}
// End flags
xtw.WriteEndElement();
}
// End header
xtw.WriteEndElement();
xtw.WriteStartElement("data");
xtw.Flush();
}
catch (Exception ex)
{
@@ -703,37 +775,31 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="newsplit">Split path representing the parent game (SabreDAT only)</param>
/// <param name="lastgame">The name of the last game to be output</param>
/// <param name="depth">Current depth to output file at (SabreDAT only)</param>
/// <param name="last">Last known depth to cycle back from (SabreDAT only)</param>
/// <returns>The new depth of the tag</returns>
private int WriteStartGame(StreamWriter sw, DatItem rom, List<string> newsplit, string lastgame, int depth, int last)
private int WriteStartGame(XmlTextWriter xtw, DatItem datItem, List<string> newsplit, string lastgame, int depth, int last)
{
try
{
// No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{
rom.MachineName = rom.MachineName.Substring(1);
}
datItem.MachineName = datItem.MachineName.TrimStart(Path.DirectorySeparatorChar);
string state = "";
// Build the state based on excluded fields
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 += "<directory name=\"" + (!ExcludeFields[(int)Field.MachineName] ? WebUtility.HtmlEncode(newsplit[i]) : "") + "\" description=\"" +
WebUtility.HtmlEncode(newsplit[i]) + "\">\n";
xtw.WriteStartElement("directory");
xtw.WriteAttributeString("name", !ExcludeFields[(int)Field.MachineName] ? newsplit[i] : string.Empty);
xtw.WriteAttributeString("description", !ExcludeFields[(int)Field.MachineName] ? newsplit[i] : string.Empty);
}
depth = depth - (last == -1 ? 0 : last) + newsplit.Count;
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -747,19 +813,18 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="splitpath">Split path representing last kwown parent game (SabreDAT only)</param>
/// <param name="newsplit">Split path representing the parent game (SabreDAT only)</param>
/// <param name="depth">Current depth to output file at (SabreDAT only)</param>
/// <param name="last">Last known depth to cycle back from (SabreDAT only)</param>
/// <returns>The new depth of the tag</returns>
private int WriteEndGame(StreamWriter sw, List<string> splitpath, List<string> newsplit, int depth, out int last)
private int WriteEndGame(XmlTextWriter xtw, List<string> splitpath, List<string> newsplit, int depth, out int last)
{
last = 0;
try
{
string state = "";
if (splitpath != null)
{
for (int i = 0; i < newsplit.Count && i < splitpath.Count; i++)
@@ -769,28 +834,21 @@ namespace SabreTools.Library.DatFiles
// 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 += "</directory>\n";
// End directory
xtw.WriteEndElement();
}
// Reset the current depth
depth = 2 + last;
}
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -804,95 +862,139 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="depth">Current depth to output file at (SabreDAT only)</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, int depth, bool ignoreblanks = false)
private bool WriteDatItem(XmlTextWriter xtw, DatItem datItem, int depth, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "", prefix = "";
// Pre-process the item name
ProcessItemName(rom, true);
ProcessItemName(datItem, true);
for (int i = 0; i < depth; i++)
{
prefix += "\t";
}
state += prefix;
switch (rom.ItemType)
// Build the state based on excluded fields
switch (datItem.ItemType)
{
case ItemType.Archive:
state += "<file type=\"archive\" name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ "/>\n";
xtw.WriteStartElement("file");
xtw.WriteAttributeString("type", "archive");
xtw.WriteAttributeString("name", datItem.GetField(Field.Name, ExcludeFields));
xtw.WriteEndElement();
break;
case ItemType.BiosSet:
state += "<file type=\"biosset\" name\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.BiosDescription] && !String.IsNullOrWhiteSpace(((BiosSet)rom).Description) ? " description=\"" + WebUtility.HtmlEncode(((BiosSet)rom).Description) + "\"" : "")
+ (!ExcludeFields[(int)Field.Default] && ((BiosSet)rom).Default != null
? ((BiosSet)rom).Default.ToString().ToLowerInvariant()
: "")
+ "/>\n";
var biosSet = datItem as BiosSet;
xtw.WriteStartElement("file");
xtw.WriteAttributeString("type", "biosset");
xtw.WriteAttributeString("name", biosSet.GetField(Field.Name, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.BiosDescription, ExcludeFields)))
xtw.WriteAttributeString("description", biosSet.Description);
if (!ExcludeFields[(int)Field.Default] && biosSet.Default != null)
xtw.WriteAttributeString("default", biosSet.Default.ToString().ToLowerInvariant());
xtw.WriteEndElement();
break;
case ItemType.Disk:
state += "<file type=\"disk\" name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.MD5] && !String.IsNullOrWhiteSpace(((Disk)rom).MD5) ? " md5=\"" + ((Disk)rom).MD5.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.RIPEMD160] && !String.IsNullOrWhiteSpace(((Disk)rom).RIPEMD160) ? " ripemd160=\"" + ((Disk)rom).RIPEMD160.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA1] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA1) ? " sha1=\"" + ((Disk)rom).SHA1.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA256] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA256) ? " sha256=\"" + ((Disk)rom).SHA256.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA384] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA384) ? " sha384=\"" + ((Disk)rom).SHA384.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA512] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA512) ? " sha512=\"" + ((Disk)rom).SHA512.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus != ItemStatus.None ? prefix + "/>\n" + prefix + "\t<flags>\n" +
prefix + "\t\t<flag name=\"status\" value=\"" + ((Disk)rom).ItemStatus.ToString().ToLowerInvariant() + "\"/>\n" +
prefix + "\t</flags>\n" +
prefix + "</file>\n" : "/>\n");
var disk = datItem as Disk;
xtw.WriteStartElement("file");
xtw.WriteAttributeString("type", "disk");
xtw.WriteAttributeString("name", disk.GetField(Field.Name, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
xtw.WriteAttributeString("md5", disk.MD5.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RIPEMD160, ExcludeFields)))
xtw.WriteAttributeString("ripemd160", disk.RIPEMD160.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
xtw.WriteAttributeString("sha1", disk.SHA1.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA256, ExcludeFields)))
xtw.WriteAttributeString("sha256", disk.SHA256.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA384, ExcludeFields)))
xtw.WriteAttributeString("sha384", disk.SHA384.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA512, ExcludeFields)))
xtw.WriteAttributeString("sha512", disk.SHA512.ToLowerInvariant());
if (!ExcludeFields[(int)Field.Status] && disk.ItemStatus != ItemStatus.None)
{
xtw.WriteStartElement("flags");
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "status");
xtw.WriteAttributeString("value", disk.ItemStatus.ToString().ToLowerInvariant());
xtw.WriteEndElement();
// End flags
xtw.WriteEndElement();
}
xtw.WriteEndElement();
break;
case ItemType.Release:
state += "<file type=\"release\" name\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.Region] && !String.IsNullOrWhiteSpace(((Release)rom).Region) ? " region=\"" + WebUtility.HtmlEncode(((Release)rom).Region) + "\"" : "")
+ (!ExcludeFields[(int)Field.Language] && !String.IsNullOrWhiteSpace(((Release)rom).Language) ? " language=\"" + WebUtility.HtmlEncode(((Release)rom).Language) + "\"" : "")
+ (!ExcludeFields[(int)Field.Date] && !String.IsNullOrWhiteSpace(((Release)rom).Date) ? " date=\"" + WebUtility.HtmlEncode(((Release)rom).Date) + "\"" : "")
+ (!ExcludeFields[(int)Field.Default] && ((Release)rom).Default != null
? ((Release)rom).Default.ToString().ToLowerInvariant()
: "")
+ "/>\n";
var release = datItem as Release;
xtw.WriteStartElement("file");
xtw.WriteAttributeString("type", "release");
xtw.WriteAttributeString("name", release.GetField(Field.Name, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Region, ExcludeFields)))
xtw.WriteAttributeString("region", release.Region);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Language, ExcludeFields)))
xtw.WriteAttributeString("language", release.Language);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Date, ExcludeFields)))
xtw.WriteAttributeString("date", release.Date);
if (!ExcludeFields[(int)Field.Default] && release.Default != null)
xtw.WriteAttributeString("default", release.Default.ToString().ToLowerInvariant());
xtw.WriteEndElement();
break;
case ItemType.Rom:
state += "<file type=\"rom\" name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? " size=\"" + ((Rom)rom).Size + "\"" : "")
+ (!ExcludeFields[(int)Field.CRC] && !String.IsNullOrWhiteSpace(((Rom)rom).CRC) ? " crc=\"" + ((Rom)rom).CRC.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.MD5] && !String.IsNullOrWhiteSpace(((Rom)rom).MD5) ? " md5=\"" + ((Rom)rom).MD5.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.RIPEMD160] && !String.IsNullOrWhiteSpace(((Rom)rom).RIPEMD160) ? " ripemd160=\"" + ((Rom)rom).RIPEMD160.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA1] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA1) ? " sha1=\"" + ((Rom)rom).SHA1.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA256] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA256) ? " sha256=\"" + ((Rom)rom).SHA256.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA384] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA384) ? " sha384=\"" + ((Rom)rom).SHA384.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA512] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA512) ? " sha512=\"" + ((Rom)rom).SHA512.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Date] && !String.IsNullOrWhiteSpace(((Rom)rom).Date) ? " date=\"" + ((Rom)rom).Date + "\"" : "")
+ (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus != ItemStatus.None ? prefix + "/>\n" + prefix + "\t<flags>\n" +
prefix + "\t\t<flag name=\"status\" value=\"" + ((Rom)rom).ItemStatus.ToString().ToLowerInvariant() + "\"/>\n" +
prefix + "\t</flags>\n" +
prefix + "</file>\n" : "/>\n");
var rom = datItem as Rom;
xtw.WriteStartElement("file");
xtw.WriteAttributeString("type", "rom");
xtw.WriteAttributeString("name", rom.GetField(Field.Name, ExcludeFields));
if (!ExcludeFields[(int)Field.Size] && rom.Size != -1)
xtw.WriteAttributeString("size", rom.Size.ToString());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CRC, ExcludeFields)))
xtw.WriteAttributeString("crc", rom.CRC.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
xtw.WriteAttributeString("md5", rom.MD5.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RIPEMD160, ExcludeFields)))
xtw.WriteAttributeString("ripemd160", rom.RIPEMD160.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
xtw.WriteAttributeString("sha1", rom.SHA1.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA256, ExcludeFields)))
xtw.WriteAttributeString("sha256", rom.SHA256.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA384, ExcludeFields)))
xtw.WriteAttributeString("sha384", rom.SHA384.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA512, ExcludeFields)))
xtw.WriteAttributeString("sha512", rom.SHA512.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Date, ExcludeFields)))
xtw.WriteAttributeString("date", rom.Date);
if (!ExcludeFields[(int)Field.Status] && rom.ItemStatus != ItemStatus.None)
{
xtw.WriteStartElement("flags");
xtw.WriteStartElement("flag");
xtw.WriteAttributeString("name", "status");
xtw.WriteAttributeString("value", rom.ItemStatus.ToString().ToLowerInvariant());
xtw.WriteEndElement();
// End flags
xtw.WriteEndElement();
}
xtw.WriteEndElement();
break;
case ItemType.Sample:
state += "<file type=\"sample\" name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ "/>\n";
xtw.WriteStartElement("file");
xtw.WriteAttributeString("type", "sample");
xtw.WriteAttributeString("name", datItem.GetField(Field.Name, ExcludeFields));
xtw.WriteEndElement();
break;
}
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -906,28 +1008,26 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DAT footer using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="depth">Current depth to output file at (SabreDAT only)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteFooter(StreamWriter sw, int depth)
private bool WriteFooter(XmlTextWriter xtw, int depth)
{
try
{
string footer = "";
for (int i = depth - 1; i >= 2; i--)
{
// Print out the number of tabs and the end folder
for (int j = 0; j < i; j++)
{
footer += "\t";
}
footer += "</directory>\n";
// End directory
xtw.WriteEndElement();
}
footer += "\t</data>\n</datafile>\n";
// Write the footer out
sw.Write(footer);
sw.Flush();
// End data
xtw.WriteEndElement();
// End datafile
xtw.WriteEndElement();
xtw.Flush();
}
catch (Exception ex)
{

View File

@@ -22,7 +22,7 @@ namespace SabreTools.Library.DatFiles
internal class SeparatedValue : DatFile
{
// Private instance variables specific to Separated Value DATs
char _delim;
private readonly char _delim;
/// <summary>
/// Constructor designed for casting a base DatFile
@@ -81,85 +81,103 @@ namespace SabreTools.Library.DatFiles
case "file name":
columns.Add("DatFile.FileName");
break;
case "internal name":
columns.Add("DatFile.Name");
break;
case "description":
case "dat description":
columns.Add("DatFile.Description");
break;
case "game name":
case "game":
case "machine":
columns.Add("Machine.Name");
break;
case "game description":
columns.Add("Description");
break;
case "type":
columns.Add("DatItem.Type");
break;
case "rom":
case "romname":
case "rom name":
case "name":
columns.Add("Rom.Name");
break;
case "disk":
case "diskname":
case "disk name":
columns.Add("Disk.Name");
break;
case "size":
columns.Add("DatItem.Size");
break;
case "crc":
case "crc hash":
columns.Add("DatItem.CRC");
break;
case "md5":
case "md5 hash":
columns.Add("DatItem.MD5");
break;
case "ripemd":
case "ripemd160":
case "ripemd hash":
case "ripemd160 hash":
columns.Add("DatItem.RIPEMD160");
break;
case "sha1":
case "sha-1":
case "sha1 hash":
case "sha-1 hash":
columns.Add("DatItem.SHA1");
break;
case "sha256":
case "sha-256":
case "sha256 hash":
case "sha-256 hash":
columns.Add("DatItem.SHA256");
break;
case "sha384":
case "sha-384":
case "sha384 hash":
case "sha-384 hash":
columns.Add("DatItem.SHA384");
break;
case "sha512":
case "sha-512":
case "sha512 hash":
case "sha-512 hash":
columns.Add("DatItem.SHA512");
break;
case "nodump":
case "no dump":
case "status":
case "item status":
columns.Add("DatItem.Nodump");
break;
case "date":
columns.Add("DatItem.Date");
break;
default:
columns.Add("INVALID");
break;
@@ -175,7 +193,7 @@ namespace SabreTools.Library.DatFiles
// If the line doesn't have the correct number of columns, we log and skip
if (parsedLine.Length != columns.Count)
{
Globals.Logger.Warning("Malformed line found in '{0}' at line {1}", filename, linenum);
Globals.Logger.Warning($"Malformed line found in '{filename}' at line {linenum}");
continue;
}
@@ -193,57 +211,72 @@ namespace SabreTools.Library.DatFiles
switch (columns[i])
{
case "DatFile.FileName":
FileName = (String.IsNullOrWhiteSpace(FileName) ? value : FileName);
FileName = (string.IsNullOrWhiteSpace(FileName) ? value : FileName);
break;
case "DatFile.Name":
Name = (String.IsNullOrWhiteSpace(Name) ? value : Name);
Name = (string.IsNullOrWhiteSpace(Name) ? value : Name);
break;
case "DatFile.Description":
Description = (String.IsNullOrWhiteSpace(Description) ? value : Description);
Description = (string.IsNullOrWhiteSpace(Description) ? value : Description);
break;
case "Machine.Name":
machineName = value;
break;
case "Description":
machineDesc = value;
break;
case "DatItem.Type":
itemType = Utilities.GetItemType(value) ?? ItemType.Rom;
break;
case "Rom.Name":
case "Disk.Name":
name = String.IsNullOrWhiteSpace(value) ? name : value;
name = string.IsNullOrWhiteSpace(value) ? name : value;
break;
case "DatItem.Size":
if (!Int64.TryParse(value, out size))
{
size = -1;
}
break;
case "DatItem.CRC":
crc = Utilities.CleanHashData(value, Constants.CRCLength);
break;
case "DatItem.MD5":
md5 = Utilities.CleanHashData(value, Constants.MD5Length);
break;
case "DatItem.RIPEMD160":
ripemd160 = Utilities.CleanHashData(value, Constants.RIPEMD160Length);
break;
case "DatItem.SHA1":
sha1 = Utilities.CleanHashData(value, Constants.SHA1Length);
break;
case "DatItem.SHA256":
sha256 = Utilities.CleanHashData(value, Constants.SHA256Length);
break;
case "DatItem.SHA384":
sha384 = Utilities.CleanHashData(value, Constants.SHA384Length);
break;
case "DatItem.SHA512":
sha512 = Utilities.CleanHashData(value, Constants.SHA512Length);
break;
case "DatItem.Nodump":
status = Utilities.GetItemStatus(value);
break;
case "DatItem.Date":
date = value;
break;
@@ -264,6 +297,7 @@ namespace SabreTools.Library.DatFiles
ParseAddHelper(archive, clean, remUnicode);
break;
case ItemType.BiosSet:
BiosSet biosset = new BiosSet()
{
@@ -275,6 +309,7 @@ namespace SabreTools.Library.DatFiles
ParseAddHelper(biosset, clean, remUnicode);
break;
case ItemType.Disk:
Disk disk = new Disk()
{
@@ -294,6 +329,7 @@ namespace SabreTools.Library.DatFiles
ParseAddHelper(disk, clean, remUnicode);
break;
case ItemType.Release:
Release release = new Release()
{
@@ -305,6 +341,7 @@ namespace SabreTools.Library.DatFiles
ParseAddHelper(release, clean, remUnicode);
break;
case ItemType.Rom:
Rom rom = new Rom()
{
@@ -327,6 +364,7 @@ namespace SabreTools.Library.DatFiles
ParseAddHelper(rom, clean, remUnicode);
break;
case ItemType.Sample:
Sample sample = new Sample()
{
@@ -352,13 +390,13 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
@@ -394,7 +432,7 @@ namespace SabreTools.Library.DatFiles
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
}
// Now, output the rom data
@@ -444,91 +482,91 @@ namespace SabreTools.Library.DatFiles
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(StreamWriter sw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
// TODO: Clean up this mess and make it more like the other DatFile types
// TODO: Specifically, make it so that each ItemType has its own block, if possible
try
{
// Initialize all strings
string state = "",
pre = "",
post = "",
type = "",
romname = "",
diskname = "",
size = "",
crc = "",
md5 = "",
ripemd160 = "",
sha1 = "",
sha256 = "",
sha384 = "",
sha512 = "",
status = "";
string state = string.Empty,
pre = string.Empty,
post = string.Empty,
type = string.Empty,
romname = string.Empty,
diskname = string.Empty,
size = string.Empty,
crc = string.Empty,
md5 = string.Empty,
ripemd160 = string.Empty,
sha1 = string.Empty,
sha256 = string.Empty,
sha384 = string.Empty,
sha512 = string.Empty,
status = string.Empty;
// Separated values should only output Rom and Disk
if (rom.ItemType != ItemType.Disk && rom.ItemType != ItemType.Rom)
{
if (datItem.ItemType != ItemType.Disk && datItem.ItemType != ItemType.Rom)
return true;
}
if (rom.ItemType == ItemType.Rom)
{
type = "rom";
romname = rom.Name;
size = ((Rom)rom).Size.ToString();
crc = ((Rom)rom).CRC;
md5 = ((Rom)rom).MD5;
ripemd160 = ((Rom)rom).RIPEMD160;
sha1 = ((Rom)rom).SHA1;
sha256 = ((Rom)rom).SHA256;
sha384 = ((Rom)rom).SHA384;
sha512 = ((Rom)rom).SHA512;
status = (((Rom)rom).ItemStatus != ItemStatus.None ? "\"" + ((Rom)rom).ItemStatus.ToString() + "\"" : "\"\"");
}
else if (rom.ItemType == ItemType.Disk)
if (datItem.ItemType == ItemType.Disk)
{
var disk = datItem as Disk;
type = "disk";
diskname = rom.Name;
md5 = ((Disk)rom).MD5;
ripemd160 = ((Disk)rom).RIPEMD160;
sha1 = ((Disk)rom).SHA1;
sha256 = ((Disk)rom).SHA256;
sha384 = ((Disk)rom).SHA384;
sha512 = ((Disk)rom).SHA512;
status = (((Disk)rom).ItemStatus != ItemStatus.None ? "\"" + ((Disk)rom).ItemStatus.ToString() + "\"" : "\"\"");
diskname = datItem.Name;
md5 = disk.MD5;
ripemd160 = disk.RIPEMD160;
sha1 = disk.SHA1;
sha256 = disk.SHA256;
sha384 = disk.SHA384;
sha512 = disk.SHA512;
status = (disk.ItemStatus != ItemStatus.None ? $"\"{disk.ItemStatus}\"" : "\"\"");
}
else if (datItem.ItemType == ItemType.Rom)
{
var rom = datItem as Rom;
type = "rom";
romname = datItem.Name;
size = rom.Size.ToString();
crc = rom.CRC;
md5 = rom.MD5;
ripemd160 = rom.RIPEMD160;
sha1 = rom.SHA1;
sha256 = rom.SHA256;
sha384 = rom.SHA384;
sha512 = rom.SHA512;
status = (rom.ItemStatus != ItemStatus.None ? $"\"{rom.ItemStatus}\"" : "\"\"");
}
pre = CreatePrefixPostfix(rom, true);
post = CreatePrefixPostfix(rom, false);
string inline = string.Format("\"" + FileName + "\""
+ "{0}\"" + Name + "\""
+ "{0}\"" + Description + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.Description] ? rom.MachineDescription : "") + "\""
+ "{0}\"" + type + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.Name] ? romname : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.Name] ? diskname : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.Size] ? size : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.CRC] ? crc : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.MD5] ? md5 : "") + "\""
// + "{0}\"" + (!ExcludeFields[(int)Field.RIPEMD160] ? ripemd160 : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.SHA1] ? sha1 : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.SHA256] ? sha256 : "") + "\""
// + "{0}\"" + (!ExcludeFields[(int)Field.SHA384] ? sha384 : "") + "\""
// + "{0}\"" + (!ExcludeFields[(int)Field.SHA512] ? sha512 : "") + "\""
+ "{0}" + status, _delim);
state += pre + inline + post + "\n";
pre = CreatePrefixPostfix(datItem, true);
post = CreatePrefixPostfix(datItem, false);
string inline = string.Format($"\"{FileName}\""
+ $"{0}\"{Name}\""
+ $"{0}\"{Description}\""
+ $"{0}\"{(!ExcludeFields[(int)Field.MachineName] ? datItem.MachineName : string.Empty)}\""
+ $"{0}\"{(!ExcludeFields[(int)Field.Description] ? datItem.MachineDescription : string.Empty)}\""
+ $"{0}\"{type}\""
+ $"{0}\"{(!ExcludeFields[(int)Field.Name] ? romname : string.Empty)}\""
+ $"{0}\"{(!ExcludeFields[(int)Field.Name] ? diskname : string.Empty)}\""
+ $"{0}\"{(!ExcludeFields[(int)Field.Size] ? size : string.Empty)}\""
+ $"{0}\"{(!ExcludeFields[(int)Field.CRC] ? crc : string.Empty)}\""
+ $"{0}\"{(!ExcludeFields[(int)Field.MD5] ? md5 : string.Empty)}\""
// + $"{0}\"{(!ExcludeFields[(int)Field.RIPEMD160] ? ripemd160 : string.Empty)}\""
+ $"{0}\"{(!ExcludeFields[(int)Field.SHA1] ? sha1 : string.Empty)}\""
+ $"{0}\"{(!ExcludeFields[(int)Field.SHA256] ? sha256 : string.Empty)}\""
// + $"{0}\"{(!ExcludeFields[(int)Field.SHA384] ? sha384 : string.Empty)}\""
// + $"{0}\"{(!ExcludeFields[(int)Field.SHA512] ? sha512 : string.Empty)}\""
+ $"{0}\"{(!ExcludeFields[(int)Field.Status] ? status : string.Empty)}\"",
_delim);
state += $"{pre}{inline}{post}\n";
sw.Write(state);
sw.Flush();

View File

@@ -1,20 +1,12 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Text;
using System.Xml;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.Tools;
#if MONO
using System.IO;
#else
using Alphaleonis.Win32.Filesystem;
using FileStream = System.IO.FileStream;
using StreamWriter = System.IO.StreamWriter;
#endif
using NaturalSort;
namespace SabreTools.Library.DatFiles
@@ -60,9 +52,7 @@ namespace SabreTools.Library.DatFiles
// If we got a null reader, just return
if (xtr == null)
{
return;
}
// Otherwise, read the file to the end
try
@@ -80,22 +70,20 @@ namespace SabreTools.Library.DatFiles
switch (xtr.Name)
{
case "softwarelist":
Name = (String.IsNullOrWhiteSpace(Name) ? xtr.GetAttribute("name") ?? "" : Name);
Description = (String.IsNullOrWhiteSpace(Description) ? xtr.GetAttribute("description") ?? "" : Description);
Name = (string.IsNullOrWhiteSpace(Name) ? xtr.GetAttribute("name") ?? string.Empty : Name);
Description = (string.IsNullOrWhiteSpace(Description) ? xtr.GetAttribute("description") ?? string.Empty : Description);
if (ForceMerging == ForceMerging.None)
{
ForceMerging = Utilities.GetForceMerging(xtr.GetAttribute("forcemerging"));
}
if (ForceNodump == ForceNodump.None)
{
ForceNodump = Utilities.GetForceNodump(xtr.GetAttribute("forcenodump"));
}
if (ForcePacking == ForcePacking.None)
{
ForcePacking = Utilities.GetForcePacking(xtr.GetAttribute("forcepacking"));
}
xtr.Read();
break;
// We want to process the entire subtree of the machine
case "software":
ReadSoftware(xtr.ReadSubtree(), filename, sysid, srcid, keep, clean, remUnicode);
@@ -103,6 +91,7 @@ namespace SabreTools.Library.DatFiles
// Skip the software now that we've processed it
xtr.Skip();
break;
default:
xtr.Read();
break;
@@ -111,7 +100,7 @@ namespace SabreTools.Library.DatFiles
}
catch (Exception ex)
{
Globals.Logger.Warning("Exception found while parsing '{0}': {1}", filename, ex);
Globals.Logger.Warning($"Exception found while parsing '{filename}': {ex}");
// For XML errors, just skip the affected node
xtr?.Read();
@@ -145,31 +134,25 @@ namespace SabreTools.Library.DatFiles
{
// If we have an empty software, skip it
if (reader == null)
{
return;
}
// Otherwise, add what is possible
reader.MoveToContent();
string key = "";
string key = string.Empty;
string temptype = reader.Name;
bool containsItems = false;
// Create a new machine
MachineType machineType = MachineType.NULL;
if (Utilities.GetYesNo(reader.GetAttribute("isbios")) == true)
{
machineType |= MachineType.Bios;
}
if (Utilities.GetYesNo(reader.GetAttribute("isdevice")) == true)
{
machineType |= MachineType.Device;
}
if (Utilities.GetYesNo(reader.GetAttribute("ismechanical")) == true)
{
machineType |= MachineType.Mechanical;
}
Machine machine = new Machine
{
@@ -177,7 +160,7 @@ namespace SabreTools.Library.DatFiles
Description = reader.GetAttribute("name"),
Supported = Utilities.GetYesNo(reader.GetAttribute("supported")), // (yes|partial|no) "yes"
CloneOf = reader.GetAttribute("cloneof") ?? "",
CloneOf = reader.GetAttribute("cloneof") ?? string.Empty,
Infos = new List<Tuple<string, string>>(),
MachineType = (machineType == MachineType.NULL ? MachineType.None : machineType),
@@ -198,29 +181,33 @@ namespace SabreTools.Library.DatFiles
case "description":
machine.Description = reader.ReadElementContentAsString();
break;
case "year":
machine.Year = reader.ReadElementContentAsString();
break;
case "publisher":
machine.Publisher = reader.ReadElementContentAsString();
break;
case "info":
machine.Infos.Add(new Tuple<string, string>(reader.GetAttribute("name"), reader.GetAttribute("value")));
reader.Read();
break;
case "sharedfeat":
// string sharedfeat_name = reader.GetAttribute("name");
// string sharedfeat_value = reader.GetAttribute("value");
reader.Read();
break;
case "part": // Contains all rom and disk information
containsItems = ReadPart(reader.ReadSubtree(), machine, filename, sysid, srcid, keep, clean, remUnicode);
// Skip the part now that we've processed it
reader.Skip();
break;
default:
reader.Read();
break;
@@ -268,7 +255,7 @@ namespace SabreTools.Library.DatFiles
bool clean,
bool remUnicode)
{
string key = "", areaname = "", partname = "", partinterface = "";
string key = string.Empty, areaname = string.Empty, partname = string.Empty, partinterface = string.Empty;
string temptype = reader.Name;
long? areasize = null;
List<Tuple<string, string>> features = new List<Tuple<string, string>>();
@@ -281,13 +268,14 @@ namespace SabreTools.Library.DatFiles
{
if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "part")
{
partname = "";
partinterface = "";
partname = string.Empty;
partinterface = string.Empty;
features = new List<Tuple<string, string>>();
}
if (reader.NodeType == XmlNodeType.EndElement && (reader.Name == "dataarea" || reader.Name == "diskarea"))
{
areaname = "";
areaname = string.Empty;
areasize = null;
}
@@ -301,23 +289,22 @@ namespace SabreTools.Library.DatFiles
case "part":
partname = reader.GetAttribute("name");
partinterface = reader.GetAttribute("interface");
reader.Read();
break;
case "feature":
features.Add(new Tuple<string, string>(reader.GetAttribute("name"), reader.GetAttribute("feature")));
reader.Read();
break;
case "dataarea":
areaname = reader.GetAttribute("name");
if (reader.GetAttribute("size") != null)
{
if (Int64.TryParse(reader.GetAttribute("size"), out long tempas))
{
areasize = tempas;
}
}
// string dataarea_width = reader.GetAttribute("width"); // (8|16|32|64) "8"
// string dataarea_endianness = reader.GetAttribute("endianness"); // endianness (big|little) "little"
@@ -327,6 +314,7 @@ namespace SabreTools.Library.DatFiles
// Skip the dataarea now that we've processed it
reader.Skip();
break;
case "diskarea":
areaname = reader.GetAttribute("name");
@@ -336,6 +324,7 @@ namespace SabreTools.Library.DatFiles
// Skip the diskarea now that we've processed it
reader.Skip();
break;
case "dipswitch":
// string dipswitch_name = reader.GetAttribute("name");
// string dipswitch_tag = reader.GetAttribute("tag");
@@ -348,6 +337,7 @@ namespace SabreTools.Library.DatFiles
reader.Skip();
break;
default:
reader.Read();
break;
@@ -392,7 +382,7 @@ namespace SabreTools.Library.DatFiles
bool clean,
bool remUnicode)
{
string key = "";
string key = string.Empty;
string temptype = reader.Name;
bool containsItems = false;
@@ -460,6 +450,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
default:
reader.Read();
break;
@@ -504,7 +495,7 @@ namespace SabreTools.Library.DatFiles
bool clean,
bool remUnicode)
{
string key = "";
string key = string.Empty;
string temptype = reader.Name;
bool containsItems = false;
@@ -553,6 +544,7 @@ namespace SabreTools.Library.DatFiles
reader.Read();
break;
default:
reader.Read();
break;
@@ -572,20 +564,21 @@ namespace SabreTools.Library.DatFiles
{
try
{
Globals.Logger.User("Opening file for writing: {0}", outfile);
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
XmlTextWriter xtw = new XmlTextWriter(fs, new UTF8Encoding(false));
xtw.Formatting = Formatting.Indented;
// Write out the header
WriteHeader(sw);
WriteHeader(xtw);
// Write out each of the machines and roms
string lastgame = null;
@@ -614,29 +607,25 @@ namespace SabreTools.Library.DatFiles
// 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.MachineName.ToLowerInvariant())
{
WriteEndGame(sw);
}
WriteEndGame(xtw);
// If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{
WriteStartGame(sw, rom);
}
WriteStartGame(xtw, rom);
// If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null")
{
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
Globals.Logger.Verbose($"Empty folder found: {rom.MachineName}");
lastgame = rom.MachineName;
continue;
}
// Now, output the rom data
WriteDatItem(sw, rom, ignoreblanks);
WriteDatItem(xtw, rom, ignoreblanks);
// Set the new data to compare against
lastgame = rom.MachineName;
@@ -644,10 +633,10 @@ namespace SabreTools.Library.DatFiles
}
// Write the file footer out
WriteFooter(sw);
WriteFooter(xtw);
Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose();
xtw.Dispose();
fs.Dispose();
}
catch (Exception ex)
@@ -662,30 +651,59 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DAT header using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteHeader(StreamWriter sw)
private bool WriteHeader(XmlTextWriter xtw)
{
try
{
string header = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE softwarelist SYSTEM \"softwarelist.dtd\">\n\n" +
"<softwarelist name=\"" + WebUtility.HtmlEncode(Name) + "\"" +
" description=\"" + WebUtility.HtmlEncode(Description) + "\"" +
(ForcePacking == ForcePacking.Unzip ? " forcepacking=\"unzip\"" : "") +
(ForcePacking == ForcePacking.Zip ? " forcepacking=\"zip\"" : "") +
(ForceMerging == ForceMerging.Full ? " forcemerging=\"full\"" : "") +
(ForceMerging == ForceMerging.Split ? " forcemerging=\"split\"" : "") +
(ForceMerging == ForceMerging.Merged ? " forcemerging=\"merged\"" : "") +
(ForceMerging == ForceMerging.NonMerged ? " forcemerging=\"nonmerged\"" : "") +
(ForceNodump == ForceNodump.Ignore ? " forcenodump=\"ignore\"" : "") +
(ForceNodump == ForceNodump.Obsolete ? " forcenodump=\"obsolete\"" : "") +
(ForceNodump == ForceNodump.Required ? " forcenodump=\"required\"" : "") +
">\n\n";
xtw.WriteStartDocument();
xtw.WriteDocType("softwarelist", null, "softwarelist.dtd", null);
// Write the header out
sw.Write(header);
sw.Flush();
xtw.WriteStartElement("softwarelist");
xtw.WriteAttributeString("name", Name);
xtw.WriteAttributeString("description", Description);
switch (ForcePacking)
{
case ForcePacking.Unzip:
xtw.WriteAttributeString("forcepacking", "unzip");
break;
case ForcePacking.Zip:
xtw.WriteAttributeString("forcepacking", "zip");
break;
}
switch (ForceMerging)
{
case ForceMerging.Full:
xtw.WriteAttributeString("forcemerging", "full");
break;
case ForceMerging.Split:
xtw.WriteAttributeString("forcemerging", "split");
break;
case ForceMerging.Merged:
xtw.WriteAttributeString("forcemerging", "merged");
break;
case ForceMerging.NonMerged:
xtw.WriteAttributeString("forcemerging", "nonmerged");
break;
}
switch (ForceNodump)
{
case ForceNodump.Ignore:
xtw.WriteAttributeString("forcenodump", "ignore");
break;
case ForceNodump.Obsolete:
xtw.WriteAttributeString("forcenodump", "obsolete");
break;
case ForceNodump.Required:
xtw.WriteAttributeString("forcenodump", "required");
break;
}
xtw.Flush();
}
catch (Exception ex)
{
@@ -699,37 +717,52 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteStartGame(StreamWriter sw, DatItem rom)
private bool WriteStartGame(XmlTextWriter xtw, DatItem datItem)
{
try
{
// No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
datItem.MachineName = datItem.MachineName.TrimStart(Path.DirectorySeparatorChar);
// Build the state based on excluded fields
xtw.WriteStartElement("software");
xtw.WriteAttributeString("name", datItem.GetField(Field.MachineName, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CloneOf, ExcludeFields)) && !string.Equals(datItem.MachineName, datItem.CloneOf, StringComparison.OrdinalIgnoreCase))
xtw.WriteAttributeString("cloneof", datItem.CloneOf);
if (!ExcludeFields[(int)Field.Supported])
{
rom.MachineName = rom.MachineName.Substring(1);
if (datItem.Supported == true)
xtw.WriteAttributeString("supported", "yes");
else if (datItem.Supported == false)
xtw.WriteAttributeString("supported", "no");
else
xtw.WriteAttributeString("supported", "partial");
}
string state = "\t<software name=\"" + (!ExcludeFields[(int)Field.MachineName] ? WebUtility.HtmlEncode(rom.MachineName) : "") + "\""
+ (!ExcludeFields[(int)Field.CloneOf] && !String.IsNullOrWhiteSpace(rom.CloneOf) && (rom.MachineName.ToLowerInvariant() != rom.CloneOf.ToLowerInvariant())
? " cloneof=\"" + WebUtility.HtmlEncode(rom.CloneOf) + "\"" : "")
+ (!ExcludeFields[(int)Field.Supported] ? " supported=\"" + (rom.Supported == true ? "yes" : rom.Supported == false ? "no" : "partial") + "\">\n" : "")
+ (!ExcludeFields[(int)Field.Description] ? "\t\t<description>" + WebUtility.HtmlEncode(rom.MachineDescription) + "</description>\n" : "")
+ (!ExcludeFields[(int)Field.Year] && rom.Year != null ? "\t\t<year>" + WebUtility.HtmlEncode(rom.Year) + "</year>\n" : "")
+ (!ExcludeFields[(int)Field.Publisher] && rom.Publisher != null ? "\t\t<publisher>" + WebUtility.HtmlEncode(rom.Publisher) + "</publisher>\n" : "");
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Description, ExcludeFields)))
xtw.WriteElementString("description", datItem.MachineDescription);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Year, ExcludeFields)))
xtw.WriteElementString("year", datItem.Year);
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Publisher, ExcludeFields)))
xtw.WriteElementString("publisher", datItem.Publisher);
if (!ExcludeFields[(int)Field.Infos])
if (!ExcludeFields[(int)Field.Infos] && datItem.Infos != null && datItem.Infos.Count > 0)
{
foreach (Tuple<string, string> kvp in rom.Infos)
foreach (Tuple<string, string> kvp in datItem.Infos)
{
state += "\t\t<info name=\"" + WebUtility.HtmlEncode(kvp.Item1) + "\" value=\"" + WebUtility.HtmlEncode(kvp.Item2) + "\" />\n";
xtw.WriteStartElement("info");
xtw.WriteAttributeString("name", kvp.Item1);
xtw.WriteAttributeString("value", kvp.Item2);
xtw.WriteEndElement();
}
}
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -743,16 +776,16 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteEndGame(StreamWriter sw)
private bool WriteEndGame(XmlTextWriter xtw)
{
try
{
string state = "\t</software>\n\n";
// End software
xtw.WriteEndElement();
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -766,80 +799,121 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
private bool WriteDatItem(XmlTextWriter xtw, DatItem datItem, bool ignoreblanks = false)
{
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks
&& (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{
if (ignoreblanks && (datItem.ItemType == ItemType.Rom && ((datItem as Rom).Size == 0 || (datItem as Rom).Size == -1)))
return true;
}
try
{
string state = "";
// Pre-process the item name
ProcessItemName(rom, true);
ProcessItemName(datItem, true);
state += "\t\t<part name=\"" + (!ExcludeFields[(int)Field.PartName] ? rom.PartName : "") + "\" interface=\""
+ (!ExcludeFields[(int)Field.PartInterface] ? rom.PartInterface : "") + "\">\n";
// Build the state based on excluded fields
xtw.WriteStartElement("part");
xtw.WriteAttributeString("name", datItem.GetField(Field.PartName, ExcludeFields));
xtw.WriteAttributeString("interface", datItem.GetField(Field.PartInterface, ExcludeFields));
if (!ExcludeFields[(int)Field.Features])
if (!ExcludeFields[(int)Field.Features] && datItem.Features != null && datItem.Features.Count > 0)
{
foreach (Tuple<string, string> kvp in rom.Features)
foreach (Tuple<string, string> kvp in datItem.Features)
{
state += "\t\t\t<feature name=\"" + WebUtility.HtmlEncode(kvp.Item1) + "\" value=\"" + WebUtility.HtmlEncode(kvp.Item2) + "\"/>\n";
xtw.WriteStartElement("feature");
xtw.WriteAttributeString("name", kvp.Item1);
xtw.WriteAttributeString("value", kvp.Item2);
xtw.WriteEndElement();
}
}
switch (rom.ItemType)
string areaName = datItem.GetField(Field.AreaName, ExcludeFields);
switch (datItem.ItemType)
{
case ItemType.Disk:
state += "\t\t\t<diskarea name=\"" + (!ExcludeFields[(int)Field.AreaName] ? (String.IsNullOrWhiteSpace(rom.AreaName) ? "cdrom" : rom.AreaName) : "") + "\""
+ (!ExcludeFields[(int)Field.AreaSize] && rom.AreaSize != null ? " size=\"" + rom.AreaSize + "\"" : "") + ">\n"
+ "\t\t\t\t<disk name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.MD5] && !String.IsNullOrWhiteSpace(((Disk)rom).MD5) ? " md5=\"" + ((Disk)rom).MD5.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.RIPEMD160] && !String.IsNullOrWhiteSpace(((Disk)rom).RIPEMD160) ? " ripemd160=\"" + ((Disk)rom).RIPEMD160.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA1] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA1) ? " sha1=\"" + ((Disk)rom).SHA1.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA256] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA256) ? " sha256=\"" + ((Disk)rom).SHA256.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA384] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA384) ? " sha384=\"" + ((Disk)rom).SHA384.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA512] && !String.IsNullOrWhiteSpace(((Disk)rom).SHA512) ? " sha512=\"" + ((Disk)rom).SHA512.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus != ItemStatus.None ? " status=\"" + ((Disk)rom).ItemStatus.ToString().ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Writable] && ((Disk)rom).Writable != null ? " writable=\"" + (((Disk)rom).Writable == true ? "yes" : "no") + "\"" : "")
+ "/>\n"
+ "\t\t\t</diskarea>\n";
var disk = datItem as Disk;
if (!ExcludeFields[(int)Field.AreaName] && string.IsNullOrWhiteSpace(areaName))
areaName = "cdrom";
xtw.WriteStartElement("diskarea");
xtw.WriteAttributeString("name", areaName);
if (!ExcludeFields[(int)Field.AreaSize] && disk.AreaSize != null)
xtw.WriteAttributeString("size", disk.AreaSize.ToString());
xtw.WriteStartElement("disk");
xtw.WriteAttributeString("name", disk.GetField(Field.Name, ExcludeFields));
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
xtw.WriteAttributeString("md5", disk.MD5.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RIPEMD160, ExcludeFields)))
xtw.WriteAttributeString("ripemd160", disk.RIPEMD160.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
xtw.WriteAttributeString("sha1", disk.SHA1.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA256, ExcludeFields)))
xtw.WriteAttributeString("sha256", disk.SHA256.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA384, ExcludeFields)))
xtw.WriteAttributeString("sha384", disk.SHA384.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA512, ExcludeFields)))
xtw.WriteAttributeString("sha512", disk.SHA512.ToLowerInvariant());
if (!ExcludeFields[(int)Field.Status] && disk.ItemStatus != ItemStatus.None)
xtw.WriteAttributeString("status", disk.ItemStatus.ToString().ToLowerInvariant());
if (!ExcludeFields[(int)Field.Writable] && disk.Writable != null)
xtw.WriteAttributeString("writable", disk.Writable == true ? "yes" : "no");
xtw.WriteEndElement();
// End diskarea
xtw.WriteEndElement();
break;
case ItemType.Rom:
state += "\t\t\t<dataarea name=\"" + (!ExcludeFields[(int)Field.AreaName] ? (String.IsNullOrWhiteSpace(rom.AreaName) ? "rom" : rom.AreaName) : "") + "\""
+ (!ExcludeFields[(int)Field.AreaSize] && rom.AreaSize != null ? " size=\"" + rom.AreaSize + "\"" : "") + ">\n"
+ "\t\t\t\t<rom name=\"" + (!ExcludeFields[(int)Field.Name] ? WebUtility.HtmlEncode(rom.Name) : "") + "\""
+ (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? " size=\"" + ((Rom)rom).Size + "\"" : "")
+ (!ExcludeFields[(int)Field.CRC] && !String.IsNullOrWhiteSpace(((Rom)rom).CRC) ? " crc=\"" + ((Rom)rom).CRC.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.MD5] && !String.IsNullOrWhiteSpace(((Rom)rom).MD5) ? " md5=\"" + ((Rom)rom).MD5.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.RIPEMD160] && !String.IsNullOrWhiteSpace(((Rom)rom).RIPEMD160) ? " ripemd160=\"" + ((Rom)rom).RIPEMD160.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA1] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA1) ? " sha1=\"" + ((Rom)rom).SHA1.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA256] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA256) ? " sha256=\"" + ((Rom)rom).SHA256.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA384] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA384) ? " sha384=\"" + ((Rom)rom).SHA384.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.SHA512] && !String.IsNullOrWhiteSpace(((Rom)rom).SHA512) ? " sha512=\"" + ((Rom)rom).SHA512.ToLowerInvariant() + "\"" : "")
+ (!ExcludeFields[(int)Field.Offset] && !String.IsNullOrWhiteSpace(((Rom)rom).Offset) ? " offset=\"" + ((Rom)rom).Offset + "\"" : "")
// + (!ExcludeFields[(int)Field.Value] && !String.IsNullOrWhiteSpace(((Rom)rom).Value) ? " value=\"" + ((Rom)rom).Value + "\"" : "")
+ (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus != ItemStatus.None ? " status=\"" + ((Rom)rom).ItemStatus.ToString().ToLowerInvariant() + "\"" : "")
// + (!ExcludeFields[(int)Field.Loadflag] && !String.IsNullOrWhiteSpace(((Rom)rom).Loadflag) ? " loadflag=\"" + ((Rom)rom).Loadflag + "\"" : "")
+ "/>\n"
+ "\t\t\t</dataarea>\n";
var rom = datItem as Rom;
if (!ExcludeFields[(int)Field.AreaName] && string.IsNullOrWhiteSpace(areaName))
areaName = "rom";
xtw.WriteStartElement("dataarea");
xtw.WriteAttributeString("name", areaName);
if (!ExcludeFields[(int)Field.AreaSize] && rom.AreaSize != null)
xtw.WriteAttributeString("size", rom.AreaSize.ToString());
xtw.WriteStartElement("rom");
xtw.WriteAttributeString("name", rom.GetField(Field.Name, ExcludeFields));
if (!ExcludeFields[(int)Field.Size] && rom.Size != -1)
xtw.WriteAttributeString("size", rom.Size.ToString());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CRC, ExcludeFields)))
xtw.WriteAttributeString("crc", rom.CRC.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.MD5, ExcludeFields)))
xtw.WriteAttributeString("md5", rom.MD5.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.RIPEMD160, ExcludeFields)))
xtw.WriteAttributeString("ripemd160", rom.RIPEMD160.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA1, ExcludeFields)))
xtw.WriteAttributeString("sha1", rom.SHA1.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA256, ExcludeFields)))
xtw.WriteAttributeString("sha256", rom.SHA256.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA384, ExcludeFields)))
xtw.WriteAttributeString("sha384", rom.SHA384.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SHA512, ExcludeFields)))
xtw.WriteAttributeString("sha512", rom.SHA512.ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Offset, ExcludeFields)))
xtw.WriteAttributeString("offset", rom.Offset);
//if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Value, ExcludeFields)))
// xtw.WriteAttributeString("value", rom.Value);
if (!ExcludeFields[(int)Field.Status] && rom.ItemStatus != ItemStatus.None)
xtw.WriteAttributeString("status", rom.ItemStatus.ToString().ToLowerInvariant());
//if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Loadflag, ExcludeFields)))
// xtw.WriteAttributeString("loadflag", rom.Loadflag);
xtw.WriteEndElement();
// End dataarea
xtw.WriteEndElement();
break;
}
state += "\t\t</part>\n";
// End part
xtw.WriteEndElement();
sw.Write(state);
sw.Flush();
xtw.Flush();
}
catch (Exception ex)
{
@@ -853,17 +927,19 @@ namespace SabreTools.Library.DatFiles
/// <summary>
/// Write out DAT footer using the supplied StreamWriter
/// </summary>
/// <param name="sw">StreamWriter to output to</param>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <returns>True if the data was written, false on error</returns>
private bool WriteFooter(StreamWriter sw)
private bool WriteFooter(XmlTextWriter xtw)
{
try
{
string footer = "\t</software>\n\n</softwarelist>\n";
// End software
xtw.WriteEndElement();
// Write the footer out
sw.Write(footer);
sw.Flush();
// End softwarelist
xtw.WriteEndElement();
xtw.Flush();
}
catch (Exception ex)
{