Add nullable context to SabreTools.DatFiles

This commit is contained in:
Matt Nadareski
2023-08-10 23:22:14 -04:00
parent 7bb0ba245d
commit a18ee46d5d
57 changed files with 846 additions and 1217 deletions

View File

@@ -38,7 +38,7 @@ namespace SabreTools.DatFiles.Formats
/// </summary>
/// <param name="filename">Filename to derive from</param>
/// <returns>Filled machine and new filename on success, null on error</returns>
private static (Machine?, string?) DeriveMachine(string filename)
private static (Machine?, string?) DeriveMachine(string? filename)
{
// If the filename is missing, we can't do anything
if (string.IsNullOrWhiteSpace(filename))
@@ -95,9 +95,8 @@ namespace SabreTools.DatFiles.Formats
if (file == null)
return;
(var machine, string name) = DeriveMachine(file.Name);
if (machine == null)
machine = new Machine { Name = Path.GetFileNameWithoutExtension(file.Name) };
(var machine, string? name) = DeriveMachine(file.Name);
machine ??= new Machine { Name = Path.GetFileNameWithoutExtension(file.Name) };
machine.Publisher = file.Publisher;
machine.Comment = file.Comment;

View File

@@ -22,7 +22,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
List<DatItemField> missingFields = new();
@@ -77,7 +77,7 @@ namespace SabreTools.DatFiles.Formats
/// Create a Files from the current internal information
/// <summary>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise</param>
private Models.ArchiveDotOrg.Files CreateFiles(bool ignoreblanks)
private Models.ArchiveDotOrg.Files? CreateFiles(bool ignoreblanks)
{
// If we don't have items, we can't do anything
if (this.Items == null || !this.Items.Any())

View File

@@ -9,7 +9,7 @@
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public ArchiveDotOrg(DatFile datFile)
public ArchiveDotOrg(DatFile? datFile)
: base(datFile)
{
}

View File

@@ -19,7 +19,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
List<DatItemField> missingFields = new();

View File

@@ -9,7 +9,7 @@
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public AttractMode(DatFile datFile)
public AttractMode(DatFile? datFile)
: base(datFile)
{
}

View File

@@ -12,7 +12,8 @@ namespace SabreTools.DatFiles.Formats
/// </summary>
public class OfflineListInfo
{
public string Name { get; set; }
[Models.Required]
public string? Name { get; set; }
public bool? Visible { get; set; }
public bool? InNamingOption { get; set; }
public bool? Default { get; set; }

View File

@@ -67,7 +67,7 @@ namespace SabreTools.DatFiles.Formats
Header.ForcePacking = cmp.ForcePacking.AsPackingFlag();
// Handle implied SuperDAT
if (cmp.Name.Contains(" - SuperDAT") && keep)
if (cmp.Name?.Contains(" - SuperDAT") == true && keep)
Header.Type ??= "SuperDAT";
}

View File

@@ -35,7 +35,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
var missingFields = new List<DatItemField>();
switch (datItem)

View File

@@ -19,7 +19,7 @@
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
/// <param name="quotes">Enable quotes on read and write, false otherwise</param>
public ClrMamePro(DatFile datFile, bool quotes)
public ClrMamePro(DatFile? datFile, bool quotes)
: base(datFile)
{
Quotes = quotes;

View File

@@ -92,8 +92,8 @@ namespace SabreTools.DatFiles.Formats
return;
// Create the machine for copying information
string machineName = game.Name.Trim('"');
if (machineName.EndsWith(".zip"))
string? machineName = game.Name?.Trim('"');
if (machineName?.EndsWith(".zip") == true)
machineName = System.IO.Path.GetFileNameWithoutExtension(machineName);
var machine = new Machine { Name = machineName };

View File

@@ -22,7 +22,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
List<DatItemField> missingFields = new();

View File

@@ -9,7 +9,7 @@
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public DosCenter(DatFile datFile)
public DosCenter(DatFile? datFile)
: base(datFile)
{
}

View File

@@ -38,7 +38,7 @@ namespace SabreTools.DatFiles.Formats
/// </summary>
/// <param name="filename">Filename to derive from</param>
/// <returns>Filled machine and new filename on success, null on error</returns>
private static (Machine?, string?) DeriveMachine(string filename)
private static (Machine?, string?) DeriveMachine(string? filename)
{
// If the filename is missing, we can't do anything
if (string.IsNullOrWhiteSpace(filename))
@@ -95,9 +95,8 @@ namespace SabreTools.DatFiles.Formats
if (row == null)
return;
(var machine, string name) = DeriveMachine(row.Name);
if (machine == null)
machine = new Machine { Name = Path.GetFileNameWithoutExtension(row.Name) };
(var machine, string? name) = DeriveMachine(row.Name);
machine ??= new Machine { Name = Path.GetFileNameWithoutExtension(row.Name) };
var rom = new Rom()
{

View File

@@ -22,7 +22,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
List<DatItemField> missingFields = new();

View File

@@ -9,7 +9,7 @@
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public EverdriveSMDB(DatFile datFile)
public EverdriveSMDB(DatFile? datFile)
: base(datFile)
{
}

View File

@@ -60,7 +60,7 @@ namespace SabreTools.DatFiles.Formats
/// </summary>
/// <param name="filename">Filename to derive from</param>
/// <returns>Filled machine and new filename on success, null on error</returns>
private static (Machine?, string?) DeriveMachine(string filename)
private static (Machine?, string?) DeriveMachine(string? filename)
{
// If the filename is missing, we can't do anything
if (string.IsNullOrWhiteSpace(filename))
@@ -89,7 +89,7 @@ namespace SabreTools.DatFiles.Formats
/// </summary>
/// <param name="filename">Filename to derive from</param>
/// <returns>ItemType representing the item (Rom by default), ItemType.NULL on error</returns>
private static ItemType DeriveItemType(string filename)
private static ItemType DeriveItemType(string? filename)
{
// If the filename is missing, we can't do anything
if (string.IsNullOrWhiteSpace(filename))
@@ -129,12 +129,16 @@ namespace SabreTools.DatFiles.Formats
// Loop through and add the items
foreach (var sfv in sfvs)
{
// Skip if we have an invalid item
if (sfv == null)
continue;
// Get the item type
ItemType itemType = DeriveItemType(sfv.File);
if (itemType == ItemType.NULL)
continue;
(var machine, string itemName) = DeriveMachine(sfv.File);
(var machine, string? itemName) = DeriveMachine(sfv.File);
switch (itemType)
{
case ItemType.Disk: // Should not happen with CRC32 hashes
@@ -179,12 +183,16 @@ namespace SabreTools.DatFiles.Formats
// Loop through and add the items
foreach (var md5 in md5s)
{
// Skip if we have an invalid item
if (md5 == null)
continue;
// Get the item type
ItemType itemType = DeriveItemType(md5.File);
if (itemType == ItemType.NULL)
continue;
(var machine, string itemName) = DeriveMachine(md5.File);
(var machine, string? itemName) = DeriveMachine(md5.File);
switch (itemType)
{
case ItemType.Disk:
@@ -261,12 +269,16 @@ namespace SabreTools.DatFiles.Formats
// Loop through and add the items
foreach (var sha1 in sha1s)
{
// Skip if we have an invalid item
if (sha1 == null)
continue;
// Get the item type
ItemType itemType = DeriveItemType(sha1.File);
if (itemType == ItemType.NULL)
continue;
(var machine, string itemName) = DeriveMachine(sha1.File);
(var machine, string? itemName) = DeriveMachine(sha1.File);
switch (itemType)
{
case ItemType.Disk:
@@ -343,12 +355,16 @@ namespace SabreTools.DatFiles.Formats
// Loop through and add the items
foreach (var sha256 in sha256s)
{
// Skip if we have an invalid item
if (sha256 == null)
continue;
// Get the item type
ItemType itemType = DeriveItemType(sha256.File);
if (itemType == ItemType.NULL)
continue;
(var machine, string itemName) = DeriveMachine(sha256.File);
(var machine, string? itemName) = DeriveMachine(sha256.File);
switch (itemType)
{
case ItemType.Media:
@@ -409,12 +425,16 @@ namespace SabreTools.DatFiles.Formats
// Loop through and add the items
foreach (var sha384 in sha384s)
{
// Skip if we have an invalid item
if (sha384 == null)
continue;
// Get the item type
ItemType itemType = DeriveItemType(sha384.File);
if (itemType == ItemType.NULL)
continue;
(var machine, string itemName) = DeriveMachine(sha384.File);
(var machine, string? itemName) = DeriveMachine(sha384.File);
switch (itemType)
{
case ItemType.Disk: // Should not happen with SHA-384 hashes
@@ -459,12 +479,16 @@ namespace SabreTools.DatFiles.Formats
// Loop through and add the items
foreach (var sha512 in sha512s)
{
// Skip if we have an invalid item
if (sha512 == null)
continue;
// Get the item type
ItemType itemType = DeriveItemType(sha512.File);
if (itemType == ItemType.NULL)
continue;
(var machine, string itemName) = DeriveMachine(sha512.File);
(var machine, string? itemName) = DeriveMachine(sha512.File);
switch (itemType)
{
case ItemType.Disk: // Should not happen with SHA-512 hashes
@@ -509,12 +533,16 @@ namespace SabreTools.DatFiles.Formats
// Loop through and add the items
foreach (var spamsum in spamsums)
{
// Skip if we have an invalid item
if (spamsum == null)
continue;
// Get the item type
ItemType itemType = DeriveItemType(spamsum.File);
if (itemType == ItemType.NULL)
continue;
(var machine, string itemName) = DeriveMachine(spamsum.File);
(var machine, string? itemName) = DeriveMachine(spamsum.File);
switch (itemType)
{
case ItemType.Media:

View File

@@ -25,7 +25,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
List<DatItemField> missingFields = new();
@@ -232,6 +232,8 @@ namespace SabreTools.DatFiles.Formats
{
// Get the item
var item = items[index];
if (item == null)
continue;
// Check for a "null" item
item = ProcessNullifiedItem(item);
@@ -241,7 +243,7 @@ namespace SabreTools.DatFiles.Formats
continue;
string name = string.Empty;
if (Header.GameName)
if (Header.GameName && item.Machine != null)
name = $"{item.Machine.Name}{Path.DirectorySeparatorChar}";
switch (item)
@@ -281,6 +283,8 @@ namespace SabreTools.DatFiles.Formats
{
// Get the item
var item = items[index];
if (item == null)
continue;
// Check for a "null" item
item = ProcessNullifiedItem(item);
@@ -290,7 +294,7 @@ namespace SabreTools.DatFiles.Formats
continue;
string name = string.Empty;
if (Header.GameName)
if (Header.GameName && item.Machine != null)
name = $"{item.Machine.Name}{Path.DirectorySeparatorChar}";
switch (item)
@@ -346,6 +350,8 @@ namespace SabreTools.DatFiles.Formats
{
// Get the item
var item = items[index];
if (item == null)
continue;
// Check for a "null" item
item = ProcessNullifiedItem(item);
@@ -355,7 +361,7 @@ namespace SabreTools.DatFiles.Formats
continue;
string name = string.Empty;
if (Header.GameName)
if (Header.GameName && item.Machine != null)
name = $"{item.Machine.Name}{Path.DirectorySeparatorChar}";
switch (item)
@@ -411,6 +417,8 @@ namespace SabreTools.DatFiles.Formats
{
// Get the item
var item = items[index];
if (item == null)
continue;
// Check for a "null" item
item = ProcessNullifiedItem(item);
@@ -420,7 +428,7 @@ namespace SabreTools.DatFiles.Formats
continue;
string name = string.Empty;
if (Header.GameName)
if (Header.GameName && item.Machine != null)
name = $"{item.Machine.Name}{Path.DirectorySeparatorChar}";
switch (item)
@@ -468,6 +476,8 @@ namespace SabreTools.DatFiles.Formats
{
// Get the item
var item = items[index];
if (item == null)
continue;
// Check for a "null" item
item = ProcessNullifiedItem(item);
@@ -477,7 +487,7 @@ namespace SabreTools.DatFiles.Formats
continue;
string name = string.Empty;
if (Header.GameName)
if (Header.GameName && item.Machine != null)
name = $"{item.Machine.Name}{Path.DirectorySeparatorChar}";
switch (item)
@@ -517,6 +527,8 @@ namespace SabreTools.DatFiles.Formats
{
// Get the item
var item = items[index];
if (item == null)
continue;
// Check for a "null" item
item = ProcessNullifiedItem(item);
@@ -526,7 +538,7 @@ namespace SabreTools.DatFiles.Formats
continue;
string name = string.Empty;
if (Header.GameName)
if (Header.GameName && item.Machine != null)
name = $"{item.Machine.Name}{Path.DirectorySeparatorChar}";
switch (item)
@@ -566,6 +578,8 @@ namespace SabreTools.DatFiles.Formats
{
// Get the item
var item = items[index];
if (item == null)
continue;
// Check for a "null" item
item = ProcessNullifiedItem(item);
@@ -575,7 +589,7 @@ namespace SabreTools.DatFiles.Formats
continue;
string name = string.Empty;
if (Header.GameName)
if (Header.GameName && item.Machine != null)
name = $"{item.Machine.Name}{Path.DirectorySeparatorChar}";
switch (item)

View File

@@ -15,7 +15,7 @@ namespace SabreTools.DatFiles.Formats
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
/// <param name="hash">Type of hash that is associated with this DAT</param>
public Hashfile(DatFile datFile, Hash hash)
public Hashfile(DatFile? datFile, Hash hash)
: base(datFile)
{
_hash = hash;

View File

@@ -88,12 +88,10 @@ namespace SabreTools.DatFiles.Formats
return;
}
foreach (var row in set.Row)
foreach (var row in set.Row ?? Array.Empty<Models.Listrom.Row>())
{
ConvertRow(row, machine, filename, indexId, statsOnly);
}
}
/// <summary>
@@ -109,8 +107,6 @@ namespace SabreTools.DatFiles.Formats
if (row == null)
return;
DatItem item = null;
// Normal CHD
if (row.Size == null
&& !row.NoGoodDumpKnown
@@ -118,7 +114,7 @@ namespace SabreTools.DatFiles.Formats
&& (!string.IsNullOrWhiteSpace(row.MD5)
|| !string.IsNullOrWhiteSpace(row.SHA1)))
{
item = new Disk
var disk = new Disk
{
Name = row.Name,
ItemStatus = ItemStatus.None,
@@ -131,9 +127,13 @@ namespace SabreTools.DatFiles.Formats
};
if (!string.IsNullOrWhiteSpace(row.MD5))
(item as Disk).MD5 = row.MD5;
disk.MD5 = row.MD5;
else
(item as Disk).SHA1 = row.SHA1;
disk.SHA1 = row.SHA1;
// Now process and add the item
disk.CopyMachineInformation(machine);
ParseAddHelper(disk, statsOnly);
}
// Normal ROM
@@ -141,7 +141,7 @@ namespace SabreTools.DatFiles.Formats
&& !row.NoGoodDumpKnown
&& !row.Bad)
{
item = new Rom
var rom = new Rom
{
Name = row.Name,
Size = Utilities.CleanLong(row.Size),
@@ -155,6 +155,10 @@ namespace SabreTools.DatFiles.Formats
Name = filename,
},
};
// Now process and add the item
rom.CopyMachineInformation(machine);
ParseAddHelper(rom, statsOnly);
}
// Bad CHD
@@ -164,7 +168,7 @@ namespace SabreTools.DatFiles.Formats
&& (!string.IsNullOrWhiteSpace(row.MD5)
|| !string.IsNullOrWhiteSpace(row.SHA1)))
{
item = new Disk
var disk = new Disk
{
Name = row.Name,
ItemStatus = ItemStatus.BadDump,
@@ -177,16 +181,20 @@ namespace SabreTools.DatFiles.Formats
};
if (!string.IsNullOrWhiteSpace(row.MD5))
(item as Disk).MD5 = row.MD5;
disk.MD5 = row.MD5;
else
(item as Disk).SHA1 = row.SHA1;
disk.SHA1 = row.SHA1;
// Now process and add the item
disk.CopyMachineInformation(machine);
ParseAddHelper(disk, statsOnly);
}
// Nodump CHD
else if (row.Size == null
&& row.NoGoodDumpKnown)
{
item = new Disk
var disk = new Disk
{
Name = row.Name,
MD5 = null,
@@ -199,6 +207,10 @@ namespace SabreTools.DatFiles.Formats
Name = filename,
},
};
// Now process and add the item
disk.CopyMachineInformation(machine);
ParseAddHelper(disk, statsOnly);
}
// Bad ROM
@@ -206,7 +218,7 @@ namespace SabreTools.DatFiles.Formats
&& !row.NoGoodDumpKnown
&& row.Bad)
{
item = new Rom
var rom = new Rom
{
Name = row.Name,
Size = Utilities.CleanLong(row.Size),
@@ -220,13 +232,17 @@ namespace SabreTools.DatFiles.Formats
Name = filename,
},
};
// Now process and add the item
rom.CopyMachineInformation(machine);
ParseAddHelper(rom, statsOnly);
}
// Nodump ROM
else if (row.Size != null
&& row.NoGoodDumpKnown)
{
item = new Rom
var rom = new Rom
{
Name = row.Name,
Size = Utilities.CleanLong(row.Size),
@@ -240,11 +256,11 @@ namespace SabreTools.DatFiles.Formats
Name = filename,
},
};
}
// Now process and add the item
item.CopyMachineInformation(machine);
ParseAddHelper(item, statsOnly);
// Now process and add the item
rom.CopyMachineInformation(machine);
ParseAddHelper(rom, statsOnly);
}
}
#endregion

View File

@@ -23,7 +23,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
List<DatItemField> missingFields = new();
@@ -136,10 +136,14 @@ namespace SabreTools.DatFiles.Formats
switch (item)
{
case Disk disk:
rows.Add(CreateRow(disk));
var diskRow = CreateRow(disk);
if (diskRow != null)
rows.Add(diskRow);
break;
case Rom rom:
rows.Add(CreateRow(rom));
var romRow = CreateRow(rom);
if (romRow != null)
rows.Add(romRow);
break;
}
}

View File

@@ -9,7 +9,7 @@
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public Listrom(DatFile datFile)
public Listrom(DatFile? datFile)
: base(datFile)
{
}

View File

@@ -55,7 +55,7 @@ namespace SabreTools.DatFiles.Formats
Header.MameConfig ??= mame.MameConfig;
// Handle implied SuperDAT
if (Header.Name.Contains(" - SuperDAT") && keep)
if (Header.Name?.Contains(" - SuperDAT") == true && keep)
Header.Type ??= "SuperDAT";
}

View File

@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using SabreTools.Core;
using SabreTools.Core.Tools;
using SabreTools.DatItems;
using SabreTools.DatItems.Formats;
using SabreTools.IO;
namespace SabreTools.DatFiles.Formats
{
@@ -45,7 +42,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
var missingFields = new List<DatItemField>();
switch (datItem)
@@ -205,476 +202,6 @@ namespace SabreTools.DatFiles.Formats
return true;
}
/// <summary>
/// Write out DAT header using the supplied StreamWriter
/// </summary>
/// <param name="xtw">XmlTextWriter to output to</param>
private void WriteHeader(XmlTextWriter xtw)
{
xtw.WriteStartDocument();
xtw.WriteStartElement("mame");
xtw.WriteRequiredAttributeString("build", Header.Name);
xtw.WriteOptionalAttributeString("debug", Header.Debug.FromYesNo());
xtw.WriteOptionalAttributeString("mameconfig", Header.MameConfig);
xtw.Flush();
}
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <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 void WriteStartGame(XmlTextWriter xtw, DatItem datItem)
{
// No game should start with a path separator
datItem.Machine.Name = datItem.Machine.Name.TrimStart(Path.DirectorySeparatorChar);
// Build the state
xtw.WriteStartElement("machine");
xtw.WriteRequiredAttributeString("name", datItem.Machine.Name);
xtw.WriteOptionalAttributeString("sourcefile", datItem.Machine.SourceFile);
if (datItem.Machine.MachineType.HasFlag(MachineType.Bios))
xtw.WriteAttributeString("isbios", "yes");
if (datItem.Machine.MachineType.HasFlag(MachineType.Device))
xtw.WriteAttributeString("isdevice", "yes");
if (datItem.Machine.MachineType.HasFlag(MachineType.Mechanical))
xtw.WriteAttributeString("ismechanical", "yes");
xtw.WriteOptionalAttributeString("runnable", datItem.Machine.Runnable.FromRunnable());
if (!string.Equals(datItem.Machine.Name, datItem.Machine.CloneOf, StringComparison.OrdinalIgnoreCase))
xtw.WriteOptionalAttributeString("cloneof", datItem.Machine.CloneOf);
if (!string.Equals(datItem.Machine.Name, datItem.Machine.RomOf, StringComparison.OrdinalIgnoreCase))
xtw.WriteOptionalAttributeString("romof", datItem.Machine.RomOf);
if (!string.Equals(datItem.Machine.Name, datItem.Machine.SampleOf, StringComparison.OrdinalIgnoreCase))
xtw.WriteOptionalAttributeString("sampleof", datItem.Machine.SampleOf);
xtw.WriteOptionalElementString("description", datItem.Machine.Description);
xtw.WriteOptionalElementString("year", datItem.Machine.Year);
xtw.WriteOptionalElementString("manufacturer", datItem.Machine.Manufacturer);
xtw.WriteOptionalElementString("history", datItem.Machine.History);
xtw.Flush();
}
/// <summary>
/// Write out Game start using the supplied StreamWriter
/// </summary>
/// <param name="xtw">XmlTextWriter to output to</param>
private void WriteEndGame(XmlTextWriter xtw)
{
// End machine
xtw.WriteEndElement();
xtw.Flush();
}
/// <summary>
/// Write out DatItem using the supplied StreamWriter
/// </summary>
/// <param name="xtw">XmlTextWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
private void WriteDatItem(XmlTextWriter xtw, DatItem datItem)
{
// Pre-process the item name
ProcessItemName(datItem, true);
// Build the state
switch (datItem.ItemType)
{
case ItemType.Adjuster:
var adjuster = datItem as Adjuster;
xtw.WriteStartElement("adjuster");
xtw.WriteRequiredAttributeString("name", adjuster.Name);
xtw.WriteRequiredAttributeString("default", adjuster.Default.FromYesNo());
if (adjuster.ConditionsSpecified)
{
foreach (var adjusterCondition in adjuster.Conditions)
{
xtw.WriteStartElement("condition");
xtw.WriteRequiredAttributeString("tag", adjusterCondition.Tag);
xtw.WriteRequiredAttributeString("mask", adjusterCondition.Mask);
xtw.WriteRequiredAttributeString("relation", adjusterCondition.Relation.FromRelation());
xtw.WriteRequiredAttributeString("value", adjusterCondition.Value);
xtw.WriteEndElement();
}
}
xtw.WriteEndElement();
break;
case ItemType.BiosSet:
var biosSet = datItem as BiosSet;
xtw.WriteStartElement("biosset");
xtw.WriteRequiredAttributeString("name", biosSet.Name);
xtw.WriteRequiredAttributeString("description", biosSet.Description);
xtw.WriteOptionalAttributeString("default", biosSet.Default?.ToString().ToLowerInvariant());
xtw.WriteEndElement();
break;
case ItemType.Chip:
var chip = datItem as Chip;
xtw.WriteStartElement("chip");
xtw.WriteRequiredAttributeString("name", chip.Name);
xtw.WriteOptionalAttributeString("tag", chip.Tag);
xtw.WriteRequiredAttributeString("type", chip.ChipType.FromChipType());
xtw.WriteOptionalAttributeString("clock", chip.Clock?.ToString());
xtw.WriteEndElement();
break;
case ItemType.Condition:
var condition = datItem as Condition;
xtw.WriteStartElement("condition");
xtw.WriteRequiredAttributeString("tag", condition.Tag);
xtw.WriteRequiredAttributeString("mask", condition.Mask);
xtw.WriteRequiredAttributeString("relation", condition.Relation.FromRelation());
xtw.WriteRequiredAttributeString("value", condition.Value);
xtw.WriteEndElement();
break;
case ItemType.Configuration:
var configuration = datItem as Configuration;
xtw.WriteStartElement("configuration");
xtw.WriteRequiredAttributeString("name", configuration.Name);
xtw.WriteRequiredAttributeString("tag", configuration.Tag);
xtw.WriteRequiredAttributeString("mask", configuration.Mask);
if (configuration.ConditionsSpecified)
{
foreach (var configurationCondition in configuration.Conditions)
{
xtw.WriteStartElement("condition");
xtw.WriteRequiredAttributeString("tag", configurationCondition.Tag);
xtw.WriteRequiredAttributeString("mask", configurationCondition.Mask);
xtw.WriteRequiredAttributeString("relation", configurationCondition.Relation.FromRelation());
xtw.WriteRequiredAttributeString("value", configurationCondition.Value);
xtw.WriteEndElement();
}
}
if (configuration.LocationsSpecified)
{
foreach (var location in configuration.Locations)
{
xtw.WriteStartElement("conflocation");
xtw.WriteRequiredAttributeString("name", location.Name);
xtw.WriteRequiredAttributeString("number", location.Number?.ToString());
xtw.WriteOptionalAttributeString("inverted", location.Inverted.FromYesNo());
xtw.WriteEndElement();
}
}
if (configuration.SettingsSpecified)
{
foreach (var setting in configuration.Settings)
{
xtw.WriteStartElement("confsetting");
xtw.WriteRequiredAttributeString("name", setting.Name);
xtw.WriteRequiredAttributeString("value", setting.Value);
xtw.WriteOptionalAttributeString("default", setting.Default.FromYesNo());
if (setting.ConditionsSpecified)
{
foreach (var confsettingCondition in setting.Conditions)
{
xtw.WriteStartElement("condition");
xtw.WriteRequiredAttributeString("tag", confsettingCondition.Tag);
xtw.WriteRequiredAttributeString("mask", confsettingCondition.Mask);
xtw.WriteRequiredAttributeString("relation", confsettingCondition.Relation.FromRelation());
xtw.WriteRequiredAttributeString("value", confsettingCondition.Value);
xtw.WriteEndElement();
}
}
xtw.WriteEndElement();
}
}
xtw.WriteEndElement();
break;
case ItemType.Device:
var device = datItem as Device;
xtw.WriteStartElement("device");
xtw.WriteRequiredAttributeString("type", device.DeviceType.FromDeviceType());
xtw.WriteOptionalAttributeString("tag", device.Tag);
xtw.WriteOptionalAttributeString("fixed_image", device.FixedImage);
xtw.WriteOptionalAttributeString("mandatory", device.Mandatory?.ToString());
xtw.WriteOptionalAttributeString("interface", device.Interface);
if (device.InstancesSpecified)
{
foreach (var instance in device.Instances)
{
xtw.WriteStartElement("instance");
xtw.WriteRequiredAttributeString("name", instance.Name);
xtw.WriteRequiredAttributeString("briefname", instance.BriefName);
xtw.WriteEndElement();
}
}
if (device.ExtensionsSpecified)
{
foreach (var extension in device.Extensions)
{
xtw.WriteStartElement("extension");
xtw.WriteRequiredAttributeString("name", extension.Name);
xtw.WriteEndElement();
}
}
xtw.WriteEndElement();
break;
case ItemType.DeviceReference:
var deviceRef = datItem as DeviceReference;
xtw.WriteStartElement("device_ref");
xtw.WriteRequiredAttributeString("name", deviceRef.Name);
xtw.WriteEndElement();
break;
case ItemType.DipSwitch:
var dipSwitch = datItem as DipSwitch;
xtw.WriteStartElement("dipswitch");
xtw.WriteRequiredAttributeString("name", dipSwitch.Name);
xtw.WriteRequiredAttributeString("tag", dipSwitch.Tag);
xtw.WriteRequiredAttributeString("mask", dipSwitch.Mask);
if (dipSwitch.ConditionsSpecified)
{
foreach (var dipSwitchCondition in dipSwitch.Conditions)
{
xtw.WriteStartElement("condition");
xtw.WriteRequiredAttributeString("tag", dipSwitchCondition.Tag);
xtw.WriteRequiredAttributeString("mask", dipSwitchCondition.Mask);
xtw.WriteRequiredAttributeString("relation", dipSwitchCondition.Relation.FromRelation());
xtw.WriteRequiredAttributeString("value", dipSwitchCondition.Value);
xtw.WriteEndElement();
}
}
if (dipSwitch.LocationsSpecified)
{
foreach (var location in dipSwitch.Locations)
{
xtw.WriteStartElement("diplocation");
xtw.WriteRequiredAttributeString("name", location.Name);
xtw.WriteRequiredAttributeString("number", location.Number?.ToString());
xtw.WriteOptionalAttributeString("inverted", location.Inverted.FromYesNo());
xtw.WriteEndElement();
}
}
if (dipSwitch.ValuesSpecified)
{
foreach (var value in dipSwitch.Values)
{
xtw.WriteStartElement("dipvalue");
xtw.WriteRequiredAttributeString("name", value.Name);
xtw.WriteRequiredAttributeString("value", value.Value);
xtw.WriteOptionalAttributeString("default", value.Default.FromYesNo());
if (value.ConditionsSpecified)
{
foreach (var dipValueCondition in value.Conditions)
{
xtw.WriteStartElement("condition");
xtw.WriteRequiredAttributeString("tag", dipValueCondition.Tag);
xtw.WriteRequiredAttributeString("mask", dipValueCondition.Mask);
xtw.WriteRequiredAttributeString("relation", dipValueCondition.Relation.FromRelation());
xtw.WriteRequiredAttributeString("value", dipValueCondition.Value);
xtw.WriteEndElement();
}
}
xtw.WriteEndElement();
}
}
xtw.WriteEndElement();
break;
case ItemType.Disk:
var disk = datItem as Disk;
xtw.WriteStartElement("disk");
xtw.WriteRequiredAttributeString("name", disk.Name);
xtw.WriteOptionalAttributeString("sha1", disk.SHA1?.ToLowerInvariant());
xtw.WriteOptionalAttributeString("merge", disk.MergeTag);
xtw.WriteOptionalAttributeString("region", disk.Region);
xtw.WriteOptionalAttributeString("index", disk.Index);
xtw.WriteOptionalAttributeString("writable", disk.Writable.FromYesNo());
if (disk.ItemStatus != ItemStatus.None)
xtw.WriteOptionalAttributeString("status", disk.ItemStatus.FromItemStatus(false));
xtw.WriteOptionalAttributeString("optional", disk.Optional.FromYesNo());
xtw.WriteEndElement();
break;
case ItemType.Display:
var display = datItem as Display;
xtw.WriteStartElement("display");
xtw.WriteOptionalAttributeString("tag", display.Tag);
xtw.WriteRequiredAttributeString("type", display.DisplayType.FromDisplayType());
xtw.WriteOptionalAttributeString("rotate", display.Rotate?.ToString());
xtw.WriteOptionalAttributeString("flipx", display.FlipX.FromYesNo());
xtw.WriteOptionalAttributeString("width", display.Width?.ToString());
xtw.WriteOptionalAttributeString("height", display.Height?.ToString());
xtw.WriteRequiredAttributeString("refresh", display.Refresh?.ToString("N6"));
xtw.WriteOptionalAttributeString("pixclock", display.PixClock?.ToString());
xtw.WriteOptionalAttributeString("htotal", display.HTotal?.ToString());
xtw.WriteOptionalAttributeString("hbend", display.HBEnd?.ToString());
xtw.WriteOptionalAttributeString("hstart", display.HBStart?.ToString());
xtw.WriteOptionalAttributeString("vtotal", display.VTotal?.ToString());
xtw.WriteOptionalAttributeString("vbend", display.VBEnd?.ToString());
xtw.WriteOptionalAttributeString("vbstart", display.VBStart?.ToString());
xtw.WriteEndElement();
break;
case ItemType.Driver:
var driver = datItem as Driver;
xtw.WriteStartElement("driver");
xtw.WriteRequiredAttributeString("status", driver.Status.FromSupportStatus());
xtw.WriteRequiredAttributeString("emulation", driver.Emulation.FromSupportStatus());
xtw.WriteOptionalAttributeString("cocktail", driver.Cocktail.FromSupportStatus());
xtw.WriteRequiredAttributeString("savestate", driver.SaveState.FromSupported(true));
xtw.WriteOptionalAttributeString("requiresartwork", driver.RequiresArtwork.FromYesNo());
xtw.WriteOptionalAttributeString("unofficial", driver.Unofficial.FromYesNo());
xtw.WriteOptionalAttributeString("nosoundhardware", driver.NoSoundHardware.FromYesNo());
xtw.WriteOptionalAttributeString("incomplete", driver.Incomplete.FromYesNo());
xtw.WriteEndElement();
break;
case ItemType.Feature:
var feature = datItem as Feature;
xtw.WriteStartElement("feature");
xtw.WriteRequiredAttributeString("type", feature.Type.FromFeatureType());
xtw.WriteOptionalAttributeString("status", feature.Status.FromFeatureStatus());
xtw.WriteOptionalAttributeString("overall", feature.Overall.FromFeatureStatus());
xtw.WriteEndElement();
break;
case ItemType.Input:
var input = datItem as Input;
xtw.WriteStartElement("input");
xtw.WriteOptionalAttributeString("service", input.Service.FromYesNo());
xtw.WriteOptionalAttributeString("tilt", input.Tilt.FromYesNo());
xtw.WriteRequiredAttributeString("players", input.Players?.ToString());
xtw.WriteOptionalAttributeString("coins", input.Coins?.ToString());
if (input.ControlsSpecified)
{
foreach (var control in input.Controls)
{
xtw.WriteStartElement("control");
xtw.WriteRequiredAttributeString("type", control.ControlType.FromControlType());
xtw.WriteOptionalAttributeString("player", control.Player?.ToString());
xtw.WriteOptionalAttributeString("buttons", control.Buttons?.ToString());
xtw.WriteOptionalAttributeString("reqbuttons", control.RequiredButtons?.ToString());
xtw.WriteOptionalAttributeString("minimum", control.Minimum?.ToString());
xtw.WriteOptionalAttributeString("maximum", control.Maximum?.ToString());
xtw.WriteOptionalAttributeString("sensitivity", control.Sensitivity?.ToString());
xtw.WriteOptionalAttributeString("keydelta", control.KeyDelta?.ToString());
xtw.WriteOptionalAttributeString("reverse", control.Reverse.FromYesNo());
xtw.WriteOptionalAttributeString("ways", control.Ways);
xtw.WriteOptionalAttributeString("ways2", control.Ways2);
xtw.WriteOptionalAttributeString("ways3", control.Ways3);
xtw.WriteEndElement();
}
}
xtw.WriteEndElement();
break;
case ItemType.Port:
var port = datItem as Port;
xtw.WriteStartElement("port");
xtw.WriteRequiredAttributeString("tag", port.Tag);
if (port.AnalogsSpecified)
{
foreach (var analog in port.Analogs)
{
xtw.WriteStartElement("analog");
xtw.WriteRequiredAttributeString("mask", analog.Mask);
xtw.WriteEndElement();
}
}
xtw.WriteEndElement();
break;
case ItemType.RamOption:
var ramOption = datItem as RamOption;
xtw.WriteStartElement("ramoption");
xtw.WriteRequiredAttributeString("name", ramOption.Name);
xtw.WriteOptionalAttributeString("default", ramOption.Default.FromYesNo());
xtw.WriteRaw(ramOption.Content ?? string.Empty);
xtw.WriteFullEndElement();
break;
case ItemType.Rom:
var rom = datItem as Rom;
xtw.WriteStartElement("rom");
xtw.WriteRequiredAttributeString("name", rom.Name);
xtw.WriteOptionalAttributeString("bios", rom.Bios);
xtw.WriteRequiredAttributeString("size", rom.Size?.ToString());
xtw.WriteOptionalAttributeString("crc", rom.CRC?.ToLowerInvariant());
xtw.WriteOptionalAttributeString("sha1", rom.SHA1?.ToLowerInvariant());
xtw.WriteOptionalAttributeString("merge", rom.MergeTag);
xtw.WriteOptionalAttributeString("region", rom.Region);
xtw.WriteOptionalAttributeString("offset", rom.Offset);
if (rom.ItemStatus != ItemStatus.None)
xtw.WriteOptionalAttributeString("status", rom.ItemStatus.FromItemStatus(false));
xtw.WriteOptionalAttributeString("optional", rom.Optional.FromYesNo());
xtw.WriteEndElement();
break;
case ItemType.Sample:
var sample = datItem as Sample;
xtw.WriteStartElement("sample");
xtw.WriteRequiredAttributeString("name", sample.Name);
xtw.WriteEndElement();
break;
case ItemType.Slot:
var slot = datItem as Slot;
xtw.WriteStartElement("slot");
xtw.WriteRequiredAttributeString("name", slot.Name);
if (slot.SlotOptionsSpecified)
{
foreach (var slotOption in slot.SlotOptions)
{
xtw.WriteStartElement("slotoption");
xtw.WriteRequiredAttributeString("name", slotOption.Name);
xtw.WriteRequiredAttributeString("devname", slotOption.DeviceName);
xtw.WriteOptionalAttributeString("default", slotOption.Default.FromYesNo());
xtw.WriteEndElement();
}
}
xtw.WriteEndElement();
break;
case ItemType.SoftwareList:
var softwareList = datItem as DatItems.Formats.SoftwareList;
xtw.WriteStartElement("softwarelist");
xtw.WriteRequiredAttributeString("tag", softwareList.Tag);
xtw.WriteRequiredAttributeString("name", softwareList.Name);
if (softwareList.Status != SoftwareListStatus.None)
xtw.WriteRequiredAttributeString("status", softwareList.Status.FromSoftwareListStatus());
xtw.WriteOptionalAttributeString("filter", softwareList.Filter);
xtw.WriteEndElement();
break;
case ItemType.Sound:
var sound = datItem as Sound;
xtw.WriteStartElement("sound");
xtw.WriteRequiredAttributeString("channels", sound.Channels?.ToString());
xtw.WriteEndElement();
break;
}
xtw.Flush();
}
/// <summary>
/// Write out DAT footer using the supplied StreamWriter
/// </summary>
/// <param name="xtw">XmlTextWriter to output to</param>
private void WriteFooter(XmlTextWriter xtw)
{
// End machine
xtw.WriteEndElement();
// End mame
xtw.WriteEndElement();
xtw.Flush();
}
#region Converters
/// <summary>
@@ -841,7 +368,7 @@ namespace SabreTools.DatFiles.Formats
/// <summary>
/// Create a GameBase from the current internal information
/// <summary>
private Models.Listxml.GameBase? CreateGame(Machine machine)
private Models.Listxml.GameBase CreateGame(Machine machine)
{
var game = new Models.Listxml.Machine
{

View File

@@ -175,7 +175,7 @@
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public Listxml(DatFile datFile)
public Listxml(DatFile? datFile)
: base(datFile)
{
}

View File

@@ -85,7 +85,7 @@ namespace SabreTools.DatFiles.Formats
ConvertSubheader(header.RomCenter);
// Handle implied SuperDAT
if (header.Name.Contains(" - SuperDAT") && keep)
if (header.Name?.Contains(" - SuperDAT") == true && keep)
Header.Type ??= "SuperDAT";
}
@@ -200,7 +200,7 @@ namespace SabreTools.DatFiles.Formats
/// <param name="filename">Name of the file to be parsed</param>
/// <param name="indexId">Index ID for the DAT</param>
/// <param name="statsOnly">True to only add item statistics while parsing, false otherwise</param>
private void ConvertGame(Models.Logiqx.GameBase game, string filename, int indexId, bool statsOnly, string dirname = null)
private void ConvertGame(Models.Logiqx.GameBase game, string filename, int indexId, bool statsOnly, string? dirname = null)
{
// If the game is missing, we can't do anything
if (game == null)

View File

@@ -29,7 +29,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
var missingFields = new List<DatItemField>();
switch (datItem)
@@ -385,7 +385,7 @@ namespace SabreTools.DatFiles.Formats
/// <summary>
/// Create a GameBase from the current internal information
/// <summary>
private Models.Logiqx.GameBase? CreateGame(Machine machine)
private Models.Logiqx.GameBase CreateGame(Machine machine)
{
Models.Logiqx.GameBase game = _deprecated ? new Models.Logiqx.Game() : new Models.Logiqx.Machine();

View File

@@ -219,7 +219,7 @@
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
/// <param name="deprecated">True if the output uses "game", false if the output uses "machine"</param>
public Logiqx(DatFile datFile, bool deprecated)
public Logiqx(DatFile? datFile, bool deprecated)
: base(datFile)
{
_deprecated = deprecated;

View File

@@ -13,7 +13,7 @@ namespace SabreTools.DatFiles.Formats
internal partial class Missfile : DatFile
{
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
// TODO: Check required fields
return null;
@@ -37,7 +37,7 @@ namespace SabreTools.DatFiles.Formats
StreamWriter sw = new(fs, new UTF8Encoding(false));
// Write out each of the machines and roms
string lastgame = null;
string? lastgame = null;
// Use a sorted list of games to output
foreach (string key in Items.SortedKeys)
@@ -86,7 +86,7 @@ namespace SabreTools.DatFiles.Formats
/// <param name="sw">StreamWriter to output to</param>
/// <param name="datItem">DatItem object to be output</param>
/// <param name="lastgame">The name of the last game to be output</param>
private void WriteDatItem(StreamWriter sw, DatItem datItem, string lastgame)
private void WriteDatItem(StreamWriter sw, DatItem datItem, string? lastgame)
{
// Process the item name
ProcessItemName(datItem, false, forceRomName: false);

View File

@@ -9,7 +9,7 @@
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public Missfile(DatFile datFile)
public Missfile(DatFile? datFile)
: base(datFile)
{
}

View File

@@ -25,7 +25,7 @@ namespace SabreTools.DatFiles.Formats
ConvertHeader(dat);
// Convert the configuration to the internal format
ConvertConfiguration(dat.Configuration, keep);
ConvertConfiguration(dat?.Configuration, keep);
// Convert the games to the internal format
ConvertGames(dat?.Games, filename, indexId, statsOnly);
@@ -78,7 +78,7 @@ namespace SabreTools.DatFiles.Formats
Header.RomTitle = config.RomTitle;
// Handle implied SuperDAT
if (config.DatName.Contains(" - SuperDAT") && keep)
if (config.DatName?.Contains(" - SuperDAT") == true && keep)
Header.Type ??= "SuperDAT";
}
@@ -235,7 +235,7 @@ namespace SabreTools.DatFiles.Formats
private void ConvertCanOpen(Models.OfflineList.CanOpen? canOpen)
{
// If the canOpen is missing, we can't do anything
if (canOpen == null)
if (canOpen?.Extension == null)
return;
Header.CanOpen = new List<string>(canOpen.Extension);
@@ -354,7 +354,7 @@ namespace SabreTools.DatFiles.Formats
/// <param name="indexId">Index ID for the DAT</param>
/// <param name="statsOnly">True to only add item statistics while parsing, false otherwise</param>
/// <param name="containsItems">True if there were any items in the array, false otherwise</param>
private void ConvertFiles(Models.OfflineList.Files? files, Machine machine, long? size, string releaseNumber, string filename, int indexId, bool statsOnly, ref bool containsItems)
private void ConvertFiles(Models.OfflineList.Files? files, Machine machine, long? size, string? releaseNumber, string filename, int indexId, bool statsOnly, ref bool containsItems)
{
// If the files array is missing, we can't do anything
if (files?.RomCRC == null || !files.RomCRC.Any())
@@ -371,6 +371,7 @@ namespace SabreTools.DatFiles.Formats
var item = new Rom
{
Name = name,
Size = size,
CRC = crc.Content,
ItemStatus = ItemStatus.None,

View File

@@ -22,7 +22,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
var missingFields = new List<DatItemField>();
@@ -120,7 +120,7 @@ namespace SabreTools.DatFiles.Formats
private Models.OfflineList.Infos? CreateInfos()
{
// If we don't have infos, we can't do anything
if (!Header.InfosSpecified)
if (!Header.InfosSpecified || Header.Infos == null)
return null;
var infos = new Models.OfflineList.Infos();
@@ -256,7 +256,7 @@ namespace SabreTools.DatFiles.Formats
private Models.OfflineList.CanOpen? CreateCanOpen()
{
// If we don't have a canopen, we can't do anything
if (!Header.CanOpenSpecified)
if (!Header.CanOpenSpecified || Header.CanOpen == null)
return null;
var canOpen = new Models.OfflineList.CanOpen
@@ -360,12 +360,9 @@ namespace SabreTools.DatFiles.Formats
/// <summary>
/// Create a Machine from the current internal information
/// <summary>
private Models.OfflineList.Game? CreateGame(Machine machine)
private Models.OfflineList.Game CreateGame(Machine machine)
{
// If we don't have a machine, we can't do anything
if (machine == null)
return null;
var game = new Models.OfflineList.Game
{
//ImageNumber = machine.ImageNumber, // TODO: Add to internal model

View File

@@ -9,7 +9,7 @@
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public OfflineList(DatFile datFile)
public OfflineList(DatFile? datFile)
: base(datFile)
{
}

View File

@@ -77,7 +77,7 @@ namespace SabreTools.DatFiles.Formats
/// <param name="filename">Name of the file to be parsed</param>
/// <param name="indexId">Index ID for the DAT</param>
/// <param name="statsOnly">True to only add item statistics while parsing, false otherwise</param>
private void ConvertSoftware(Models.OpenMSX.Software software, string filename, int indexId, bool statsOnly, string dirname = null)
private void ConvertSoftware(Models.OpenMSX.Software software, string filename, int indexId, bool statsOnly)
{
// If the software is missing, we can't do anything
if (software == null)

View File

@@ -22,7 +22,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
var missingFields = new List<DatItemField>();
@@ -149,9 +149,8 @@ namespace SabreTools.DatFiles.Formats
/// <summary>
private static Models.OpenMSX.Dump CreateDump(Rom item)
{
Models.OpenMSX.Original original = null;
if (item.OriginalSpecified)
Models.OpenMSX.Original? original = null;
if (item.OriginalSpecified && item.Original != null)
{
original = new Models.OpenMSX.Original { Content = item.Original.Content };
if (item.Original.Value != null)

View File

@@ -40,7 +40,7 @@ The softwaredb.xml file contains information about rom mapper types
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public OpenMSX(DatFile datFile)
public OpenMSX(DatFile? datFile)
: base(datFile)
{
}

View File

@@ -22,7 +22,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
List<DatItemField> missingFields = new();
@@ -135,7 +135,7 @@ namespace SabreTools.DatFiles.Formats
/// Create a Games from the current internal information
/// <summary>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise</param>
private Models.RomCenter.Games CreateGames(bool ignoreblanks)
private Models.RomCenter.Games? CreateGames(bool ignoreblanks)
{
// If we don't have items, we can't do anything
if (this.Items == null || !this.Items.Any())

View File

@@ -9,7 +9,7 @@
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public RomCenter(DatFile datFile)
public RomCenter(DatFile? datFile)
: base(datFile)
{
}

View File

@@ -22,7 +22,7 @@ namespace SabreTools.DatFiles.Formats
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public SabreJSON(DatFile datFile)
public SabreJSON(DatFile? datFile)
: base(datFile)
{
}
@@ -92,7 +92,7 @@ namespace SabreTools.DatFiles.Formats
// Read in the header and apply any new fields
jtr.Read();
JsonSerializer js = new();
DatHeader header = js.Deserialize<DatHeader>(jtr);
DatHeader? header = js.Deserialize<DatHeader>(jtr);
Header.ConditionalCopy(header);
}
@@ -112,10 +112,10 @@ namespace SabreTools.DatFiles.Formats
// Read in the machine array
jtr.Read();
JsonSerializer js = new();
JArray machineArray = js.Deserialize<JArray>(jtr);
JArray? machineArray = js.Deserialize<JArray>(jtr);
// Loop through each machine object and process
foreach (JObject machineObj in machineArray)
foreach (JObject machineObj in machineArray ?? new JArray())
{
ReadMachine(machineObj, statsOnly, filename, indexId);
}
@@ -135,11 +135,11 @@ namespace SabreTools.DatFiles.Formats
return;
// Prepare internal variables
Machine machine = null;
Machine? machine = null;
// Read the machine info, if possible
if (machineObj.ContainsKey("machine"))
machine = machineObj["machine"].ToObject<Machine>();
machine = machineObj["machine"]?.ToObject<Machine>();
// Read items, if possible
if (machineObj.ContainsKey("items"))
@@ -155,7 +155,7 @@ namespace SabreTools.DatFiles.Formats
/// <param name="indexId">Index ID for the DAT</param>
/// <param name="machine">Machine information to add to the parsed items</param>
private void ReadItems(
JArray itemsArr,
JArray? itemsArr,
bool statsOnly,
// Standard Dat parsing
@@ -163,7 +163,7 @@ namespace SabreTools.DatFiles.Formats
int indexId,
// Miscellaneous
Machine machine)
Machine? machine)
{
// If the array is invalid, skip
if (itemsArr == null)
@@ -193,19 +193,22 @@ namespace SabreTools.DatFiles.Formats
int indexId,
// Miscellaneous
Machine machine)
Machine? machine)
{
// If we have an empty item, skip it
if (itemObj == null)
return;
// Prepare internal variables
DatItem datItem = null;
DatItem? datItem = null;
// Read the datitem info, if possible
if (itemObj.ContainsKey("datitem"))
{
JToken datItemObj = itemObj["datitem"];
JToken? datItemObj = itemObj["datitem"];
if (datItemObj == null)
return;
switch (datItemObj.Value<string>("type").AsItemType())
{
case ItemType.Adjuster:
@@ -367,7 +370,7 @@ namespace SabreTools.DatFiles.Formats
WriteHeader(jtw);
// Write out each of the machines and roms
string lastgame = null;
string? lastgame = null;
// Use a sorted list of games to output
foreach (string key in Items.SortedKeys)
@@ -523,7 +526,7 @@ namespace SabreTools.DatFiles.Formats
jtw.Flush();
}
// https://github.com/dotnet/runtime/issues/728
private class BaseFirstContractResolver : DefaultContractResolver
{
@@ -535,9 +538,11 @@ namespace SabreTools.DatFiles.Formats
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return base.CreateProperties(type, memberSerialization)
.OrderBy(p => BaseTypesAndSelf(p.DeclaringType).Count()).ToList();
.Where(p => p != null)
.OrderBy(p => BaseTypesAndSelf(p.DeclaringType).Count())
.ToList();
static IEnumerable<Type> BaseTypesAndSelf(Type t)
static IEnumerable<Type?> BaseTypesAndSelf(Type? t)
{
while (t != null)
{

View File

@@ -18,7 +18,7 @@ namespace SabreTools.DatFiles.Formats
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public SabreXML(DatFile datFile)
public SabreXML(DatFile? datFile)
: base(datFile)
{
}
@@ -27,7 +27,7 @@ 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
XmlReader? xtr = XmlReader.Create(filename, new XmlReaderSettings
{
CheckCharacters = false,
DtdProcessing = DtdProcessing.Ignore,
@@ -58,7 +58,7 @@ namespace SabreTools.DatFiles.Formats
{
case "header":
XmlSerializer xs = new(typeof(DatHeader));
DatHeader header = xs.Deserialize(xtr.ReadSubtree()) as DatHeader;
DatHeader? header = xs.Deserialize(xtr.ReadSubtree()) as DatHeader;
Header.ConditionalCopy(header);
xtr.Skip();
break;
@@ -78,12 +78,12 @@ namespace SabreTools.DatFiles.Formats
catch (Exception ex) when (!throwOnError)
{
logger.Warning(ex, $"Exception found while parsing '{filename}'");
// For XML errors, just skip the affected node
xtr?.Read();
}
xtr.Dispose();
xtr?.Dispose();
}
/// <summary>
@@ -100,7 +100,7 @@ namespace SabreTools.DatFiles.Formats
return;
// Prepare internal variables
Machine machine = null;
Machine? machine = null;
// Otherwise, read the directory
xtr.MoveToContent();
@@ -117,7 +117,7 @@ namespace SabreTools.DatFiles.Formats
{
case "machine":
XmlSerializer xs = new(typeof(Machine));
machine = xs.Deserialize(xtr.ReadSubtree()) as Machine;
machine = xs?.Deserialize(xtr.ReadSubtree()) as Machine;
xtr.Skip();
break;
@@ -142,7 +142,7 @@ namespace SabreTools.DatFiles.Formats
/// <param name="statsOnly">True to only add item statistics while parsing, false otherwise</param>
/// <param name="filename">Name of the file to be parsed</param>
/// <param name="indexId">Index ID for the DAT</param>
private void ReadFiles(XmlReader xtr, Machine machine, bool statsOnly, string filename, int indexId)
private void ReadFiles(XmlReader xtr, Machine? machine, bool statsOnly, string filename, int indexId)
{
// If the reader is invalid, skip
if (xtr == null)
@@ -163,10 +163,12 @@ namespace SabreTools.DatFiles.Formats
{
case "datitem":
XmlSerializer xs = new(typeof(DatItem));
DatItem item = xs.Deserialize(xtr.ReadSubtree()) as DatItem;
item.CopyMachineInformation(machine);
item.Source = new Source { Name = filename, Index = indexId };
ParseAddHelper(item, statsOnly);
if (xs.Deserialize(xtr.ReadSubtree()) is DatItem item)
{
item.CopyMachineInformation(machine);
item.Source = new Source { Name = filename, Index = indexId };
ParseAddHelper(item, statsOnly);
}
xtr.Skip();
break;
default:
@@ -202,7 +204,7 @@ namespace SabreTools.DatFiles.Formats
WriteHeader(xtw);
// Write out each of the machines and roms
string lastgame = null;
string? lastgame = null;
// Use a sorted list of games to output
foreach (string key in Items.SortedKeys)

View File

@@ -78,7 +78,7 @@ namespace SabreTools.DatFiles.Formats
};
// Read item values
DatItem item = null;
DatItem? item = null;
switch (row.Type.AsItemType())
{
case ItemType.Disk:
@@ -137,8 +137,11 @@ namespace SabreTools.DatFiles.Formats
}
// Now process and add the item
item.CopyMachineInformation(machine);
ParseAddHelper(item, statsOnly);
if (item != null)
{
item.CopyMachineInformation(machine);
ParseAddHelper(item, statsOnly);
}
}
#endregion

View File

@@ -25,7 +25,7 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
List<DatItemField> missingFields = new();

View File

@@ -13,7 +13,7 @@
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
/// <param name="delim">Delimiter for parsing individual lines</param>
public SeparatedValue(DatFile datFile, char delim)
public SeparatedValue(DatFile? datFile, char delim)
: base(datFile)
{
_delim = delim;

View File

@@ -51,7 +51,7 @@ namespace SabreTools.DatFiles.Formats
Header.Comment ??= softwarelist.Notes;
// Handle implied SuperDAT
if (Header.Name.Contains(" - SuperDAT") && keep)
if (Header.Name?.Contains(" - SuperDAT") == true && keep)
Header.Type ??= "SuperDAT";
}

View File

@@ -27,14 +27,13 @@ namespace SabreTools.DatFiles.Formats
}
/// <inheritdoc/>
protected override List<DatItemField> GetMissingRequiredFields(DatItem datItem)
protected override List<DatItemField>? GetMissingRequiredFields(DatItem datItem)
{
List<DatItemField> missingFields = new();
var missingFields = new List<DatItemField>();
switch (datItem.ItemType)
switch (datItem)
{
case ItemType.DipSwitch:
DipSwitch dipSwitch = datItem as DipSwitch;
case DipSwitch dipSwitch:
if (!dipSwitch.PartSpecified)
{
missingFields.Add(DatItemField.Part_Name);
@@ -63,8 +62,7 @@ namespace SabreTools.DatFiles.Formats
break;
case ItemType.Disk:
Disk disk = datItem as Disk;
case Disk disk:
if (!disk.PartSpecified)
{
missingFields.Add(DatItemField.Part_Name);
@@ -90,14 +88,12 @@ namespace SabreTools.DatFiles.Formats
missingFields.Add(DatItemField.Name);
break;
case ItemType.Info:
Info info = datItem as Info;
case Info info:
if (string.IsNullOrWhiteSpace(info.Name))
missingFields.Add(DatItemField.Name);
break;
case ItemType.Rom:
Rom rom = datItem as Rom;
case Rom rom:
if (!rom.PartSpecified)
{
missingFields.Add(DatItemField.Part_Name);
@@ -124,9 +120,8 @@ namespace SabreTools.DatFiles.Formats
}
break;
case ItemType.SharedFeature:
SharedFeature sharedFeature = datItem as SharedFeature;
if (string.IsNullOrWhiteSpace(sharedFeature.Name))
case SharedFeature sharedFeat:
if (string.IsNullOrWhiteSpace(sharedFeat.Name))
missingFields.Add(DatItemField.Name);
break;
default:
@@ -260,7 +255,7 @@ namespace SabreTools.DatFiles.Formats
/// <summary>
/// Create a Software from the current internal information
/// <summary>
private Models.SoftwareList.Software? CreateSoftware(Machine machine)
private Models.SoftwareList.Software CreateSoftware(Machine machine)
{
var software = new Models.SoftwareList.Software
{
@@ -467,7 +462,7 @@ namespace SabreTools.DatFiles.Formats
private static List<Models.SoftwareList.Part> SantitizeParts(List<Models.SoftwareList.Part> parts)
{
// If we have no parts, we can't do anything
if (parts == null || !parts.Any())
if (!parts.Any())
return parts;
var grouped = parts.GroupBy(p => p.Name);
@@ -521,7 +516,7 @@ namespace SabreTools.DatFiles.Formats
private static List<Models.SoftwareList.DataArea> SantitizeDataAreas(List<Models.SoftwareList.DataArea> dataAreas)
{
// If we have no DataAreas, we can't do anything
if (dataAreas == null || !dataAreas.Any())
if (!dataAreas.Any())
return dataAreas;
var grouped = dataAreas.GroupBy(p => p.Name);
@@ -558,7 +553,7 @@ namespace SabreTools.DatFiles.Formats
private static List<Models.SoftwareList.DiskArea> SantitizeDiskAreas(List<Models.SoftwareList.DiskArea> diskAreas)
{
// If we have no DiskAreas, we can't do anything
if (diskAreas == null || !diskAreas.Any())
if (!diskAreas.Any())
return diskAreas;
var grouped = diskAreas.GroupBy(p => p.Name);

View File

@@ -74,7 +74,7 @@ namespace SabreTools.DatFiles.Formats
/// Constructor designed for casting a base DatFile
/// </summary>
/// <param name="datFile">Parent DatFile to copy from</param>
public SoftwareList(DatFile datFile)
public SoftwareList(DatFile? datFile)
: base(datFile)
{
}