diff --git a/SabreTools.Library/DatFiles/Json.cs b/SabreTools.Library/DatFiles/Json.cs index 55b8a0ea..4a7606c3 100644 --- a/SabreTools.Library/DatFiles/Json.cs +++ b/SabreTools.Library/DatFiles/Json.cs @@ -539,7 +539,7 @@ namespace SabreTools.Library.DatFiles machine.SourceFile = jtr.ReadAsString(); break; case "runnable": - machine.Runnable = jtr.ReadAsString().AsYesNo(); + machine.Runnable = jtr.ReadAsString().AsRunnable(); break; case "devices": machine.Devices = new List(); @@ -568,12 +568,14 @@ namespace SabreTools.Library.DatFiles if (jtr.TokenType == JsonToken.EndArray) break; + var info = new ListXmlInfo(); + jtr.Read(); // Key - string key = jtr.Value as string; - string value = jtr.ReadAsString(); + info.Name = jtr.Value as string; + info.Value = jtr.ReadAsString(); jtr.Read(); // End object - machine.Infos.Add(new ListXmlInfo(key, value)); + machine.Infos.Add(info); } break; @@ -663,7 +665,7 @@ namespace SabreTools.Library.DatFiles break; case "dipswitches": - machine.DipSwitches = new List(); + machine.DipSwitches = new List(); jtr.Read(); // Start Array while (!sr.EndOfStream) { @@ -678,7 +680,7 @@ namespace SabreTools.Library.DatFiles jtr.Read(); // Mask Key string mask = jtr.ReadAsString(); - var dipSwitch = new ListXMLDipSwitch(); + var dipSwitch = new ListXmlDipSwitch(); dipSwitch.Name = name; dipSwitch.Tag = tag; dipSwitch.Mask = mask; @@ -698,7 +700,7 @@ namespace SabreTools.Library.DatFiles bool? def = jtr.ReadAsString().AsYesNo(); jtr.Read(); // End object - var dipValue = new ListXMLDipValue(); + var dipValue = new ListXmlDipValue(); dipValue.Name = valname; dipValue.Value = value; dipValue.Default = def; @@ -1706,15 +1708,20 @@ namespace SabreTools.Library.DatFiles } if (!Header.ExcludeFields.Contains(Field.Runnable) && datItem.Machine.Runnable != null) { - if (datItem.Machine.Runnable == true) + switch (datItem.Machine.Runnable) { - jtw.WritePropertyName("runnable"); - jtw.WriteValue("yes"); - } - else if (datItem.Machine.Runnable == false) - { - jtw.WritePropertyName("runnable"); - jtw.WriteValue("no"); + case Runnable.No: + jtw.WritePropertyName("runnable"); + jtw.WriteValue("no"); + break; + case Runnable.Partial: + jtw.WritePropertyName("runnable"); + jtw.WriteValue("partial"); + break; + case Runnable.Yes: + jtw.WritePropertyName("runnable"); + jtw.WriteValue("yes"); + break; } } if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Devices, Header.ExcludeFields))) @@ -1898,7 +1905,7 @@ namespace SabreTools.Library.DatFiles jtw.WriteValue(dip.Mask); jtw.WriteStartArray(); - foreach (ListXMLDipValue dipval in dip.Values) + foreach (ListXmlDipValue dipval in dip.Values) { jtw.WriteStartObject(); jtw.WritePropertyName("name"); diff --git a/SabreTools.Library/DatFiles/Listxml.cs b/SabreTools.Library/DatFiles/Listxml.cs index 6f08948c..3606adb7 100644 --- a/SabreTools.Library/DatFiles/Listxml.cs +++ b/SabreTools.Library/DatFiles/Listxml.cs @@ -145,7 +145,7 @@ namespace SabreTools.Library.DatFiles Name = reader.GetAttribute("name"), Description = reader.GetAttribute("name"), SourceFile = reader.GetAttribute("sourcefile"), - Runnable = reader.GetAttribute("runnable").AsYesNo(), + Runnable = reader.GetAttribute("runnable").AsRunnable(), Comment = string.Empty, @@ -281,9 +281,13 @@ namespace SabreTools.Library.DatFiles break; case "device_ref": - string device_ref_name = reader.GetAttribute("name"); - if (!machine.Devices.Contains(device_ref_name)) - machine.Devices.Add(device_ref_name); + // TODO: Use these device references + var deviceReference = new ListXmlDeviceReference(); + deviceReference.Name = reader.GetAttribute("name"); + + // TODO: Retire this direct machine setter + if (!machine.Devices.Contains(deviceReference.Name)) + machine.Devices.Add(deviceReference.Name); reader.Read(); break; @@ -310,12 +314,9 @@ namespace SabreTools.Library.DatFiles reader.Read(); break; - // TODO: Should these be new DatItem types? - // TODO: Should any be additional Machine fields? - case "chip": // TODO: Use these chips - var chip = new ListXMLChip(); + var chip = new ListXmlChip(); chip.Name = reader.GetAttribute("name"); chip.Tag = reader.GetAttribute("tag"); chip.Type = reader.GetAttribute("type"); @@ -326,7 +327,7 @@ namespace SabreTools.Library.DatFiles case "display": // TODO: Use these displays - var display = new ListXMLDisplay(); + var display = new ListXmlDisplay(); display.Tag = reader.GetAttribute("tag"); display.Type = reader.GetAttribute("type"); display.Rotate = reader.GetAttribute("rotate"); @@ -347,7 +348,7 @@ namespace SabreTools.Library.DatFiles case "sound": // TODO: Use these sounds - var sound = new ListXMLSound(); + var sound = new ListXmlSound(); sound.Channels = reader.GetAttribute("channels"); reader.Read(); @@ -355,7 +356,7 @@ namespace SabreTools.Library.DatFiles case "condition": // TODO: Use these conditions - var condition = new ListXMLCondition(); + var condition = new ListXmlCondition(); condition.Tag = reader.GetAttribute("tag"); condition.Mask = reader.GetAttribute("mask"); condition.Relation = reader.GetAttribute("relation"); @@ -366,7 +367,7 @@ namespace SabreTools.Library.DatFiles case "input": // TODO: Use these inputs - var input = new ListXMLInput(); + var input = new ListXmlInput(); input.Service = reader.GetAttribute("service").AsYesNo(); input.Tilt = reader.GetAttribute("tilt").AsYesNo(); input.Players = reader.GetAttribute("players"); @@ -381,7 +382,7 @@ namespace SabreTools.Library.DatFiles case "dipswitch": // TODO: Use these dipswitches - var dipSwitch = new ListXMLDipSwitch(); + var dipSwitch = new ListXmlDipSwitch(); dipSwitch.Name = reader.GetAttribute("name"); dipSwitch.Tag = reader.GetAttribute("tag"); dipSwitch.Mask = reader.GetAttribute("mask"); @@ -394,110 +395,106 @@ namespace SabreTools.Library.DatFiles break; case "configuration": - // TODO: Make a new object for this - // string configuration_name = reader.GetAttribute("name"); - // string configuration_tag = reader.GetAttribute("tag"); - // string configuration_mask = reader.GetAttribute("mask"); + // TODO: Use these configurations + var configuration = new ListXmlConfiguration(); + configuration.Name = reader.GetAttribute("name"); + configuration.Tag = reader.GetAttribute("tag"); + configuration.Mask = reader.GetAttribute("mask"); - // // While the subtree contains elements... - // TODO: Make a new object for this - // string conflocation_name = reader.GetAttribute("name"); - // string conflocation_number = reader.GetAttribute("number"); - // bool? conflocation_inverted = Utilities.GetYesNo(reader.GetAttribute("inverted")); - - // // While the subtree contains elements... - // TODO: Make a new object for this - // string confsetting_name = reader.GetAttribute("name"); - // string confsetting_value = reader.GetAttribute("value"); - // bool? confsetting_default = Utilities.GetYesNo(reader.GetAttribute("default")); + // Now read the internal tags + ReadConfiguration(reader.ReadSubtree(), configuration); + // Skip the configuration now that we've processed it reader.Skip(); break; case "port": - // TODO: Make a new object for this - // string port_tag = reader.GetAttribute("tag"); + // TODO: Use these ports + var port = new ListXmlPort(); + port.Tag = reader.GetAttribute("tag"); - // // While the subtree contains elements... - // TODO: Make a new object for this - // string analog_mask = reader.GetAttribute("mask"); + // Now read the internal tags + ReadPort(reader.ReadSubtree(), port); + // Skip the port now that we've processed it reader.Skip(); break; case "adjuster": - // TODO: Make a new object for this - // string adjuster_name = reader.GetAttribute("name"); - // bool? adjuster_default = Utilities.GetYesNo(reader.GetAttribute("default")); + // TODO: Use these adjusters + var adjuster = new ListXmlAdjuster(); + adjuster.Name = reader.GetAttribute("name"); + adjuster.Default = reader.GetAttribute("default").AsYesNo(); - // // For the one possible element... - // TODO: Make a new object for this - // string condition_tag = reader.GetAttribute("tag"); - // string condition_mask = reader.GetAttribute("mask"); - // string condition_relation = reader.GetAttribute("relation"); // (eq|ne|gt|le|lt|ge) - // string condition_value = reader.GetAttribute("value"); + // Now read the internal tags + ReadAdjuster(reader.ReadSubtree(), adjuster); + // Skip the adjuster now that we've processed it reader.Skip(); break; case "driver": - // TODO: Make a new object for this - // string driver_status = reader.GetAttribute("status"); // (good|imperfect|preliminary) - // string driver_emulation = reader.GetAttribute("emulation"); // (good|imperfect|preliminary) - // string driver_cocktail = reader.GetAttribute("cocktail"); // (good|imperfect|preliminary) - // string driver_savestate = reader.GetAttribute("savestate"); // (supported|unsupported) + // TODO: Use these drivers + var driver = new ListXmlDriver(); + driver.Status = reader.GetAttribute("status"); + driver.Emulation = reader.GetAttribute("emulation"); + driver.Cocktail = reader.GetAttribute("cocktail"); + driver.SaveState = reader.GetAttribute("savestate"); reader.Read(); break; case "feature": - // TODO: Make a new object for this - // 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) - // string feature_overall = reader.GetAttribute("overall"); // (unemulated|imperfect) + // TODO: Use these features + var feature = new ListXmlFeature(); + feature.Type = reader.GetAttribute("type"); + feature.Status = reader.GetAttribute("status"); + feature.Overall = reader.GetAttribute("overall"); reader.Read(); break; case "device": - // TODO: Make a new object for this - // string device_type = reader.GetAttribute("type"); - // string device_tag = reader.GetAttribute("tag"); - // string device_fixed_image = reader.GetAttribute("fixed_image"); - // string device_mandatory = reader.GetAttribute("mandatory"); - // string device_interface = reader.GetAttribute("interface"); + // TODO: Use these devices + var device = new ListXmlDevice(); + device.Type = reader.GetAttribute("type"); + device.Tag = reader.GetAttribute("tag"); + device.FixedImage = reader.GetAttribute("fixed_image"); + device.Mandatory = reader.GetAttribute("mandatory"); + device.Interface = reader.GetAttribute("interface"); - // // For the one possible element... - // TODO: Make a new object for this - // string instance_name = reader.GetAttribute("name"); - // string instance_briefname = reader.GetAttribute("briefname"); - - // // While the subtree contains elements... - // TODO: Make a new object for this - // string extension_name = reader.GetAttribute("name"); + // Now read the internal tags + ReadDevice(reader.ReadSubtree(), device); + // Skip the device now that we've processed it reader.Skip(); break; case "slot": - // string slot_name = reader.GetAttribute("name"); - ReadSlot(reader.ReadSubtree(), machine); + // TODO: Use these slots + var slot = new ListXmlSlot(); + slot.Name = reader.GetAttribute("name"); + + // Now read the internal tags + ReadSlot(reader.ReadSubtree(), slot, machine); // Skip the slot now that we've processed it reader.Skip(); break; case "softwarelist": - // TODO: Make a new object for this - // string softwarelist_name = reader.GetAttribute("name"); - // string softwarelist_status = reader.GetAttribute("status"); // (original|compatible) - // string softwarelist_filter = reader.GetAttribute("filter"); + // TODO: Use these softwarelists + var softwareList = new ListXmlSoftwareList(); + softwareList.Name = reader.GetAttribute("name"); + softwareList.Status = reader.GetAttribute("status"); + softwareList.Filter = reader.GetAttribute("filter"); reader.Read(); break; case "ramoption": - // TODO: Make a new object for this - // string ramoption_default = reader.GetAttribute("default"); + // TODO: Use these ramoptions + var ramOption = new ListXmlRamOption(); + ramOption.Default = reader.GetAttribute("default").AsYesNo(); reader.Read(); break; @@ -531,13 +528,17 @@ namespace SabreTools.Library.DatFiles /// Read slot information /// /// XmlReader representing a machine block + /// ListXmlSlot to populate /// Machine information to pass to contained items - private void ReadSlot(XmlReader reader, Machine machine) + private void ReadSlot(XmlReader reader, ListXmlSlot slot, Machine machine) { // If we have an empty machine, skip it if (reader == null) return; + // Get list ready + slot.SlotOptions = new List(); + // Otherwise, add what is possible reader.MoveToContent(); @@ -554,13 +555,17 @@ namespace SabreTools.Library.DatFiles switch (reader.Name) { case "slotoption": - // string slotoption_name = reader.GetAttribute("name"); - string devname = reader.GetAttribute("devname"); - if (!machine.SlotOptions.Contains(devname)) - { - machine.SlotOptions.Add(devname); - } - // bool? slotoption_default = Utilities.GetYesNo(reader.GetAttribute("default")); + var slotOption = new ListXmlSlotOption(); + slotOption.Name = reader.GetAttribute("name"); + slotOption.DeviceName = reader.GetAttribute("devname"); + slotOption.Default = reader.GetAttribute("default").AsYesNo(); + + // TODO: Retire this direct machine setter + if (!machine.SlotOptions.Contains(slotOption.DeviceName)) + machine.SlotOptions.Add(slotOption.DeviceName); + + slot.SlotOptions.Add(slotOption); + reader.Read(); break; @@ -575,15 +580,15 @@ namespace SabreTools.Library.DatFiles /// Read Input information /// /// XmlReader representing a diskarea block - /// ListXMLInput to populate - private void ReadInput(XmlReader reader, ListXMLInput input) + /// ListXmlInput to populate + private void ReadInput(XmlReader reader, ListXmlInput input) { - // If we have an empty trurip, skip it + // If we have an empty input, skip it if (reader == null) return; // Get list ready - input.Controls = new List(); + input.Controls = new List(); // Otherwise, add what is possible reader.MoveToContent(); @@ -601,7 +606,7 @@ namespace SabreTools.Library.DatFiles switch (reader.Name) { case "control": - var control = new ListXMLControl(); + var control = new ListXmlControl(); control.Type = reader.GetAttribute("type"); control.Player = reader.GetAttribute("player"); control.Buttons = reader.GetAttribute("buttons"); @@ -631,16 +636,16 @@ namespace SabreTools.Library.DatFiles /// Read DipSwitch information /// /// XmlReader representing a diskarea block - /// ListXMLDipSwitch to populate - private void ReadDipSwitch(XmlReader reader, ListXMLDipSwitch dipSwitch) + /// ListXmlDipSwitch to populate + private void ReadDipSwitch(XmlReader reader, ListXmlDipSwitch dipSwitch) { - // If we have an empty trurip, skip it + // If we have an empty dipswitch, skip it if (reader == null) return; // Get lists ready - dipSwitch.Locations = new List(); - dipSwitch.Values = new List(); + dipSwitch.Locations = new List(); + dipSwitch.Values = new List(); // Otherwise, add what is possible reader.MoveToContent(); @@ -658,7 +663,7 @@ namespace SabreTools.Library.DatFiles switch (reader.Name) { case "diplocation": - var dipLocation = new ListXMLDipLocation(); + var dipLocation = new ListXmlDipLocation(); dipLocation.Name = reader.GetAttribute("name"); dipLocation.Number = reader.GetAttribute("number"); dipLocation.Inverted = reader.GetAttribute("inverted").AsYesNo(); @@ -669,7 +674,7 @@ namespace SabreTools.Library.DatFiles break; case "dipvalue": - var dipValue = new ListXMLDipValue(); + var dipValue = new ListXmlDipValue(); dipValue.Name = reader.GetAttribute("name"); dipValue.Value = reader.GetAttribute("value"); dipValue.Default = reader.GetAttribute("default").AsYesNo(); @@ -686,6 +691,214 @@ namespace SabreTools.Library.DatFiles } } + /// + /// Read Configuration information + /// + /// XmlReader representing a diskarea block + /// ListXmlConfiguration to populate + private void ReadConfiguration(XmlReader reader, ListXmlConfiguration configuration) + { + // If we have an empty configuration, skip it + if (reader == null) + return; + + // Get lists ready + configuration.Locations = new List(); + configuration.Settings = new List(); + + // Otherwise, add what is possible + reader.MoveToContent(); + + while (!reader.EOF) + { + // We only want elements + if (reader.NodeType != XmlNodeType.Element) + { + reader.Read(); + continue; + } + + // Get the information from the dipswitch + switch (reader.Name) + { + case "conflocation": + var confLocation = new ListXmlConfLocation(); + confLocation.Name = reader.GetAttribute("name"); + confLocation.Number = reader.GetAttribute("number"); + confLocation.Inverted = reader.GetAttribute("inverted").AsYesNo(); + + configuration.Locations.Add(confLocation); + + reader.Read(); + break; + + case "confsetting": + var confSetting = new ListXmlConfSetting(); + confSetting.Name = reader.GetAttribute("name"); + confSetting.Value = reader.GetAttribute("value"); + confSetting.Default = reader.GetAttribute("default").AsYesNo(); + + configuration.Settings.Add(confSetting); + + reader.Read(); + break; + + default: + reader.Read(); + break; + } + } + } + + /// + /// Read Port information + /// + /// XmlReader representing a diskarea block + /// ListXmlPort to populate + private void ReadPort(XmlReader reader, ListXmlPort port) + { + // If we have an empty port, skip it + if (reader == null) + return; + + // Get list ready + port.Analogs = new List(); + + // Otherwise, add what is possible + reader.MoveToContent(); + + while (!reader.EOF) + { + // We only want elements + if (reader.NodeType != XmlNodeType.Element) + { + reader.Read(); + continue; + } + + // Get the information from the port + switch (reader.Name) + { + case "analog": + var analog = new ListXmlAnalog(); + analog.Mask = reader.GetAttribute("mask"); + + port.Analogs.Add(analog); + + reader.Read(); + break; + + default: + reader.Read(); + break; + } + } + } + + /// + /// Read Adjuster information + /// + /// XmlReader representing a diskarea block + /// ListXmlAdjuster to populate + private void ReadAdjuster(XmlReader reader, ListXmlAdjuster adjuster) + { + // If we have an empty port, skip it + if (reader == null) + return; + + // Get list ready + adjuster.Conditions = new List(); + + // Otherwise, add what is possible + reader.MoveToContent(); + + while (!reader.EOF) + { + // We only want elements + if (reader.NodeType != XmlNodeType.Element) + { + reader.Read(); + continue; + } + + // Get the information from the adjuster + switch (reader.Name) + { + case "condition": + var condition = new ListXmlCondition(); + condition.Tag = reader.GetAttribute("tag"); + condition.Mask = reader.GetAttribute("mask"); + condition.Relation = reader.GetAttribute("relation"); + condition.Value = reader.GetAttribute("value"); + + adjuster.Conditions.Add(condition); + + reader.Read(); + break; + + default: + reader.Read(); + break; + } + } + } + + /// + /// Read Device information + /// + /// XmlReader representing a diskarea block + /// ListXmlDevice to populate + private void ReadDevice(XmlReader reader, ListXmlDevice device) + { + // If we have an empty port, skip it + if (reader == null) + return; + + // Get lists ready + device.Instances = new List(); + device.Extensions = new List(); + + // Otherwise, add what is possible + reader.MoveToContent(); + + while (!reader.EOF) + { + // We only want elements + if (reader.NodeType != XmlNodeType.Element) + { + reader.Read(); + continue; + } + + // Get the information from the adjuster + switch (reader.Name) + { + case "instance": + var instance = new ListXmlInstance(); + instance.Name = reader.GetAttribute("name"); + instance.BriefName = reader.GetAttribute("briefname"); + + device.Instances.Add(instance); + + reader.Read(); + break; + + case "extension": + var extension = new ListXmlExtension(); + extension.Name = reader.GetAttribute("name"); + + device.Extensions.Add(extension); + + reader.Read(); + break; + + default: + reader.Read(); + break; + } + } + } + /// /// Create and open an output file for writing direct from a dictionary /// @@ -852,10 +1065,18 @@ namespace SabreTools.Library.DatFiles if (!Header.ExcludeFields.Contains(Field.Runnable)) { - if (datItem.Machine.Runnable == true) - xtw.WriteAttributeString("runnable", "yes"); - else if (datItem.Machine.Runnable == false) - xtw.WriteAttributeString("runnable", "no"); + switch (datItem.Machine.Runnable) + { + case Runnable.No: + xtw.WriteAttributeString("runnable", "no"); + break; + case Runnable.Partial: + xtw.WriteAttributeString("runnable", "partial"); + break; + case Runnable.Yes: + xtw.WriteAttributeString("runnable", "yes"); + break; + } } if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CloneOf, Header.ExcludeFields)) && !string.Equals(datItem.Machine.Name, datItem.Machine.CloneOf, StringComparison.OrdinalIgnoreCase)) diff --git a/SabreTools.Library/DatFiles/Logiqx.cs b/SabreTools.Library/DatFiles/Logiqx.cs index 2df07276..2f91b691 100644 --- a/SabreTools.Library/DatFiles/Logiqx.cs +++ b/SabreTools.Library/DatFiles/Logiqx.cs @@ -313,7 +313,7 @@ namespace SabreTools.Library.DatFiles SourceFile = reader.GetAttribute("sourcefile"), Board = reader.GetAttribute("board"), RebuildTo = reader.GetAttribute("rebuildto"), - Runnable = reader.GetAttribute("runnable").AsYesNo(), // Listxml-specific, used by older DATs + Runnable = reader.GetAttribute("runnable").AsRunnable(), // Used by older DATs Comment = string.Empty, @@ -982,10 +982,18 @@ namespace SabreTools.Library.DatFiles if (!Header.ExcludeFields.Contains(Field.Runnable) && datItem.Machine.Runnable != null) { - if (datItem.Machine.Runnable == true) - xtw.WriteAttributeString("runnable", "yes"); - else if (datItem.Machine.Runnable == false) - xtw.WriteAttributeString("runnable", "no"); + switch (datItem.Machine.Runnable) + { + case Runnable.No: + xtw.WriteAttributeString("runnable", "no"); + break; + case Runnable.Partial: + xtw.WriteAttributeString("runnable", "partial"); + break; + case Runnable.Yes: + xtw.WriteAttributeString("runnable", "yes"); + break; + } } if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.CloneOf, Header.ExcludeFields)) && !string.Equals(datItem.Machine.Name, datItem.Machine.CloneOf, StringComparison.OrdinalIgnoreCase)) diff --git a/SabreTools.Library/DatFiles/SeparatedValue.cs b/SabreTools.Library/DatFiles/SeparatedValue.cs index 216137c9..d6d884b2 100644 --- a/SabreTools.Library/DatFiles/SeparatedValue.cs +++ b/SabreTools.Library/DatFiles/SeparatedValue.cs @@ -376,7 +376,7 @@ namespace SabreTools.Library.DatFiles break; case "Machine.Runnable": - machine.Runnable = value.AsYesNo(); + machine.Runnable = value.AsRunnable(); break; case "Machine.Devices": @@ -405,7 +405,12 @@ namespace SabreTools.Library.DatFiles foreach (var info in infos) { var infoPair = info.Split('='); - machine.Infos.Add(new ListXmlInfo(infoPair[0], infoPair[1])); + + var infoObj = new ListXmlInfo(); + infoObj.Name = infoPair[0]; + infoObj.Value = infoPair[1]; + + machine.Infos.Add(infoObj); } break; @@ -498,7 +503,7 @@ namespace SabreTools.Library.DatFiles break; case "Machine.DipSwitches": - machine.DipSwitches = new List(); + machine.DipSwitches = new List(); // TODO: There is no way this would work... Just use empty for now break; diff --git a/SabreTools.Library/DatFiles/SoftwareList.cs b/SabreTools.Library/DatFiles/SoftwareList.cs index 5d7f4e1c..52831977 100644 --- a/SabreTools.Library/DatFiles/SoftwareList.cs +++ b/SabreTools.Library/DatFiles/SoftwareList.cs @@ -147,7 +147,7 @@ namespace SabreTools.Library.DatFiles CloneOf = reader.GetAttribute("cloneof") ?? string.Empty, Infos = new List(), SharedFeatures = new List(), - DipSwitches = new List(), + DipSwitches = new List(), MachineType = (machineType == MachineType.NULL ? MachineType.None : machineType), }; @@ -181,7 +181,12 @@ namespace SabreTools.Library.DatFiles break; case "info": - machine.Infos.Add(new ListXmlInfo(reader.GetAttribute("name"), reader.GetAttribute("value"))); + var info = new ListXmlInfo(); + info.Name = reader.GetAttribute("name"); + info.Value = reader.GetAttribute("value"); + + machine.Infos.Add(info); + reader.Read(); break; @@ -248,7 +253,6 @@ namespace SabreTools.Library.DatFiles areaEndinaness; long? areasize = null; var features = new List(); - var dipswitches = new List(); bool containsItems = false; while (!reader.EOF) @@ -334,7 +338,7 @@ namespace SabreTools.Library.DatFiles case "dipswitch": // TODO: Use these dipswitches - var dipSwitch = new ListXMLDipSwitch(); + var dipSwitch = new ListXmlDipSwitch(); dipSwitch.Name = reader.GetAttribute("name"); dipSwitch.Tag = reader.GetAttribute("tag"); dipSwitch.Mask = reader.GetAttribute("mask"); @@ -570,14 +574,14 @@ namespace SabreTools.Library.DatFiles /// /// XmlReader representing a diskarea block /// ListXMLDipSwitch to populate - private void ReadDipSwitch(XmlReader reader, ListXMLDipSwitch dipSwitch) + private void ReadDipSwitch(XmlReader reader, ListXmlDipSwitch dipSwitch) { - // If we have an empty trurip, skip it + // If we have an empty dipswitch, skip it if (reader == null) return; // Get list ready - dipSwitch.Values = new List(); + dipSwitch.Values = new List(); // Otherwise, add what is possible reader.MoveToContent(); @@ -595,7 +599,7 @@ namespace SabreTools.Library.DatFiles switch (reader.Name) { case "dipvalue": - var dipValue = new ListXMLDipValue(); + var dipValue = new ListXmlDipValue(); dipValue.Name = reader.GetAttribute("name"); dipValue.Value = reader.GetAttribute("value"); dipValue.Default = reader.GetAttribute("default").AsYesNo(); @@ -842,14 +846,14 @@ namespace SabreTools.Library.DatFiles if (!Header.ExcludeFields.Contains(Field.DipSwitches) && datItem.Machine.DipSwitches != null && datItem.Machine.DipSwitches.Count > 0) { - foreach (ListXMLDipSwitch dip in datItem.Machine.DipSwitches) + foreach (ListXmlDipSwitch dip in datItem.Machine.DipSwitches) { xtw.WriteStartElement("dipswitch"); xtw.WriteAttributeString("name", dip.Name); xtw.WriteAttributeString("tag", dip.Tag); xtw.WriteAttributeString("mask", dip.Mask); - foreach (ListXMLDipValue dipval in dip.Values) + foreach (ListXmlDipValue dipval in dip.Values) { xtw.WriteStartElement("dipvalue"); xtw.WriteAttributeString("name", dipval.Name); diff --git a/SabreTools.Library/DatItems/Auxiliary.cs b/SabreTools.Library/DatItems/Auxiliary.cs index ada554cb..a0e20c4b 100644 --- a/SabreTools.Library/DatItems/Auxiliary.cs +++ b/SabreTools.Library/DatItems/Auxiliary.cs @@ -10,41 +10,32 @@ namespace SabreTools.Library.DatItems #region ListXML /// - /// Represents one ListXML info object + /// Represents one ListXML adjuster /// - public class ListXmlInfo + public class ListXmlAdjuster { public string Name { get; set; } - public string Value { get; set; } + public bool? Default { get; set; } + public List Conditions { get; set; } - public ListXmlInfo(string name, string value) + public ListXmlAdjuster() { - Name = name; - Value = value; + Conditions = new List(); } } - #endregion - - #region OpenMSX - /// - /// Represents the OpenMSX original value + /// Represents one ListXML analog /// - public class OpenMSXOriginal + public class ListXmlAnalog { - public string Name { get; set; } - public bool? Value { get; set; } + public string Mask { get; set; } } - #endregion - - #region ListXML - /// /// Represents one ListXML chip /// - public class ListXMLChip + public class ListXmlChip { public string Name { get; set; } public string Tag { get; set; } @@ -55,7 +46,7 @@ namespace SabreTools.Library.DatItems /// /// Represents one ListXML condition /// - public class ListXMLCondition + public class ListXmlCondition { public string Tag { get; set; } public string Mask { get; set; } @@ -63,10 +54,48 @@ namespace SabreTools.Library.DatItems public string Value { get; set; } } + /// + /// Represents one ListXML configuration + /// + public class ListXmlConfiguration + { + public string Name { get; set; } + public string Tag { get; set; } + public string Mask { get; set; } + public List Locations { get; set; } + public List Settings { get; set; } + + public ListXmlConfiguration() + { + Locations = new List(); + Settings = new List(); + } + } + + /// + /// Represents one ListXML conflocation + /// + public class ListXmlConfLocation + { + public string Name { get; set; } + public string Number { get; set; } + public bool? Inverted { get; set; } + } + + /// + /// Represents one ListXML confsetting + /// + public class ListXmlConfSetting + { + public string Name { get; set; } + public string Value { get; set; } + public bool? Default { get; set; } + } + /// /// Represents one ListXML control /// - public class ListXMLControl + public class ListXmlControl { public string Type { get; set; } public string Player { get; set; } // TODO: Int32? @@ -82,10 +111,38 @@ namespace SabreTools.Library.DatItems public string Ways3 { get; set; } // TODO: Int32? Float? } + /// + /// Represents one ListXML device + /// + public class ListXmlDevice + { + public string Type { get; set; } + public string Tag { get; set; } + public string FixedImage { get; set; } + public string Mandatory { get; set; } // TODO: bool? + public string Interface { get; set; } + public List Instances { get; set; } + public List Extensions { get; set; } + + public ListXmlDevice() + { + Instances = new List(); + Extensions = new List(); + } + } + + /// + /// Represents one ListXML deviceref + /// + public class ListXmlDeviceReference + { + public string Name { get; set; } + } + /// /// Represents one ListXML display /// - public class ListXMLDisplay + public class ListXmlDisplay { public string Tag { get; set; } public string Type { get; set; } // TODO: (raster|vector|lcd|svg|unknown) @@ -107,25 +164,25 @@ namespace SabreTools.Library.DatItems /// Represents one ListXML dipswitch /// /// Also used by SoftwareList - public class ListXMLDipSwitch + public class ListXmlDipSwitch { public string Name { get; set; } public string Tag { get; set; } public string Mask { get; set; } - public List Locations { get; set; } - public List Values { get; set; } + public List Locations { get; set; } + public List Values { get; set; } - public ListXMLDipSwitch() + public ListXmlDipSwitch() { - Locations = new List(); - Values = new List(); + Locations = new List(); + Values = new List(); } } /// /// Represents one ListXML diplocation /// - public class ListXMLDipLocation + public class ListXmlDipLocation { public string Name { get; set; } public string Number { get; set; } @@ -136,40 +193,156 @@ namespace SabreTools.Library.DatItems /// Represents one ListXML dipvalue /// /// Also used by SoftwareList - public class ListXMLDipValue + public class ListXmlDipValue { public string Name { get; set; } public string Value { get; set; } public bool? Default { get; set; } } + /// + /// Represents one ListXML driver + /// + public class ListXmlDriver + { + public string Status { get; set; } // TODO: (good|imperfect|preliminary) + public string Emulation { get; set; } // TODO: (good|imperfect|preliminary) + public string Cocktail { get; set; } // TODO: bool? (good|imperfect|preliminary)? + public string SaveState { get; set; } // TODO: (supported|unsupported) + } + + /// + /// Represents one ListXML extension + /// + public class ListXmlExtension + { + public string Name { get; set; } + } + + /// + /// Represents one ListXML feature + /// + public class ListXmlFeature + { + public string Type { get; set; } // TODO: (protection|palette|graphics|sound|controls|keyboard|mouse|microphone|camera|disk|printer|lan|wan|timing) + public string Status { get; set; } // TODO: (unemulated|imperfect) + public string Overall { get; set; } // TODO: (unemulated|imperfect) + } + + /// + /// Represents one ListXML info + /// + public class ListXmlInfo + { + public string Name { get; set; } + public string Value { get; set; } + } + /// /// Represents one ListXML input /// - public class ListXMLInput + public class ListXmlInput { public bool? Service { get; set; } public bool? Tilt { get; set; } public string Players { get; set; } // TODO: Int32? public string Coins { get; set; } // TODO: Int32? - public List Controls { get; set; } + public List Controls { get; set; } - public ListXMLInput() + public ListXmlInput() { - Controls = new List(); + Controls = new List(); } } + /// + /// Represents one ListXML instance + /// + public class ListXmlInstance + { + public string Name { get; set; } + public string BriefName { get; set; } + } + + /// + /// Represents one ListXML port + /// + public class ListXmlPort + { + public string Tag { get; set; } + public List Analogs { get; set; } + + public ListXmlPort() + { + Analogs = new List(); + } + } + + /// + /// Represents one ListXML ramoption + /// + public class ListXmlRamOption + { + public bool? Default { get; set; } + } + + /// + /// Represents one ListXML slot + /// + public class ListXmlSlot + { + public string Name { get; set; } + public List SlotOptions { get; set; } + + public ListXmlSlot() + { + SlotOptions = new List(); + } + } + + /// + /// Represents one ListXML slotoption + /// + public class ListXmlSlotOption + { + public string Name { get; set; } + public string DeviceName { get; set; } + public bool? Default { get; set; } + } + + /// + /// Represents one ListXML softwarelist + /// + public class ListXmlSoftwareList + { + public string Name { get; set; } + public string Status { get; set; } // TODO: (original|compatible) + public string Filter { get; set; } + } + /// /// Represents one ListXML sound /// - public class ListXMLSound + public class ListXmlSound { public string Channels { get; set; } // TODO: Int32? } #endregion + #region OpenMSX + + /// + /// Represents the OpenMSX original value + /// + public class OpenMSXOriginal + { + public string Name { get; set; } + public bool? Value { get; set; } + } + + #endregion + #region SoftwareList /// diff --git a/SabreTools.Library/DatItems/Enums.cs b/SabreTools.Library/DatItems/Enums.cs index a716bfb6..94cebf30 100644 --- a/SabreTools.Library/DatItems/Enums.cs +++ b/SabreTools.Library/DatItems/Enums.cs @@ -241,6 +241,18 @@ namespace SabreTools.Library.DatItems Mechanical = 1 << 3, } + /// + /// Determine machine runnable status + /// + [Flags] + public enum Runnable + { + NULL, + No, + Partial, + Yes, + } + /// /// Determine machine support status /// diff --git a/SabreTools.Library/DatItems/Machine.cs b/SabreTools.Library/DatItems/Machine.cs index e229d68e..6c8b4558 100644 --- a/SabreTools.Library/DatItems/Machine.cs +++ b/SabreTools.Library/DatItems/Machine.cs @@ -145,20 +145,21 @@ namespace SabreTools.Library.DatItems /// /// Machine runnable status /// - /// yes = true, partial = null, no = false /// Also in Logiqx [JsonProperty("runnable")] - public bool? Runnable { get; set; } = null; + public Runnable Runnable { get; set; } = Runnable.NULL; /// /// List of associated device names /// + /// TODO: Use ListXmlDeviceReference for this... [JsonProperty("devices")] public List Devices { get; set; } = null; /// /// List of slot options /// + /// TODO: Use ListXmlSlot for this... [JsonProperty("slotoptions")] public List SlotOptions { get; set; } = null; @@ -285,8 +286,10 @@ namespace SabreTools.Library.DatItems /// List of shared feature items /// /// Also in SoftwareList + /// TODO: Move to ListXML section + /// TODO: Order ListXML and SoftwareList outputs by area names [JsonProperty("dipswitches")] - public List DipSwitches { get; set; } = null; + public List DipSwitches { get; set; } = null; #endregion @@ -376,7 +379,7 @@ namespace SabreTools.Library.DatItems fieldValue = SourceFile; break; case Field.Runnable: - fieldValue = Runnable?.ToString(); + fieldValue = Runnable.ToString(); break; case Field.Devices: fieldValue = string.Join(";", Devices ?? new List()); @@ -547,7 +550,7 @@ namespace SabreTools.Library.DatItems SourceFile = mappings[Field.SourceFile]; if (mappings.Keys.Contains(Field.Runnable)) - Runnable = mappings[Field.Runnable].AsYesNo(); + Runnable = mappings[Field.Runnable].AsRunnable(); if (mappings.Keys.Contains(Field.Devices)) { @@ -576,7 +579,12 @@ namespace SabreTools.Library.DatItems foreach (string pair in pairs) { string[] split = pair.Split('='); - Infos.Add(new ListXmlInfo(split[0], split[1])); + + var infoObj = new ListXmlInfo(); + infoObj.Name = split[0]; + infoObj.Value = split[1]; + + Infos.Add(infoObj); } } @@ -657,7 +665,7 @@ namespace SabreTools.Library.DatItems if (mappings.Keys.Contains(Field.DipSwitches)) { if (DipSwitches == null) - DipSwitches = new List(); + DipSwitches = new List(); // TODO: There's no way this will work... just create the new list for now } @@ -919,7 +927,9 @@ namespace SabreTools.Library.DatItems return false; // Filter on runnable - if (filter.Runnable.MatchesNeutral(null, Runnable) == false) + if (filter.Runnables.MatchesPositive(Runnable.NULL, Runnable) == false) + return false; + if (filter.Runnables.MatchesNegative(Runnable.NULL, Runnable) == true) return false; // Filter on devices @@ -1141,7 +1151,7 @@ namespace SabreTools.Library.DatItems SourceFile = null; if (fields.Contains(Field.Runnable)) - Runnable = null; + Runnable = Runnable.NULL; if (fields.Contains(Field.Devices)) Devices = null; diff --git a/SabreTools.Library/Filtering/Filter.cs b/SabreTools.Library/Filtering/Filter.cs index 3d4bb3e2..216b9dbd 100644 --- a/SabreTools.Library/Filtering/Filter.cs +++ b/SabreTools.Library/Filtering/Filter.cs @@ -121,7 +121,7 @@ namespace SabreTools.Library.Filtering /// /// Include or exclude items with the "Runnable" tag /// - public FilterItem Runnable { get; private set; } = new FilterItem() { Neutral = null }; + public FilterItem Runnables { get; private set; } = new FilterItem() { Positive = Runnable.NULL, Negative = Runnable.NULL }; /// /// Include or exclude machine devices @@ -703,10 +703,10 @@ namespace SabreTools.Library.Filtering break; case Field.Runnable: - if (negate || value.Equals("false", StringComparison.OrdinalIgnoreCase)) - Runnable.Neutral = false; + if (negate) + Runnables.Negative |= value.AsRunnable(); else - Runnable.Neutral = true; + Runnables.Positive |= value.AsRunnable(); break; case Field.Devices: diff --git a/SabreTools.Library/Tools/Converters.cs b/SabreTools.Library/Tools/Converters.cs index a2730393..d8d03a99 100644 --- a/SabreTools.Library/Tools/Converters.cs +++ b/SabreTools.Library/Tools/Converters.cs @@ -745,6 +745,36 @@ namespace SabreTools.Library.Tools #endif } + /// + /// Get Runnable value from input string + /// + /// String to get value from + /// Runnable value corresponding to the string + public static Runnable AsRunnable(this string runnable) + { +#if NET_FRAMEWORK + switch (runnable?.ToLowerInvariant()) + { + case "no": + return Runnable.No; + case "partial": + return Runnable.Partial; + case "yes": + return Runnable.Yes; + default: + return Runnable.NULL; + } +#else + return runnable?.ToLowerInvariant() switch + { + "no" => Runnable.No, + "partial" => Runnable.Partial, + "yes" => Runnable.Yes, + _ => Runnable.NULL, + }; +#endif + } + /// /// Get SplitType value from input ForceMerging /// @@ -849,7 +879,6 @@ namespace SabreTools.Library.Tools #endif } - /// /// Get bool? value from input string ///