diff --git a/SabreTools.DatFiles/Formats/SoftwareList.Reader.cs b/SabreTools.DatFiles/Formats/SoftwareList.Reader.cs
index 51683867..c82ea260 100644
--- a/SabreTools.DatFiles/Formats/SoftwareList.Reader.cs
+++ b/SabreTools.DatFiles/Formats/SoftwareList.Reader.cs
@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Xml;
-using System.Xml.Schema;
-using SabreTools.Core;
using SabreTools.Core.Tools;
using SabreTools.DatItems;
using SabreTools.DatItems.Formats;
@@ -18,174 +15,139 @@ namespace SabreTools.DatFiles.Formats
///
public override void ParseFile(string filename, int indexId, bool keep, bool statsOnly = false, bool throwOnError = false)
{
- // Prepare all internal variables
- XmlReader xtr = XmlReader.Create(filename, new XmlReaderSettings
- {
- CheckCharacters = false,
- DtdProcessing = DtdProcessing.Ignore,
- IgnoreComments = true,
- IgnoreWhitespace = true,
- ValidationFlags = XmlSchemaValidationFlags.None,
- ValidationType = ValidationType.None,
- });
-
- // If we got a null reader, just return
- if (xtr == null)
- return;
-
- // Otherwise, read the file to the end
try
{
- xtr.MoveToContent();
- while (!xtr.EOF)
- {
- // We only want elements
- if (xtr.NodeType != XmlNodeType.Element)
- {
- xtr.Read();
- continue;
- }
+ // Deserialize the input file
+ var softwarelist = Serialization.SoftawreList.Deserialize(filename);
- switch (xtr.Name)
- {
- case "softwarelist":
- Header.Name ??= xtr.GetAttribute("name") ?? string.Empty;
- Header.Description ??= xtr.GetAttribute("description") ?? string.Empty;
+ // Convert the header to the internal format
+ ConvertHeader(softwarelist, keep);
- xtr.Read();
- break;
-
- // We want to process the entire subtree of the machine
- case "software":
- ReadSoftware(xtr.ReadSubtree(), statsOnly, filename, indexId);
-
- // Skip the software now that we've processed it
- xtr.Skip();
- break;
-
- default:
- xtr.Read();
- break;
- }
- }
+ // Convert the software data to the internal format
+ ConvertSoftware(softwarelist?.Software, filename, indexId, statsOnly);
}
catch (Exception ex) when (!throwOnError)
{
- logger.Warning(ex, $"Exception found while parsing '{filename}'");
-
- // For XML errors, just skip the affected node
- xtr?.Read();
+ string message = $"'{filename}' - An error occurred during parsing";
+ logger.Error(ex, message);
}
+ }
- xtr.Dispose();
+ #region Converters
+
+ ///
+ /// Convert header information
+ ///
+ /// Deserialized model to convert
+ /// True if full pathnames are to be kept, false otherwise (default)
+ private void ConvertHeader(Models.SoftwareList.SoftwareList? softwarelist, bool keep)
+ {
+ // If the datafile is missing, we can't do anything
+ if (softwarelist == null)
+ return;
+
+ Header.Name ??= softwarelist.Name;
+ Header.Description ??= softwarelist.Description;
+ Header.Comment ??= softwarelist.Notes;
+
+ // Handle implied SuperDAT
+ if (Header.Name.Contains(" - SuperDAT") && keep)
+ Header.Type ??= "SuperDAT";
}
///
- /// Read software information
+ /// Convert software information
///
- /// XmlReader representing a software block
- /// True to only add item statistics while parsing, false otherwise
+ /// Array of deserialized models to convert
/// Name of the file to be parsed
/// Index ID for the DAT
- private void ReadSoftware(XmlReader reader, bool statsOnly, string filename, int indexId)
+ /// True to only add item statistics while parsing, false otherwise
+ private void ConvertSoftware(Models.SoftwareList.Software[]? software, string filename, int indexId, bool statsOnly)
{
- // If we have an empty software, skip it
- if (reader == null)
+ // If the game array is missing, we can't do anything
+ if (software == null || !software.Any())
return;
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- bool containsItems = false;
-
- // Create a new machine
- Machine machine = new()
+ // Loop through the software and add
+ foreach (var sw in software)
{
- Name = reader.GetAttribute("name"),
- CloneOf = reader.GetAttribute("cloneof"),
- Supported = reader.GetAttribute("supported").AsSupported(),
+ ConvertSoftware(sw, filename, indexId, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert software information
+ ///
+ /// Deserialized model to convert
+ /// Name of the file to be parsed
+ /// Index ID for the DAT
+ /// True to only add item statistics while parsing, false otherwise
+ private void ConvertSoftware(Models.SoftwareList.Software software, string filename, int indexId, bool statsOnly)
+ {
+ // If the game is missing, we can't do anything
+ if (software == null)
+ return;
+
+ // Create the machine for copying information
+ var machine = new Machine
+ {
+ Name = software.Name,
+ CloneOf = software.CloneOf,
+ Supported = software.Supported.AsSupported(),
+ Description = software.Description,
+ Year = software.Year,
+ Publisher = software.Publisher,
+ Comment = software.Notes,
};
- while (!reader.EOF)
+ // Add all Info objects
+ foreach (var info in software.Info ?? Array.Empty())
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var infoItem = new Info
{
- reader.Read();
- continue;
- }
+ Name = info.Name,
+ Value = info.Value,
- // Get the elements from the software
- switch (reader.Name)
- {
- case "description":
- machine.Description = reader.ReadElementContentAsString();
- break;
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
- case "year":
- machine.Year = reader.ReadElementContentAsString();
- break;
-
- case "publisher":
- machine.Publisher = reader.ReadElementContentAsString();
- break;
-
- case "info":
- ParseAddHelper(new Info
- {
- Name = reader.GetAttribute("name"),
- Value = reader.GetAttribute("value"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- }, statsOnly);
-
- reader.Read();
- break;
-
- case "sharedfeat":
- ParseAddHelper(new SharedFeature
- {
- Name = reader.GetAttribute("name"),
- Value = reader.GetAttribute("value"),
-
- Source = new Source
- {
- Index = indexId,
- Name = filename,
- },
- }, statsOnly);
-
- reader.Read();
- break;
-
- case "part": // Contains all rom and disk information
- var part = new Part()
- {
- Name = reader.GetAttribute("name"),
- Interface = reader.GetAttribute("interface"),
- };
-
- // Now read the internal tags
- containsItems = ReadPart(reader.ReadSubtree(), machine, part, statsOnly, filename, indexId);
-
- // Skip the part now that we've processed it
- reader.Skip();
- break;
-
- default:
- reader.Read();
- break;
- }
+ infoItem.CopyMachineInformation(machine);
+ ParseAddHelper(infoItem, statsOnly);
}
- // If no items were found for this machine, add a Blank placeholder
+ // Add all SharedFeat objects
+ foreach (var sharedfeat in software.SharedFeat ?? Array.Empty())
+ {
+ var sharedfeatItem = new SharedFeature
+ {
+ Name = sharedfeat.Name,
+ Value = sharedfeat.Value,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ sharedfeatItem.CopyMachineInformation(machine);
+ ParseAddHelper(sharedfeatItem, statsOnly);
+ }
+
+ // Check if there are any items
+ bool containsItems = false;
+
+ // Loop through each type of item
+ ConvertPart(software.Part, machine, filename, indexId, statsOnly, ref containsItems);
+
+ // If we had no items, create a Blank placeholder
if (!containsItems)
{
- Blank blank = new()
+ var blank = new Blank
{
Source = new Source
{
@@ -195,302 +157,319 @@ namespace SabreTools.DatFiles.Formats
};
blank.CopyMachineInformation(machine);
-
- // Now process and add the rom
ParseAddHelper(blank, statsOnly);
}
}
///
- /// Read part information
+ /// Convert Part information
///
- /// XmlReader representing a part block
- /// Machine information to pass to contained items
- /// Part information to pass to contained items
- /// True to only add item statistics while parsing, false otherwise
+ /// Array of deserialized models to convert
+ /// Prefilled machine to use
/// Name of the file to be parsed
/// Index ID for the DAT
- private bool ReadPart(XmlReader reader, Machine machine, Part part, bool statsOnly, string filename, int indexId)
+ /// True to only add item statistics while parsing, false otherwise
+ /// True if there were any items in the array, false otherwise
+ private void ConvertPart(Models.SoftwareList.Part[]? parts, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
- // If we have an empty port, skip it
- if (reader == null)
- return false;
-
- // Get lists ready
- part.Features = new List();
- List items = new();
-
- while (!reader.EOF)
- {
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
- {
- reader.Read();
- continue;
- }
-
- // Get the elements from the software
- switch (reader.Name)
- {
- case "feature":
- var feature = new PartFeature()
- {
- Name = reader.GetAttribute("name"),
- Value = reader.GetAttribute("value"),
- };
-
- part.Features.Add(feature);
-
- reader.Read();
- break;
-
- case "dataarea":
- var dataArea = new DataArea
- {
- Name = reader.GetAttribute("name"),
- Size = Utilities.CleanLong(reader.GetAttribute("size")),
- Width = Utilities.CleanLong(reader.GetAttribute("width")),
- Endianness = reader.GetAttribute("endianness").AsEndianness(),
- };
-
- List roms = ReadDataArea(reader.ReadSubtree(), dataArea);
-
- // If we got valid roms, add them to the list
- if (roms != null)
- items.AddRange(roms);
-
- // Skip the dataarea now that we've processed it
- reader.Skip();
- break;
-
- case "diskarea":
- var diskArea = new DiskArea
- {
- Name = reader.GetAttribute("name"),
- };
-
- List disks = ReadDiskArea(reader.ReadSubtree(), diskArea);
-
- // If we got valid disks, add them to the list
- if (disks != null)
- items.AddRange(disks);
-
- // Skip the diskarea now that we've processed it
- reader.Skip();
- break;
-
- case "dipswitch":
- var dipSwitch = new DipSwitch
- {
- Name = reader.GetAttribute("name"),
- Tag = reader.GetAttribute("tag"),
- Mask = reader.GetAttribute("mask"),
- };
-
- // Now read the internal tags
- ReadDipSwitch(reader.ReadSubtree(), dipSwitch);
-
- items.Add(dipSwitch);
-
- // Skip the dipswitch now that we've processed it
- reader.Skip();
- break;
-
- default:
- reader.Read();
- break;
- }
- }
-
- // Loop over all of the items, if they exist
- string key = string.Empty;
- foreach (DatItem item in items)
- {
- // Add all missing information
- switch (item.ItemType)
- {
- case ItemType.DipSwitch:
- (item as DipSwitch).Part = part;
- break;
- case ItemType.Disk:
- (item as Disk).Part = part;
- break;
- case ItemType.Rom:
- (item as Rom).Part = part;
-
- // If the rom is continue or ignore, add the size to the previous rom
- // TODO: Can this be done on write? We technically lose information this way.
- // Order is not guaranteed, and since these don't tend to have any way
- // of determining what the "previous" item was after this, that info would
- // have to be stored *with* the item somehow
- if ((item as Rom).LoadFlag == LoadFlag.Continue || (item as Rom).LoadFlag == LoadFlag.Ignore)
- {
- int index = Items[key].Count - 1;
- DatItem lastrom = Items[key][index];
- if (lastrom.ItemType == ItemType.Rom)
- {
- (lastrom as Rom).Size += (item as Rom).Size;
- Items[key].RemoveAt(index);
- Items[key].Add(lastrom);
- }
-
- continue;
- }
-
- break;
- }
-
- item.Source = new Source(indexId, filename);
- item.CopyMachineInformation(machine);
-
- // Finally add each item
- key = ParseAddHelper(item, statsOnly);
- }
-
- return items.Any();
- }
-
- ///
- /// Read dataarea information
- ///
- /// XmlReader representing a dataarea block
- /// DataArea representing the enclosing area
- private List ReadDataArea(XmlReader reader, DataArea dataArea)
- {
- List items = new();
-
- while (!reader.EOF)
- {
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
- {
- reader.Read();
- continue;
- }
-
- // Get the elements from the software
- switch (reader.Name)
- {
- case "rom":
- var rom = new Rom
- {
- Name = reader.GetAttribute("name"),
- Size = Utilities.CleanLong(reader.GetAttribute("size")),
- CRC = reader.GetAttribute("crc"),
- SHA1 = reader.GetAttribute("sha1"),
- Offset = reader.GetAttribute("offset"),
- Value = reader.GetAttribute("value"),
- ItemStatus = reader.GetAttribute("status").AsItemStatus(),
- LoadFlag = reader.GetAttribute("loadflag").AsLoadFlag(),
-
- DataArea = dataArea,
- };
-
- items.Add(rom);
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
- }
-
- return items;
- }
-
- ///
- /// Read diskarea information
- ///
- /// XmlReader representing a diskarea block
- /// DiskArea representing the enclosing area
- private List ReadDiskArea(XmlReader reader, DiskArea diskArea)
- {
- List items = new();
-
- while (!reader.EOF)
- {
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
- {
- reader.Read();
- continue;
- }
-
- // Get the elements from the software
- switch (reader.Name)
- {
- case "disk":
- DatItem disk = new Disk
- {
- Name = reader.GetAttribute("name"),
- SHA1 = reader.GetAttribute("sha1"),
- ItemStatus = reader.GetAttribute("status").AsItemStatus(),
- Writable = reader.GetAttribute("writable").AsYesNo(),
-
- DiskArea = diskArea,
- };
-
- items.Add(disk);
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
- }
-
- return items;
- }
-
- ///
- /// Read DipSwitch DipValues information
- ///
- /// XmlReader representing a diskarea block
- /// DipSwitch to populate
- private void ReadDipSwitch(XmlReader reader, DipSwitch dipSwitch)
- {
- // If we have an empty dipswitch, skip it
- if (reader == null)
+ // If the parts array is missing, we can't do anything
+ if (parts == null || !parts.Any())
return;
- // Get list ready
- dipSwitch.Values = new List();
-
- // Otherwise, add what is possible
- reader.MoveToContent();
-
- while (!reader.EOF)
+ foreach (var part in parts)
{
- // We only want elements
- if (reader.NodeType != XmlNodeType.Element)
+ var item = new Part
{
- reader.Read();
- continue;
- }
+ Name = part.Name,
+ Interface = part.Interface,
+ Features = CreateFeatures(part.Feature, machine, filename, indexId, statsOnly),
- // Get the information from the dipswitch
- switch (reader.Name)
- {
- case "dipvalue":
- var dipValue = new Setting
- {
- Name = reader.GetAttribute("name"),
- Value = reader.GetAttribute("value"),
- Default = reader.GetAttribute("default").AsYesNo(),
- };
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
- dipSwitch.Values.Add(dipValue);
+ item.CopyMachineInformation(machine);
- reader.Read();
- break;
-
- default:
- reader.Read();
- break;
- }
+ ConvertDataArea(part.DataArea, item, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertDiskArea(part.DiskArea, item, machine, filename, indexId, statsOnly, ref containsItems);
+ ConvertDipSwitch(part.DipSwitch, item, machine, filename, indexId, statsOnly, ref containsItems);
}
}
+
+ ///
+ /// Convert Feature information
+ ///
+ /// Array of deserialized models to convert
+ /// Prefilled machine to use
+ /// Name of the file to be parsed
+ /// Index ID for the DAT
+ /// True to only add item statistics while parsing, false otherwise
+ private static List? CreateFeatures(Models.SoftwareList.Feature[]? features, Machine machine, string filename, int indexId, bool statsOnly)
+ {
+ // If the feature array is missing, we can't do anything
+ if (features == null || !features.Any())
+ return null;
+
+ var partFeatures = new List();
+ foreach (var feature in features)
+ {
+ var item = new PartFeature
+ {
+ Name = feature.Name,
+ Value = feature.Value,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ partFeatures.Add(item);
+ }
+
+ return partFeatures;
+ }
+
+ ///
+ /// Convert DataArea information
+ ///
+ /// Array of deserialized models to convert
+ /// Parent Part to use
+ /// Prefilled machine to use
+ /// Name of the file to be parsed
+ /// Index ID for the DAT
+ /// True to only add item statistics while parsing, false otherwise
+ /// True if there were any items in the array, false otherwise
+ private void ConvertDataArea(Models.SoftwareList.DataArea[]? dataareas, Part part, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the dataarea array is missing, we can't do anything
+ if (dataareas == null || !dataareas.Any())
+ return;
+
+ foreach (var dataarea in dataareas)
+ {
+ var item = new DataArea
+ {
+ Name = dataarea.Name,
+ Size = Utilities.CleanLong(dataarea.Size),
+ Width = Utilities.CleanLong(dataarea.Width),
+ Endianness = dataarea.Endianness.AsEndianness(),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ConvertRoms(dataarea.Rom, part, item, machine, filename, indexId, statsOnly, ref containsItems);
+ }
+ }
+
+ ///
+ /// Convert Rom information
+ ///
+ /// Array of deserialized models to convert
+ /// Parent Part to use
+ /// Parent DataArea to use
+ /// Prefilled machine to use
+ /// Name of the file to be parsed
+ /// Index ID for the DAT
+ /// True to only add item statistics while parsing, false otherwise
+ /// True if there were any items in the array, false otherwise
+ private void ConvertRoms(Models.SoftwareList.Rom[]? roms, Part part, DataArea dataarea, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the rom array is missing, we can't do anything
+ if (roms == null || !roms.Any())
+ return;
+
+ containsItems = true;
+ foreach (var rom in roms)
+ {
+ var item = new Rom
+ {
+ Name = rom.Name,
+ Size = Utilities.CleanLong(rom.Size ?? rom.Length),
+ CRC = rom.CRC,
+ SHA1 = rom.SHA1,
+ Offset = rom.Offset,
+ Value = rom.Value,
+ ItemStatus = rom.Status.AsItemStatus(),
+ LoadFlag = rom.LoadFlag.AsLoadFlag(),
+
+ Part = part,
+ DataArea = dataarea,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert DiskArea information
+ ///
+ /// Array of deserialized models to convert
+ /// Parent Part to use
+ /// Prefilled machine to use
+ /// Name of the file to be parsed
+ /// Index ID for the DAT
+ /// True to only add item statistics while parsing, false otherwise
+ /// True if there were any items in the array, false otherwise
+ private void ConvertDiskArea(Models.SoftwareList.DiskArea[]? diskareas, Part part, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the diskarea array is missing, we can't do anything
+ if (diskareas == null || !diskareas.Any())
+ return;
+
+ foreach (var diskarea in diskareas)
+ {
+ var item = new DiskArea
+ {
+ Name = diskarea.Name,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ConvertDisks(diskarea.Disk, part, item, machine, filename, indexId, statsOnly, ref containsItems);
+ }
+ }
+
+ ///
+ /// Convert Disk information
+ ///
+ /// Array of deserialized models to convert
+ /// Parent Part to use
+ /// Parent DiskArea to use
+ /// Prefilled machine to use
+ /// Name of the file to be parsed
+ /// Index ID for the DAT
+ /// True to only add item statistics while parsing, false otherwise
+ /// True if there were any items in the array, false otherwise
+ private void ConvertDisks(Models.SoftwareList.Disk[]? disks, Part part, DiskArea diskarea, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the rom array is missing, we can't do anything
+ if (disks == null || !disks.Any())
+ return;
+
+ containsItems = true;
+ foreach (var rom in disks)
+ {
+ var item = new Disk
+ {
+ Name = rom.Name,
+ MD5 = rom.MD5,
+ SHA1 = rom.SHA1,
+ ItemStatus = rom.Status.AsItemStatus(),
+ Writable = rom.Writeable.AsYesNo(),
+
+ Part = part,
+ DiskArea = diskarea,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert DipSwitch information
+ ///
+ /// Array of deserialized models to convert
+ /// Parent Part to use
+ /// Prefilled machine to use
+ /// Name of the file to be parsed
+ /// Index ID for the DAT
+ /// True to only add item statistics while parsing, false otherwise
+ /// True if there were any items in the array, false otherwise
+ private void ConvertDipSwitch(Models.SoftwareList.DipSwitch[]? dipswitches, Part part, Machine machine, string filename, int indexId, bool statsOnly, ref bool containsItems)
+ {
+ // If the dipswitch array is missing, we can't do anything
+ if (dipswitches == null || !dipswitches.Any())
+ return;
+
+ foreach (var dipswitch in dipswitches)
+ {
+ var item = new DipSwitch
+ {
+ Name = dipswitch.Name,
+ Tag = dipswitch.Tag,
+ Mask = dipswitch.Mask,
+ Values = CreateSettings(dipswitch.DipValue, machine, filename, indexId),
+
+ Part = part,
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ ParseAddHelper(item, statsOnly);
+ }
+ }
+
+ ///
+ /// Convert DipValue information
+ ///
+ /// Array of deserialized models to convert
+ /// Prefilled machine to use
+ /// Name of the file to be parsed
+ /// Index ID for the DAT
+ private static List? CreateSettings(Models.SoftwareList.DipValue[]? dipvalues, Machine machine, string filename, int indexId)
+ {
+ // If the feature array is missing, we can't do anything
+ if (dipvalues == null || !dipvalues.Any())
+ return null;
+
+ var settings = new List();
+ foreach (var dipvalue in dipvalues)
+ {
+ var item = new Setting
+ {
+ Name = dipvalue.Name,
+ Value = dipvalue.Value,
+ Default = dipvalue.Default.AsYesNo(),
+
+ Source = new Source
+ {
+ Index = indexId,
+ Name = filename,
+ },
+ };
+
+ item.CopyMachineInformation(machine);
+ settings.Add(item);
+ }
+
+ return settings;
+ }
+
+ #endregion
}
}
diff --git a/SabreTools.DatFiles/Formats/SoftwareList.Writer.cs b/SabreTools.DatFiles/Formats/SoftwareList.Writer.cs
index 44500bed..212c185d 100644
--- a/SabreTools.DatFiles/Formats/SoftwareList.Writer.cs
+++ b/SabreTools.DatFiles/Formats/SoftwareList.Writer.cs
@@ -66,6 +66,7 @@ namespace SabreTools.DatFiles.Formats
}
break;
+
case ItemType.Disk:
Disk disk = datItem as Disk;
if (!disk.PartSpecified)
@@ -92,11 +93,13 @@ namespace SabreTools.DatFiles.Formats
if (string.IsNullOrWhiteSpace(disk.Name))
missingFields.Add(DatItemField.Name);
break;
+
case ItemType.Info:
Info info = datItem as Info;
if (string.IsNullOrWhiteSpace(info.Name))
missingFields.Add(DatItemField.Name);
break;
+
case ItemType.Rom:
Rom rom = datItem as Rom;
if (!rom.PartSpecified)
@@ -124,6 +127,7 @@ namespace SabreTools.DatFiles.Formats
missingFields.Add(DatItemField.AreaSize);
}
break;
+
case ItemType.SharedFeature:
SharedFeature sharedFeature = datItem as SharedFeature;
if (string.IsNullOrWhiteSpace(sharedFeature.Name))
diff --git a/SabreTools.Models/SoftwareList/Disk.cs b/SabreTools.Models/SoftwareList/Disk.cs
index 072362a7..8090eaae 100644
--- a/SabreTools.Models/SoftwareList/Disk.cs
+++ b/SabreTools.Models/SoftwareList/Disk.cs
@@ -9,6 +9,9 @@ namespace SabreTools.Models.SoftwareList
[XmlAttribute("name")]
public string Name { get; set; }
+ [XmlAttribute("md5")]
+ public string? MD5 { get; set; }
+
[XmlAttribute("sha1")]
public string? SHA1 { get; set; }
diff --git a/SabreTools.Models/SoftwareList/Rom.cs b/SabreTools.Models/SoftwareList/Rom.cs
index 57193b5d..0215016e 100644
--- a/SabreTools.Models/SoftwareList/Rom.cs
+++ b/SabreTools.Models/SoftwareList/Rom.cs
@@ -12,6 +12,9 @@ namespace SabreTools.Models.SoftwareList
[XmlAttribute("size")]
public string Size { get; set; }
+ [XmlAttribute("length")]
+ public string Length { get; set; }
+
[XmlAttribute("crc")]
public string? CRC { get; set; }
diff --git a/SabreTools.Serialization/XmlSerializer.Deserializer.cs b/SabreTools.Serialization/XmlSerializer.Deserializer.cs
index d174f454..1b444166 100644
--- a/SabreTools.Serialization/XmlSerializer.Deserializer.cs
+++ b/SabreTools.Serialization/XmlSerializer.Deserializer.cs
@@ -1,5 +1,6 @@
using System.IO;
using System.Xml;
+using System.Xml.Schema;
using System.Xml.Serialization;
namespace SabreTools.Serialization
@@ -37,6 +38,8 @@ namespace SabreTools.Serialization
{
CheckCharacters = false,
DtdProcessing = DtdProcessing.Ignore,
+ ValidationFlags = XmlSchemaValidationFlags.None,
+ ValidationType = ValidationType.None,
};
var streamReader = new StreamReader(stream);
var xmlReader = XmlReader.Create(streamReader, settings);