diff --git a/SabreTools.Library/DatFiles/DatFile.cs b/SabreTools.Library/DatFiles/DatFile.cs index e84265bb..35672eda 100644 --- a/SabreTools.Library/DatFiles/DatFile.cs +++ b/SabreTools.Library/DatFiles/DatFile.cs @@ -1083,6 +1083,7 @@ namespace SabreTools.Library.DatFiles OneRomPerGame(); // If we are removing fields, do that now + // TODO: If this works, why in the hell do I have all of the "GetField" crap????? if (Header.ExcludeFields != null && Header.ExcludeFields.Any()) RemoveFieldsFromItems(); @@ -1536,8 +1537,8 @@ namespace SabreTools.Library.DatFiles // If the game has no devices, we continue if (Items[game][0].Machine.DeviceReferences == null || Items[game][0].Machine.DeviceReferences.Count == 0 - || (slotoptions && Items[game][0].Machine.SlotOptions == null) - || (slotoptions && Items[game][0].Machine.SlotOptions.Count == 0)) + || (slotoptions && Items[game][0].Machine.Slots == null) + || (slotoptions && Items[game][0].Machine.Slots.Count == 0)) { continue; } @@ -1577,36 +1578,39 @@ namespace SabreTools.Library.DatFiles // If we're checking slotoptions too if (slotoptions) { - // Determine if the game has any slotoptions or not - List slotopts = Items[game][0].Machine.SlotOptions; - List newslotopts = new List(); - foreach (string slotopt in slotopts) + // Determine if the game has any slots or not + List slots = Items[game][0].Machine.Slots; + List newSlots = new List(); + foreach (ListXmlSlot slot in slots) { - // If the slotoption doesn't exist then we continue - if (Items[slotopt].Count == 0) - continue; - - // Otherwise, copy the items from the slotoption to the current game - DatItem copyFrom = Items[game][0]; - List slotItems = Items[slotopt]; - foreach (DatItem item in slotItems) + foreach (ListXmlSlotOption slotOption in slot.SlotOptions) { - DatItem datItem = (DatItem)item.Clone(); - newslotopts.AddRange(datItem.Machine.SlotOptions ?? new List()); - datItem.CopyMachineInformation(copyFrom); - if (Items[game].Where(i => i.Name.ToLowerInvariant() == datItem.Name.ToLowerInvariant()).Count() == 0) + // If the slotoption doesn't exist then we continue + if (Items[slotOption.Name].Count == 0) + continue; + + // Otherwise, copy the items from the slotoption to the current game + DatItem copyFrom = Items[game][0]; + List slotItems = Items[slotOption.Name]; + foreach (DatItem item in slotItems) { - foundnew = true; - Items.Add(game, datItem); + DatItem datItem = (DatItem)item.Clone(); + newSlots.AddRange(datItem.Machine.Slots ?? new List()); + + datItem.CopyMachineInformation(copyFrom); + if (Items[game].Where(i => i.Name.ToLowerInvariant() == datItem.Name.ToLowerInvariant()).Count() == 0) + { + foundnew = true; + Items.Add(game, datItem); + } } } } - // Now that every slotoption is accounted for, add the new list of slotoptions, if they don't already exist - foreach (string slotopt in newslotopts) + // Now that every slotoption is accounted for, add the new list of slots, if they don't already exist + foreach (ListXmlSlot slot in newSlots) { - if (!Items[game][0].Machine.SlotOptions.Contains(slotopt)) - Items[game][0].Machine.SlotOptions.Add(slotopt); + Items[game][0].Machine.Slots.Add(slot); } } } diff --git a/SabreTools.Library/DatFiles/Json.cs b/SabreTools.Library/DatFiles/Json.cs index 60668594..2a665c89 100644 --- a/SabreTools.Library/DatFiles/Json.cs +++ b/SabreTools.Library/DatFiles/Json.cs @@ -550,15 +550,9 @@ namespace SabreTools.Library.DatFiles } break; - case "slotoptions": - machine.SlotOptions = new List(); - jtr.Read(); // Start Array - while (!sr.EndOfStream && jtr.TokenType != JsonToken.EndArray) - { - machine.SlotOptions.Add(jtr.ReadAsString()); - } - break; + // TODO: Add `slot` + case "infos": machine.Infos = new List(); jtr.Read(); // Start Array @@ -654,12 +648,14 @@ namespace SabreTools.Library.DatFiles if (jtr.TokenType == JsonToken.EndArray) break; + var sharedFeature = new SoftwareListSharedFeature(); + jtr.Read(); // Key - string key = jtr.Value as string; - string value = jtr.ReadAsString(); + sharedFeature.Name = jtr.Value as string; + sharedFeature.Value = jtr.ReadAsString(); jtr.Read(); // End object - machine.SharedFeatures.Add(new SoftwareListSharedFeature(key, value)); + machine.SharedFeatures.Add(sharedFeature); } break; @@ -850,7 +846,7 @@ namespace SabreTools.Library.DatFiles datItem.AltName = altName; datItem.AltTitle = altTitle; - datItem.Original = new OpenMSXOriginal() { Name = original }; + datItem.Original = new OpenMSXOriginal() { Content = original }; datItem.OpenMSXSubType = subType; datItem.OpenMSXType = msxType; datItem.Remark = remark; @@ -998,12 +994,14 @@ namespace SabreTools.Library.DatFiles if (jtr.TokenType == JsonToken.EndArray) break; + var feature = new SoftwareListFeature(); + jtr.Read(); // Key - string key = jtr.Value as string; - string featureValue = jtr.ReadAsString(); + feature.Name = jtr.Value as string; + feature.Value = jtr.ReadAsString(); jtr.Read(); // End object - features.Add(new SoftwareListFeature(key, featureValue)); + features.Add(feature); } break; @@ -1724,7 +1722,7 @@ namespace SabreTools.Library.DatFiles break; } } - if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Devices, Header.ExcludeFields))) + if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.DeviceReferences, Header.ExcludeFields))) { jtw.WritePropertyName("devices"); jtw.WriteStartArray(); @@ -1735,17 +1733,9 @@ namespace SabreTools.Library.DatFiles jtw.WriteEndArray(); } - if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.SlotOptions, Header.ExcludeFields))) - { - jtw.WritePropertyName("slotoptions"); - jtw.WriteStartArray(); - foreach (string slotoption in datItem.Machine.SlotOptions) - { - jtw.WriteValue(slotoption); - } - - jtw.WriteEndArray(); - } + + // TODO: Add Field.Slots + if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Infos, Header.ExcludeFields))) { jtw.WritePropertyName("infos"); @@ -2231,7 +2221,7 @@ namespace SabreTools.Library.DatFiles if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.Original, Header.ExcludeFields))) { jtw.WritePropertyName("original"); - jtw.WriteValue(datItem.Original.Name); + jtw.WriteValue(datItem.Original.Content); } if (!string.IsNullOrWhiteSpace(datItem.GetField(Field.OpenMSXSubType, Header.ExcludeFields))) { diff --git a/SabreTools.Library/DatFiles/Listxml.cs b/SabreTools.Library/DatFiles/Listxml.cs index ef9b1177..62f98484 100644 --- a/SabreTools.Library/DatFiles/Listxml.cs +++ b/SabreTools.Library/DatFiles/Listxml.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Xml; @@ -125,10 +126,6 @@ namespace SabreTools.Library.DatFiles // Otherwise, add what is possible reader.MoveToContent(); - string key = string.Empty; - string temptype = reader.Name; - bool containsItems = false; - // Create a new machine MachineType machineType = MachineType.NULL; if (reader.GetAttribute("isbios").AsYesNo() == true) @@ -143,21 +140,29 @@ namespace SabreTools.Library.DatFiles Machine machine = new Machine { Name = reader.GetAttribute("name"), - Description = reader.GetAttribute("name"), - SourceFile = reader.GetAttribute("sourcefile"), - Runnable = reader.GetAttribute("runnable").AsRunnable(), - Comment = string.Empty, - + Description = reader.GetAttribute("name"), CloneOf = reader.GetAttribute("cloneof") ?? string.Empty, RomOf = reader.GetAttribute("romof") ?? string.Empty, SampleOf = reader.GetAttribute("sampleof") ?? string.Empty, - DeviceReferences = new List(), - SlotOptions = new List(), - MachineType = (machineType == MachineType.NULL ? MachineType.None : machineType), + + SourceFile = reader.GetAttribute("sourcefile"), + Runnable = reader.GetAttribute("runnable").AsRunnable(), + DeviceReferences = new List(), + Chips = new List(), + Displays = new List(), + Sounds = new List(), + Conditions = new List(), + Inputs = new List(), + DipSwitches = new List(), + Configurations = new List(), + Slots = new List(), }; + // Get list for new DatItems + List datItems = new List(); + while (!reader.EOF) { // We only want elements @@ -183,9 +188,7 @@ namespace SabreTools.Library.DatFiles break; case "biosset": - containsItems = true; - - DatItem biosset = new BiosSet + datItems.Add(new BiosSet { Name = reader.GetAttribute("name"), Description = reader.GetAttribute("description"), @@ -196,20 +199,13 @@ namespace SabreTools.Library.DatFiles Index = indexId, Name = filename, }, - }; - - biosset.CopyMachineInformation(machine); - - // Now process and add the rom - key = ParseAddHelper(biosset); + }); reader.Read(); break; case "rom": - containsItems = true; - - DatItem rom = new Rom + datItems.Add(new Rom { Name = reader.GetAttribute("name"), Bios = reader.GetAttribute("bios"), @@ -234,20 +230,13 @@ namespace SabreTools.Library.DatFiles Index = indexId, Name = filename, }, - }; - - rom.CopyMachineInformation(machine); - - // Now process and add the rom - key = ParseAddHelper(rom); + }); reader.Read(); break; case "disk": - containsItems = true; - - DatItem disk = new Disk + datItems.Add(new Disk { Name = reader.GetAttribute("name"), MD5 = reader.GetAttribute("md5"), @@ -270,18 +259,12 @@ namespace SabreTools.Library.DatFiles Index = indexId, Name = filename, }, - }; - - disk.CopyMachineInformation(machine); - - // Now process and add the rom - key = ParseAddHelper(disk); + }); reader.Read(); break; case "device_ref": - // TODO: Use these device references var deviceReference = new ListXmlDeviceReference(); deviceReference.Name = reader.GetAttribute("name"); @@ -291,9 +274,7 @@ namespace SabreTools.Library.DatFiles break; case "sample": - containsItems = true; - - DatItem samplerom = new Sample + datItems.Add(new Sample { Name = reader.GetAttribute("name"), @@ -302,29 +283,24 @@ namespace SabreTools.Library.DatFiles Index = indexId, Name = filename, }, - }; - - samplerom.CopyMachineInformation(machine); - - // Now process and add the rom - key = ParseAddHelper(samplerom); + }); reader.Read(); break; case "chip": - // TODO: Use these chips var chip = new ListXmlChip(); chip.Name = reader.GetAttribute("name"); chip.Tag = reader.GetAttribute("tag"); chip.Type = reader.GetAttribute("type"); chip.Clock = reader.GetAttribute("clock"); + machine.Chips.Add(chip); + reader.Read(); break; case "display": - // TODO: Use these displays var display = new ListXmlDisplay(); display.Tag = reader.GetAttribute("tag"); display.Type = reader.GetAttribute("type"); @@ -341,30 +317,33 @@ namespace SabreTools.Library.DatFiles display.VBend = reader.GetAttribute("vbend"); display.VStart = reader.GetAttribute("vstart"); + machine.Displays.Add(display); + reader.Read(); break; case "sound": - // TODO: Use these sounds var sound = new ListXmlSound(); sound.Channels = reader.GetAttribute("channels"); + machine.Sounds.Add(sound); + reader.Read(); break; case "condition": - // TODO: Use these conditions var condition = new ListXmlCondition(); condition.Tag = reader.GetAttribute("tag"); condition.Mask = reader.GetAttribute("mask"); condition.Relation = reader.GetAttribute("relation"); condition.Value = reader.GetAttribute("value"); + machine.Conditions.Add(condition); + reader.Read(); break; case "input": - // TODO: Use these inputs var input = new ListXmlInput(); input.Service = reader.GetAttribute("service").AsYesNo(); input.Tilt = reader.GetAttribute("tilt").AsYesNo(); @@ -374,12 +353,13 @@ namespace SabreTools.Library.DatFiles // Now read the internal tags ReadInput(reader.ReadSubtree(), input); + machine.Inputs.Add(input); + // Skip the input now that we've processed it reader.Skip(); break; case "dipswitch": - // TODO: Use these dipswitches var dipSwitch = new ListXmlDipSwitch(); dipSwitch.Name = reader.GetAttribute("name"); dipSwitch.Tag = reader.GetAttribute("tag"); @@ -388,12 +368,13 @@ namespace SabreTools.Library.DatFiles // Now read the internal tags ReadDipSwitch(reader.ReadSubtree(), dipSwitch); + machine.DipSwitches.Add(dipSwitch); + // Skip the dipswitch now that we've processed it reader.Skip(); break; case "configuration": - // TODO: Use these configurations var configuration = new ListXmlConfiguration(); configuration.Name = reader.GetAttribute("name"); configuration.Tag = reader.GetAttribute("tag"); @@ -402,6 +383,8 @@ namespace SabreTools.Library.DatFiles // Now read the internal tags ReadConfiguration(reader.ReadSubtree(), configuration); + machine.Configurations.Add(configuration); + // Skip the configuration now that we've processed it reader.Skip(); break; @@ -451,6 +434,7 @@ namespace SabreTools.Library.DatFiles reader.Read(); break; + case "device": // TODO: Use these devices var device = new ListXmlDevice(); @@ -468,12 +452,12 @@ namespace SabreTools.Library.DatFiles break; case "slot": - // TODO: Use these slots var slot = new ListXmlSlot(); slot.Name = reader.GetAttribute("name"); // Now read the internal tags ReadSlot(reader.ReadSubtree(), slot, machine); + machine.Slots.Add(slot); // Skip the slot now that we've processed it reader.Skip(); @@ -503,8 +487,18 @@ namespace SabreTools.Library.DatFiles } } + // If we found items, copy the machine info and add them + if (datItems.Any()) + { + foreach (DatItem datItem in datItems) + { + datItem.CopyMachineInformation(machine); + ParseAddHelper(datItem); + } + } + // If no items were found for this machine, add a Blank placeholder - if (!containsItems) + else { Blank blank = new Blank() { @@ -558,10 +552,6 @@ namespace SabreTools.Library.DatFiles 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(); diff --git a/SabreTools.Library/DatFiles/OpenMSX.cs b/SabreTools.Library/DatFiles/OpenMSX.cs index a84d75a2..0bd158b1 100644 --- a/SabreTools.Library/DatFiles/OpenMSX.cs +++ b/SabreTools.Library/DatFiles/OpenMSX.cs @@ -250,7 +250,7 @@ namespace SabreTools.Library.DatFiles case "original": original = new OpenMSXOriginal(); original.Value = reader.GetAttribute("value").AsYesNo(); - original.Name = reader.ReadElementContentAsString(); + original.Content = reader.ReadElementContentAsString(); break; default: @@ -730,7 +730,7 @@ namespace SabreTools.Library.DatFiles { xtw.WriteStartElement("original"); xtw.WriteAttributeString("value", rom.Original.Value == true ? "true" : "false"); - xtw.WriteString(rom.Original.Name); + xtw.WriteString(rom.Original.Content); xtw.WriteEndElement(); } diff --git a/SabreTools.Library/DatFiles/SeparatedValue.cs b/SabreTools.Library/DatFiles/SeparatedValue.cs index 9a79cdac..b600cecf 100644 --- a/SabreTools.Library/DatFiles/SeparatedValue.cs +++ b/SabreTools.Library/DatFiles/SeparatedValue.cs @@ -389,15 +389,7 @@ namespace SabreTools.Library.DatFiles break; - case "Machine.SlotOptions": - machine.SlotOptions = new List(); - var slotOptions = value.Split(';'); - foreach (var slotOption in slotOptions) - { - machine.SlotOptions.Add(slotOption); - } - - break; + // TODO: Add Machine.Slot case "Machine.Infos": machine.Infos = new List(); @@ -494,18 +486,20 @@ namespace SabreTools.Library.DatFiles case "Machine.SharedFeatures": machine.SharedFeatures = new List(); var sharedFeatures = value.Split(';'); - foreach (var sharedFeature in sharedFeatures) + foreach (var pair in sharedFeatures) { - var featurePair = sharedFeature.Split('='); - machine.SharedFeatures.Add(new SoftwareListSharedFeature(featurePair[0], featurePair[1])); + var featurePair = pair.Split('='); + + var sharedFeature = new SoftwareListSharedFeature(); + sharedFeature.Name = featurePair[0]; + sharedFeature.Value = featurePair[1]; + + machine.SharedFeatures.Add(sharedFeature); } break; - case "Machine.DipSwitches": - machine.DipSwitches = new List(); - // TODO: There is no way this would work... Just use empty for now - break; + // TODO: Implement Machine.DipSwitches #endregion @@ -577,7 +571,12 @@ namespace SabreTools.Library.DatFiles foreach (var splitFeature in splitFeatures) { var featurePair = splitFeature.Split('='); - features.Add(new SoftwareListFeature(featurePair[0], featurePair[1])); + + var feature = new SoftwareListFeature(); + feature.Name = featurePair[0]; + feature.Value = featurePair[1]; + + features.Add(feature); } break; @@ -720,7 +719,7 @@ namespace SabreTools.Library.DatFiles AltName = altName, AltTitle = altTitle, - Original = new OpenMSXOriginal() { Name = original }, + Original = new OpenMSXOriginal() { Content = original }, OpenMSXSubType = subType, OpenMSXType = msxType, Remark = remark, @@ -755,7 +754,7 @@ namespace SabreTools.Library.DatFiles AltName = altName, AltTitle = altTitle, - Original = new OpenMSXOriginal() { Name = original }, + Original = new OpenMSXOriginal() { Content = original }, OpenMSXSubType = subType, OpenMSXType = msxType, Remark = remark, @@ -793,7 +792,7 @@ namespace SabreTools.Library.DatFiles AltName = altName, AltTitle = altTitle, - Original = new OpenMSXOriginal() { Name = original }, + Original = new OpenMSXOriginal() { Content = original }, OpenMSXSubType = subType, OpenMSXType = msxType, Remark = remark, @@ -843,7 +842,7 @@ namespace SabreTools.Library.DatFiles AltName = altName, AltTitle = altTitle, - Original = new OpenMSXOriginal() { Name = original }, + Original = new OpenMSXOriginal() { Content = original }, OpenMSXSubType = subType, OpenMSXType = msxType, Remark = remark, @@ -883,7 +882,7 @@ namespace SabreTools.Library.DatFiles AltName = altName, AltTitle = altTitle, - Original = new OpenMSXOriginal() { Name = original }, + Original = new OpenMSXOriginal() { Content = original }, OpenMSXSubType = subType, OpenMSXType = msxType, Remark = remark, @@ -937,7 +936,7 @@ namespace SabreTools.Library.DatFiles AltName = altName, AltTitle = altTitle, - Original = new OpenMSXOriginal() { Name = original }, + Original = new OpenMSXOriginal() { Content = original }, OpenMSXSubType = subType, OpenMSXType = msxType, Remark = remark, @@ -1265,10 +1264,7 @@ namespace SabreTools.Library.DatFiles case "devices": return "Machine.Devices"; - case "slotoptions": - case "slot options": - case "slot-options": - return "Machine.SlotOptions"; + // TODO: Add Machine.Slot case "infos": return "Machine.Infos"; diff --git a/SabreTools.Library/DatFiles/SoftwareList.cs b/SabreTools.Library/DatFiles/SoftwareList.cs index 52831977..f19291cf 100644 --- a/SabreTools.Library/DatFiles/SoftwareList.cs +++ b/SabreTools.Library/DatFiles/SoftwareList.cs @@ -191,7 +191,12 @@ namespace SabreTools.Library.DatFiles break; case "sharedfeat": - machine.SharedFeatures.Add(new SoftwareListSharedFeature(reader.GetAttribute("name"), reader.GetAttribute("value"))); + var sharedFeature = new SoftwareListSharedFeature(); + sharedFeature.Name = reader.GetAttribute("name"); + sharedFeature.Value = reader.GetAttribute("value"); + + machine.SharedFeatures.Add(sharedFeature); + reader.Read(); break; @@ -284,7 +289,12 @@ namespace SabreTools.Library.DatFiles break; case "feature": - features.Add(new SoftwareListFeature(reader.GetAttribute("name"), reader.GetAttribute("value"))); + var feature = new SoftwareListFeature(); + feature.Name = reader.GetAttribute("name"); + feature.Value = reader.GetAttribute("value"); + + features.Add(feature); + reader.Read(); break; diff --git a/SabreTools.Library/DatItems/Auxiliary.cs b/SabreTools.Library/DatItems/Auxiliary.cs index a0e20c4b..88ebab1b 100644 --- a/SabreTools.Library/DatItems/Auxiliary.cs +++ b/SabreTools.Library/DatItems/Auxiliary.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +using Newtonsoft.Json; + /// /// This holds all of the auxiliary types needed for proper parsing /// @@ -12,151 +14,248 @@ namespace SabreTools.Library.DatItems /// /// Represents one ListXML adjuster /// + [JsonObject("adjuster")] public class ListXmlAdjuster { + [JsonProperty("name")] public string Name { get; set; } - public bool? Default { get; set; } - public List Conditions { get; set; } - public ListXmlAdjuster() - { - Conditions = new List(); - } + [JsonProperty("default")] + public bool? Default { get; set; } + + [JsonProperty("conditions")] + public List Conditions { get; set; } } /// /// Represents one ListXML analog /// + [JsonObject("analog")] public class ListXmlAnalog { + [JsonProperty("mask")] public string Mask { get; set; } } /// /// Represents one ListXML chip /// + [JsonObject("chip")] public class ListXmlChip { + [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("tag")] public string Tag { get; set; } + + [JsonProperty("type")] public string Type { get; set; } // TODO: (cpu|audio) + + [JsonProperty("clock")] public string Clock { get; set; } } /// /// Represents one ListXML condition /// + [JsonObject("condition")] public class ListXmlCondition { + [JsonProperty("tag")] public string Tag { get; set; } + + [JsonProperty("mask")] public string Mask { get; set; } + + [JsonProperty("relation")] public string Relation { get; set; } // TODO: (eq|ne|gt|le|lt|ge) + + [JsonProperty("value")] public string Value { get; set; } } /// /// Represents one ListXML configuration /// + [JsonObject("configuration")] public class ListXmlConfiguration { + [JsonProperty("name")] 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(); - } + [JsonProperty("tag")] + public string Tag { get; set; } + + [JsonProperty("mask")] + public string Mask { get; set; } + + [JsonProperty("locations")] + public List Locations { get; set; } + + [JsonProperty("settings")] + public List Settings { get; set; } } /// /// Represents one ListXML conflocation /// + [JsonObject("conflocation")] public class ListXmlConfLocation { + [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("number")] public string Number { get; set; } + + [JsonProperty("inverted")] public bool? Inverted { get; set; } } /// /// Represents one ListXML confsetting /// + [JsonObject("confsetting")] public class ListXmlConfSetting { + [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("value")] public string Value { get; set; } + + [JsonProperty("default")] public bool? Default { get; set; } } /// /// Represents one ListXML control /// + [JsonObject("control")] public class ListXmlControl { + [JsonProperty("type")] public string Type { get; set; } + + [JsonProperty("player")] public string Player { get; set; } // TODO: Int32? + + [JsonProperty("buttons")] public string Buttons { get; set; } // TODO: Int32? + + [JsonProperty("regbuttons")] public string RegButtons { get; set; } // TODO: Int32? + + [JsonProperty("minimum")] public string Minimum { get; set; } // TODO: Int32? Float? + + [JsonProperty("maximum")] public string Maximum { get; set; } // TODO: Int32? Float? + + [JsonProperty("sensitivity")] public string Sensitivity { get; set; } // TODO: Int32? Float? + + [JsonProperty("keydelta")] public string KeyDelta { get; set; } // TODO: Int32? Float? + + [JsonProperty("reverse")] public bool? Reverse { get; set; } + + [JsonProperty("ways")] public string Ways { get; set; } // TODO: Int32? Float? + + [JsonProperty("ways2")] public string Ways2 { get; set; } // TODO: Int32? Float? + + [JsonProperty("ways3")] public string Ways3 { get; set; } // TODO: Int32? Float? } /// /// Represents one ListXML device /// + [JsonObject("device")] public class ListXmlDevice { + [JsonProperty("type")] 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(); - } + [JsonProperty("tag")] + public string Tag { get; set; } + + [JsonProperty("fixed_image")] + public string FixedImage { get; set; } + + [JsonProperty("mandatory")] + public string Mandatory { get; set; } // TODO: bool? + + [JsonProperty("interface")] + public string Interface { get; set; } + + [JsonProperty("instances")] + public List Instances { get; set; } + + [JsonProperty("extensions")] + public List Extensions { get; set; } } /// /// Represents one ListXML deviceref /// + [JsonObject("deviceref")] public class ListXmlDeviceReference { + [JsonProperty("name")] public string Name { get; set; } } /// /// Represents one ListXML display /// + [JsonObject("display")] public class ListXmlDisplay { + [JsonProperty("tag")] public string Tag { get; set; } + + [JsonProperty("type")] public string Type { get; set; } // TODO: (raster|vector|lcd|svg|unknown) + + [JsonProperty("rotate")] public string Rotate { get; set; } // TODO: (0|90|180|270) Int32? + + [JsonProperty("flipx")] public bool? FlipX { get; set; } + + [JsonProperty("width")] public string Width { get; set; } // TODO: Int32? + + [JsonProperty("height")] public string Height { get; set; } // TODO: Int32? + + [JsonProperty("refresh")] public string Refresh { get; set; } // TODO: Int32? Float? + + [JsonProperty("pixclock")] public string PixClock { get; set; } // TODO: Int32? Float? + + [JsonProperty("htotal")] public string HTotal { get; set; } // TODO: Int32? Float? + + [JsonProperty("hbend")] public string HBend { get; set; } // TODO: Int32? Float? + + [JsonProperty("hstart")] public string HStart { get; set; } // TODO: Int32? Float? + + [JsonProperty("vtotal")] public string VTotal { get; set; } // TODO: Int32? Float? + + [JsonProperty("vbend")] public string VBend { get; set; } // TODO: Int32? Float? + + [JsonProperty("vstart")] public string VStart { get; set; } // TODO: Int32? Float? } @@ -164,28 +263,38 @@ namespace SabreTools.Library.DatItems /// Represents one ListXML dipswitch /// /// Also used by SoftwareList + [JsonObject("dipswitch")] public class ListXmlDipSwitch { + [JsonProperty("name")] 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 ListXmlDipSwitch() - { - Locations = new List(); - Values = new List(); - } + [JsonProperty("tag")] + public string Tag { get; set; } + + [JsonProperty("tag")] + public string Mask { get; set; } + + [JsonProperty("locations")] + public List Locations { get; set; } + + [JsonProperty("values")] + public List Values { get; set; } } /// /// Represents one ListXML diplocation /// + [JsonObject("diplocation")] public class ListXmlDipLocation { + [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("number")] public string Number { get; set; } + + [JsonProperty("inverted")] public bool? Inverted { get; set; } } @@ -193,138 +302,187 @@ namespace SabreTools.Library.DatItems /// Represents one ListXML dipvalue /// /// Also used by SoftwareList + [JsonObject("dipvalue")] public class ListXmlDipValue { + [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("value")] public string Value { get; set; } + + [JsonProperty("default")] public bool? Default { get; set; } } /// /// Represents one ListXML driver /// + [JsonObject("driver")] public class ListXmlDriver { + [JsonProperty("status")] public string Status { get; set; } // TODO: (good|imperfect|preliminary) + + [JsonProperty("emulation")] public string Emulation { get; set; } // TODO: (good|imperfect|preliminary) + + [JsonProperty("cocktail")] public string Cocktail { get; set; } // TODO: bool? (good|imperfect|preliminary)? + + [JsonProperty("savestate")] public string SaveState { get; set; } // TODO: (supported|unsupported) } /// /// Represents one ListXML extension /// + [JsonObject("extension")] public class ListXmlExtension { + [JsonProperty("name")] public string Name { get; set; } } /// /// Represents one ListXML feature /// + [JsonObject("feature")] public class ListXmlFeature { + [JsonProperty("type")] public string Type { get; set; } // TODO: (protection|palette|graphics|sound|controls|keyboard|mouse|microphone|camera|disk|printer|lan|wan|timing) + + [JsonProperty("status")] public string Status { get; set; } // TODO: (unemulated|imperfect) + + [JsonProperty("overall")] public string Overall { get; set; } // TODO: (unemulated|imperfect) } /// /// Represents one ListXML info /// + [JsonObject("info")] public class ListXmlInfo { + [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("value")] public string Value { get; set; } } /// /// Represents one ListXML input /// + [JsonObject("input")] public class ListXmlInput { + [JsonProperty("service")] 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 ListXmlInput() - { - Controls = new List(); - } + [JsonProperty("tilt")] + public bool? Tilt { get; set; } + + [JsonProperty("players")] + public string Players { get; set; } // TODO: Int32? + + [JsonProperty("coins")] + public string Coins { get; set; } // TODO: Int32? + + [JsonProperty("controls")] + public List Controls { get; set; } } /// /// Represents one ListXML instance /// + [JsonObject("instance")] public class ListXmlInstance { + [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("briefname")] public string BriefName { get; set; } } /// /// Represents one ListXML port /// + [JsonObject("port")] public class ListXmlPort { + [JsonProperty("tag")] public string Tag { get; set; } - public List Analogs { get; set; } - public ListXmlPort() - { - Analogs = new List(); - } + [JsonProperty("analogs")] + public List Analogs { get; set; } } /// /// Represents one ListXML ramoption /// + [JsonObject("ramoption")] public class ListXmlRamOption { + [JsonProperty("default")] public bool? Default { get; set; } } /// /// Represents one ListXML slot /// + [JsonObject("slot")] public class ListXmlSlot { + [JsonProperty("name")] public string Name { get; set; } - public List SlotOptions { get; set; } - public ListXmlSlot() - { - SlotOptions = new List(); - } + [JsonProperty("slotoptions")] + public List SlotOptions { get; set; } } /// /// Represents one ListXML slotoption /// + [JsonObject("slotoption")] public class ListXmlSlotOption { + [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("devname")] public string DeviceName { get; set; } + + [JsonProperty("default")] public bool? Default { get; set; } } /// /// Represents one ListXML softwarelist /// + [JsonObject("softwarelist")] public class ListXmlSoftwareList { + [JsonProperty("name")] public string Name { get; set; } + + [JsonProperty("status")] public string Status { get; set; } // TODO: (original|compatible) + + [JsonProperty("filter")] public string Filter { get; set; } } /// /// Represents one ListXML sound /// + [JsonObject("sound")] public class ListXmlSound { + [JsonProperty("channels")] public string Channels { get; set; } // TODO: Int32? } @@ -335,10 +493,14 @@ namespace SabreTools.Library.DatItems /// /// Represents the OpenMSX original value /// + [JsonObject("original")] public class OpenMSXOriginal { - public string Name { get; set; } + [JsonProperty("value")] public bool? Value { get; set; } + + [JsonProperty("content")] + public string Content { get; set; } } #endregion @@ -348,16 +510,14 @@ namespace SabreTools.Library.DatItems /// /// Represents one SoftwareList shared feature object /// + [JsonObject("sharedfeat")] public class SoftwareListSharedFeature { + [JsonProperty("name")] public string Name { get; set; } - public string Value { get; set; } - public SoftwareListSharedFeature(string name, string value) - { - Name = name; - Value = value; - } + [JsonProperty("value")] + public string Value { get; set; } } #endregion @@ -371,16 +531,14 @@ namespace SabreTools.Library.DatItems /// /// Represents one SoftwareList feature object /// + [JsonObject("feature")] public class SoftwareListFeature { + [JsonProperty("name")] public string Name { get; set; } - public string Value { get; set; } - public SoftwareListFeature(string name, string value) - { - Name = name; - Value = value; - } + [JsonProperty("value")] + public string Value { get; set; } } #endregion diff --git a/SabreTools.Library/DatItems/DatItem.cs b/SabreTools.Library/DatItems/DatItem.cs index 18e34e2d..e4915602 100644 --- a/SabreTools.Library/DatItems/DatItem.cs +++ b/SabreTools.Library/DatItems/DatItem.cs @@ -276,8 +276,8 @@ namespace SabreTools.Library.DatItems // ListXML Field.SourceFile, Field.Runnable, - Field.Devices, - Field.SlotOptions, + Field.DeviceReferences, + Field.Slots, Field.Infos, // Logiqx @@ -352,7 +352,7 @@ namespace SabreTools.Library.DatItems #region OpenMSX case Field.Original: - fieldValue = Original.Name; + fieldValue = Original.Content; break; case Field.OpenMSXSubType: fieldValue = OpenMSXSubType.ToString(); @@ -442,7 +442,7 @@ namespace SabreTools.Library.DatItems #region OpenMSX if (mappings.Keys.Contains(Field.Original)) - Original = new OpenMSXOriginal() { Name = mappings[Field.Original] }; + Original = new OpenMSXOriginal() { Content = mappings[Field.Original] }; if (mappings.Keys.Contains(Field.OpenMSXSubType)) OpenMSXSubType = mappings[Field.OpenMSXSubType].AsOpenMSXSubType(); @@ -475,7 +475,12 @@ namespace SabreTools.Library.DatItems foreach (string pair in pairs) { string[] split = pair.Split('='); - Features.Add(new SoftwareListFeature(split[0], split[1])); + + var feature = new SoftwareListFeature(); + feature.Name = split[0]; + feature.Value = split[1]; + + Features.Add(feature); } } @@ -725,9 +730,9 @@ namespace SabreTools.Library.DatItems #region OpenMSX // Filter on original - if (filter.Original.MatchesPositiveSet(Original.Name) == false) + if (filter.Original.MatchesPositiveSet(Original.Content) == false) return false; - if (filter.Original.MatchesNegativeSet(Original.Name) == true) + if (filter.Original.MatchesNegativeSet(Original.Content) == true) return false; // Filter on OpenMSX subtype diff --git a/SabreTools.Library/DatItems/Enums.cs b/SabreTools.Library/DatItems/Enums.cs index 94cebf30..cabf3b91 100644 --- a/SabreTools.Library/DatItems/Enums.cs +++ b/SabreTools.Library/DatItems/Enums.cs @@ -60,8 +60,12 @@ namespace SabreTools.Library.DatItems SourceFile, Runnable, - Devices, - SlotOptions, + DeviceReferences, // TODO: Double-check DeviceReferences usage + Chips, // TODO: Implement Chips usage + Displays, // TODO: Implement Displays usage + Sounds, // TODO: Implement Sounds usage + Conditions, // TODO: Implement Conditions usage + Slots, // TODO: Fix Slots usage Infos, #endregion diff --git a/SabreTools.Library/DatItems/Machine.cs b/SabreTools.Library/DatItems/Machine.cs index 7a671db0..4e63fd13 100644 --- a/SabreTools.Library/DatItems/Machine.cs +++ b/SabreTools.Library/DatItems/Machine.cs @@ -155,12 +155,55 @@ namespace SabreTools.Library.DatItems [JsonProperty("devices")] public List DeviceReferences { get; set; } = null; + /// + /// List of associated chips + /// + [JsonProperty("chips")] + public List Chips { get; set; } = null; + + /// + /// List of associated displays + /// + [JsonProperty("displays")] + public List Displays { get; set; } = null; + + /// + /// List of associated sounds + /// + [JsonProperty("sounds")] + public List Sounds { get; set; } = null; + + /// + /// List of associated conditions + /// + [JsonProperty("conditions")] + public List Conditions { get; set; } = null; + + /// + /// List of associated inputs + /// + [JsonProperty("inputs")] + public List Inputs { get; set; } = null; + + /// + /// List of associated dipswitches + /// + /// Also in SoftwareList + /// TODO: Order ListXML and SoftwareList outputs by area names + [JsonProperty("dipswitches")] + public List DipSwitches { get; set; } = null; + + /// + /// List of associated configurations + /// + [JsonProperty("configurations")] + public List Configurations { get; set; } = null; + /// /// List of slot options /// - /// TODO: Use ListXmlSlot for this... - [JsonProperty("slotoptions")] - public List SlotOptions { get; set; } = null; + [JsonProperty("slots")] + public List Slots { get; set; } = null; /// /// List of info items @@ -281,15 +324,6 @@ namespace SabreTools.Library.DatItems [JsonProperty("sharedfeat")] public List SharedFeatures { get; set; } = null; - /// - /// 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; - #endregion #endregion @@ -380,11 +414,11 @@ namespace SabreTools.Library.DatItems case Field.Runnable: fieldValue = Runnable.ToString(); break; - case Field.Devices: + case Field.DeviceReferences: fieldValue = string.Join(";", DeviceReferences ?? new List()); break; - case Field.SlotOptions: - fieldValue = string.Join(";", SlotOptions ?? new List()); + case Field.Slots: + fieldValue = string.Join(";", Slots ?? new List()); break; case Field.Infos: fieldValue = string.Join(";", (Infos ?? new List()).Select(i => $"{i.Name}={i.Value}")); @@ -551,23 +585,16 @@ namespace SabreTools.Library.DatItems if (mappings.Keys.Contains(Field.Runnable)) Runnable = mappings[Field.Runnable].AsRunnable(); - if (mappings.Keys.Contains(Field.Devices)) + if (mappings.Keys.Contains(Field.DeviceReferences)) { if (DeviceReferences == null) DeviceReferences = new List(); - var devices = mappings[Field.Devices].Split(';').Select(d => new ListXmlDeviceReference() { Name = d, }); + var devices = mappings[Field.DeviceReferences].Split(';').Select(d => new ListXmlDeviceReference() { Name = d, }); DeviceReferences.AddRange(devices); } - if (mappings.Keys.Contains(Field.SlotOptions)) - { - if (SlotOptions == null) - SlotOptions = new List(); - - string[] slotOptions = mappings[Field.SlotOptions].Split(';'); - SlotOptions.AddRange(slotOptions); - } + // TODO: Add Field.Slot if (mappings.Keys.Contains(Field.Infos)) { @@ -657,7 +684,12 @@ namespace SabreTools.Library.DatItems foreach (string pair in pairs) { string[] split = pair.Split('='); - SharedFeatures.Add(new SoftwareListSharedFeature(split[0], split[1])); + + var sharedFeature = new SoftwareListSharedFeature(); + sharedFeature.Name = split[0]; + sharedFeature.Value = split[1]; + + SharedFeatures.Add(sharedFeature); } } @@ -738,7 +770,7 @@ namespace SabreTools.Library.DatItems SourceFile = this.SourceFile, Runnable = this.Runnable, DeviceReferences = this.DeviceReferences, - SlotOptions = this.SlotOptions, + Slots = this.Slots, Infos = this.Infos, MachineType = this.MachineType, @@ -946,20 +978,7 @@ namespace SabreTools.Library.DatItems return false; } - // Filter on slot options - if (SlotOptions != null && SlotOptions.Any()) - { - bool anyPositiveSlotOption = false; - bool anyNegativeSlotOption = false; - foreach (string slotOption in SlotOptions) - { - anyPositiveSlotOption |= filter.SlotOptions.MatchesPositiveSet(slotOption) != false; - anyNegativeSlotOption |= filter.SlotOptions.MatchesNegativeSet(slotOption) == false; - } - - if (!anyPositiveSlotOption || anyNegativeSlotOption) - return false; - } + // TODO: Add Slot filter // Filter on machine type if (filter.MachineTypes.MatchesPositive(MachineType.NULL, MachineType) == false) @@ -1152,11 +1171,11 @@ namespace SabreTools.Library.DatItems if (fields.Contains(Field.Runnable)) Runnable = Runnable.NULL; - if (fields.Contains(Field.Devices)) + if (fields.Contains(Field.DeviceReferences)) DeviceReferences = null; - if (fields.Contains(Field.SlotOptions)) - SlotOptions = null; + if (fields.Contains(Field.Slots)) + Slots = null; if (fields.Contains(Field.Infos)) Infos = null; @@ -1316,11 +1335,11 @@ namespace SabreTools.Library.DatItems if (fields.Contains(Field.Runnable)) Runnable = machine.Runnable; - if (fields.Contains(Field.Devices)) + if (fields.Contains(Field.DeviceReferences)) DeviceReferences = machine.DeviceReferences; - if (fields.Contains(Field.SlotOptions)) - SlotOptions = machine.SlotOptions; + if (fields.Contains(Field.Slots)) + Slots = machine.Slots; if (fields.Contains(Field.Infos)) Infos = machine.Infos; diff --git a/SabreTools.Library/Filtering/Filter.cs b/SabreTools.Library/Filtering/Filter.cs index 216b9dbd..e1a492db 100644 --- a/SabreTools.Library/Filtering/Filter.cs +++ b/SabreTools.Library/Filtering/Filter.cs @@ -709,14 +709,14 @@ namespace SabreTools.Library.Filtering Runnables.Positive |= value.AsRunnable(); break; - case Field.Devices: + case Field.DeviceReferences: if (negate) Devices.NegativeSet.Add(value); else Devices.PositiveSet.Add(value); break; - case Field.SlotOptions: + case Field.Slots: if (negate) SlotOptions.NegativeSet.Add(value); else diff --git a/SabreTools.Library/IO/XmlTextWriterExtensions.cs b/SabreTools.Library/IO/XmlTextWriterExtensions.cs new file mode 100644 index 00000000..12c0ddf9 --- /dev/null +++ b/SabreTools.Library/IO/XmlTextWriterExtensions.cs @@ -0,0 +1,23 @@ +using System.Xml; + +namespace SabreTools.Library.IO +{ + /// + /// Additional methods for XmlTextWriter + /// + public static class XmlTextWriterExtensions + { + /// + /// Force writing separate open and start tags, even for empty elements + /// + /// XmlTextWriter to write out with + /// Name of the element + /// Value to write in the element + public static void WriteFullElementString(this XmlTextWriter xmlTextWriter, string localName, string value) + { + xmlTextWriter.WriteStartElement(localName); + xmlTextWriter.WriteRaw(value); + xmlTextWriter.WriteFullEndElement(); + } + } +} diff --git a/SabreTools.Library/Tools/Converters.cs b/SabreTools.Library/Tools/Converters.cs index d8d03a99..90d6f301 100644 --- a/SabreTools.Library/Tools/Converters.cs +++ b/SabreTools.Library/Tools/Converters.cs @@ -232,12 +232,12 @@ namespace SabreTools.Library.Tools return Field.Runnable; case "devices": - return Field.Devices; + return Field.DeviceReferences; case "slotoptions": case "slot options": case "slot-options": - return Field.SlotOptions; + return Field.Slots; case "infos": return Field.Infos;