diff --git a/SabreTools.Core/Enums.cs b/SabreTools.Core/Enums.cs
index d203eea3..f3ee2937 100644
--- a/SabreTools.Core/Enums.cs
+++ b/SabreTools.Core/Enums.cs
@@ -494,6 +494,9 @@ namespace SabreTools.Core
[Mapping("location")]
Location,
+ [Mapping("original")]
+ Original,
+
[Mapping("part")]
Part,
diff --git a/SabreTools.DatItems/DatItemDict.cs b/SabreTools.DatItems/DatItemDict.cs
deleted file mode 100644
index 1d9662d0..00000000
--- a/SabreTools.DatItems/DatItemDict.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System.Collections.Generic;
-
-namespace SabreTools.DatItems
-{
- ///
- /// Format-agnostic representation of item data
- ///
- public class DatItemDict : Dictionary
- {
- #region Common Keys
-
- public const string NameKey = "name";
-
- #endregion
-
- public string? Name
- {
- get => ContainsKey(NameKey) ? this[NameKey] as string : null;
- set => this[NameKey] = value;
- }
- }
-}
\ No newline at end of file
diff --git a/SabreTools.Models/ArchiveDotOrg/File.cs b/SabreTools.Models/ArchiveDotOrg/File.cs
index eb9ee31c..465dd9c6 100644
--- a/SabreTools.Models/ArchiveDotOrg/File.cs
+++ b/SabreTools.Models/ArchiveDotOrg/File.cs
@@ -123,12 +123,12 @@ namespace SabreTools.Models.ArchiveDotOrg
[XmlElement("ocr_detected_script_conf")]
public string? TesseractOCRDetectedScriptConf { get; set; }
- [XmlElement("ocr_parameters")]
- public string? TesseractOCRParameters { get; set; }
-
[XmlElement("ocr_module_version")]
public string? TesseractOCRModuleVersion { get; set; }
+ [XmlElement("ocr_parameters")]
+ public string? TesseractOCRParameters { get; set; }
+
[XmlElement("pdf_module_version")]
public string? PDFModuleVersion { get; set; }
diff --git a/SabreTools.Models/ClrMamePro/DipSwitch.cs b/SabreTools.Models/ClrMamePro/DipSwitch.cs
index 3d3dcaa0..46c5f09e 100644
--- a/SabreTools.Models/ClrMamePro/DipSwitch.cs
+++ b/SabreTools.Models/ClrMamePro/DipSwitch.cs
@@ -9,7 +9,7 @@ namespace SabreTools.Models.ClrMamePro
/// entry
public string[]? Entry { get; set; }
- /// default
+ /// default, (yes|no) "no"
public string? Default { get; set; }
#region DO NOT USE IN PRODUCTION
diff --git a/SabreTools.Models/ClrMamePro/Input.cs b/SabreTools.Models/ClrMamePro/Input.cs
index b0070a89..76c416bc 100644
--- a/SabreTools.Models/ClrMamePro/Input.cs
+++ b/SabreTools.Models/ClrMamePro/Input.cs
@@ -3,22 +3,22 @@ namespace SabreTools.Models.ClrMamePro
/// input
public class Input
{
- /// players, Numeric?
+ /// players, Numeric?/remarks>
public string Players { get; set; }
/// control
public string? Control { get; set; }
- /// buttons, Numeric?
+ /// buttons, Numeric
public string Buttons { get; set; }
- /// coins, Numeric?
+ /// coins, Numeric
public string? Coins { get; set; }
- /// tilt, Boolean?
+ /// tilt, (yes|no) "no"
public string? Tilt { get; set; }
- /// service, Boolean?
+ /// service, (yes|no) "no"
public string? Service { get; set; }
#region DO NOT USE IN PRODUCTION
diff --git a/SabreTools.Models/ClrMamePro/Rom.cs b/SabreTools.Models/ClrMamePro/Rom.cs
index f71ff638..250da8c2 100644
--- a/SabreTools.Models/ClrMamePro/Rom.cs
+++ b/SabreTools.Models/ClrMamePro/Rom.cs
@@ -62,7 +62,7 @@ namespace SabreTools.Models.ClrMamePro
public string? Region { get; set; }
/// offs; Appears after Flags
- public string? Offs { get; set; } // TODO: Is this "Offset" elsewhere?
+ public string? Offs { get; set; }
#endregion
diff --git a/SabreTools.Models/Internal/Adjuster.cs b/SabreTools.Models/Internal/Adjuster.cs
new file mode 100644
index 00000000..e48aa708
--- /dev/null
+++ b/SabreTools.Models/Internal/Adjuster.cs
@@ -0,0 +1,24 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("adjuster"), XmlRoot("adjuster")]
+ public class Adjuster : DatItem
+ {
+ #region Keys
+
+ // Condition
+ public const string ConditionKey = "condition";
+
+ /// bool
+ public const string DefaultKey = "default";
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public Adjuster() => Type = ItemType.Adjuster;
+ }
+}
diff --git a/SabreTools.Models/Internal/Analog.cs b/SabreTools.Models/Internal/Analog.cs
new file mode 100644
index 00000000..5aa36d53
--- /dev/null
+++ b/SabreTools.Models/Internal/Analog.cs
@@ -0,0 +1,18 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("analog"), XmlRoot("analog")]
+ public class Analog : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string MaskKey = "mask";
+
+ #endregion
+
+ public Analog() => Type = ItemType.Analog;
+ }
+}
diff --git a/SabreTools.Models/Internal/Archive.cs b/SabreTools.Models/Internal/Archive.cs
new file mode 100644
index 00000000..4fee4514
--- /dev/null
+++ b/SabreTools.Models/Internal/Archive.cs
@@ -0,0 +1,18 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("archive"), XmlRoot("archive")]
+ public class Archive : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public Archive() => Type = ItemType.Archive;
+ }
+}
diff --git a/SabreTools.Models/Internal/BiosSet.cs b/SabreTools.Models/Internal/BiosSet.cs
new file mode 100644
index 00000000..f5a4d47f
--- /dev/null
+++ b/SabreTools.Models/Internal/BiosSet.cs
@@ -0,0 +1,24 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("biosset"), XmlRoot("biosset")]
+ public class BiosSet : DatItem
+ {
+ #region Keys
+
+ /// bool
+ public const string DefaultKey = "default";
+
+ /// string
+ public const string DescriptionKey = "description";
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public BiosSet() => Type = ItemType.BiosSet;
+ }
+}
diff --git a/SabreTools.Models/Internal/Blank.cs b/SabreTools.Models/Internal/Blank.cs
new file mode 100644
index 00000000..f7af0f02
--- /dev/null
+++ b/SabreTools.Models/Internal/Blank.cs
@@ -0,0 +1,11 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("blank"), XmlRoot("blank")]
+ public class Blank : DatItem
+ {
+ public Blank() => Type = ItemType.Blank;
+ }
+}
diff --git a/SabreTools.Models/Internal/Chip.cs b/SabreTools.Models/Internal/Chip.cs
new file mode 100644
index 00000000..519e5f04
--- /dev/null
+++ b/SabreTools.Models/Internal/Chip.cs
@@ -0,0 +1,33 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("chip"), XmlRoot("chip")]
+ public class Chip : DatItem
+ {
+ #region Keys
+
+ /// long
+ public const string ClockKey = "clock";
+
+ /// string
+ public const string FlagsKey = "flags";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// (yes|no) "no"
+ public const string SoundOnlyKey = "soundonly";
+
+ /// string
+ public const string TagKey = "tag";
+
+ /// (cpu|audio)
+ public const string ChipTypeKey = "type";
+
+ #endregion
+
+ public Chip() => Type = ItemType.Chip;
+ }
+}
diff --git a/SabreTools.Models/Internal/Condition.cs b/SabreTools.Models/Internal/Condition.cs
new file mode 100644
index 00000000..17210c01
--- /dev/null
+++ b/SabreTools.Models/Internal/Condition.cs
@@ -0,0 +1,27 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("condition"), XmlRoot("condition")]
+ public class Condition : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string ValueKey = "clock";
+
+ /// string
+ public const string MaskKey = "mask";
+
+ /// (eq|ne|gt|le|lt|ge)
+ public const string RelationKey = "relation";
+
+ /// string
+ public const string TagKey = "tag";
+
+ #endregion
+
+ public Condition() => Type = ItemType.Condition;
+ }
+}
diff --git a/SabreTools.Models/Internal/ConfLocation.cs b/SabreTools.Models/Internal/ConfLocation.cs
new file mode 100644
index 00000000..d38a19ad
--- /dev/null
+++ b/SabreTools.Models/Internal/ConfLocation.cs
@@ -0,0 +1,24 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("conflocation"), XmlRoot("conflocation")]
+ public class ConfLocation : DatItem
+ {
+ #region Keys
+
+ /// (yes|no) "no"
+ public const string InvertedKey = "inverted";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string, possibly long
+ public const string NumberKey = "number";
+
+ #endregion
+
+ public ConfLocation() => Type = ItemType.ConfLocation;
+ }
+}
diff --git a/SabreTools.Models/Internal/ConfSetting.cs b/SabreTools.Models/Internal/ConfSetting.cs
new file mode 100644
index 00000000..6f24d52d
--- /dev/null
+++ b/SabreTools.Models/Internal/ConfSetting.cs
@@ -0,0 +1,27 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("confsetting"), XmlRoot("confsetting")]
+ public class ConfSetting : DatItem
+ {
+ #region Keys
+
+ /// Condition
+ public const string ConditionKey = "condition";
+
+ /// (yes|no) "no"
+ public const string DefaultKey = "default";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string
+ public const string ValueKey = "value";
+
+ #endregion
+
+ public ConfSetting() => Type = ItemType.ConfSetting;
+ }
+}
diff --git a/SabreTools.Models/Internal/Configuration.cs b/SabreTools.Models/Internal/Configuration.cs
new file mode 100644
index 00000000..be432faf
--- /dev/null
+++ b/SabreTools.Models/Internal/Configuration.cs
@@ -0,0 +1,33 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("configuration"), XmlRoot("configuration")]
+ public class Configuration : DatItem
+ {
+ #region Keys
+
+ /// Condition
+ public const string ConditionKey = "condition";
+
+ /// ConfLocation[]
+ public const string ConfLocationKey = "conflocation";
+
+ /// ConfSetting[]
+ public const string ConfSettingKey = "confsetting";
+
+ /// string
+ public const string MaskKey = "mask";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string
+ public const string TagKey = "tag";
+
+ #endregion
+
+ public Configuration() => Type = ItemType.Configuration;
+ }
+}
diff --git a/SabreTools.Models/Internal/Control.cs b/SabreTools.Models/Internal/Control.cs
new file mode 100644
index 00000000..1e2bcb87
--- /dev/null
+++ b/SabreTools.Models/Internal/Control.cs
@@ -0,0 +1,51 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("control"), XmlRoot("control")]
+ public class Control : DatItem
+ {
+ #region Keys
+
+ /// long
+ public const string ButtonsKey = "buttons";
+
+ /// long
+ public const string KeyDeltaKey = "keydelta";
+
+ /// long
+ public const string MaximumKey = "maximum";
+
+ /// long
+ public const string MinimumKey = "minimum";
+
+ /// long
+ public const string PlayerKey = "player";
+
+ /// long
+ public const string ReqButtonsKey = "reqbuttons";
+
+ /// (yes|no) "no"
+ public const string ReverseKey = "reverse";
+
+ /// long
+ public const string Sensitivity = "sensitivity";
+
+ /// (joy|stick|paddle|pedal|lightgun|positional|dial|trackball|mouse|only_buttons|keypad|keyboard|mahjong|hanafuda|gambling)
+ public const string ControlTypeKey = "type";
+
+ /// string, possibly long
+ public const string WaysKey = "ways";
+
+ /// string, possibly long
+ public const string Ways2Key = "ways2";
+
+ /// string, possibly long
+ public const string Ways3Key = "ways3";
+
+ #endregion
+
+ public Control() => Type = ItemType.Control;
+ }
+}
diff --git a/SabreTools.Models/Internal/DatItem.cs b/SabreTools.Models/Internal/DatItem.cs
new file mode 100644
index 00000000..ea6076ec
--- /dev/null
+++ b/SabreTools.Models/Internal/DatItem.cs
@@ -0,0 +1,80 @@
+using System.Collections.Generic;
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ ///
+ /// Format-agnostic representation of item data
+ ///
+ public class DatItem : Dictionary
+ {
+ #region Common Keys
+
+ public const string TypeKey = "_type";
+
+ #endregion
+
+ ///
+ /// Quick accessor to item type, if it exists
+ ///
+ [JsonProperty("itemtype", DefaultValueHandling = DefaultValueHandling.Ignore), XmlElement("itemtype")]
+ public ItemType? Type
+ {
+ get => ContainsKey(TypeKey) ? this[TypeKey] as ItemType? : null;
+ set => this[TypeKey] = value;
+ }
+
+ #region Reading Helpers
+
+ ///
+ /// Read a key as a bool, returning null on error
+ ///
+ public bool? ReadBool(string key)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ return null;
+ if (!ContainsKey(key))
+ return null;
+ return this[key] as bool?;
+ }
+
+ ///
+ /// Read a key as a double, returning null on error
+ ///
+ public double? ReadDouble(string key)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ return null;
+ if (!ContainsKey(key))
+ return null;
+ return this[key] as double?;
+ }
+
+ ///
+ /// Read a key as a long, returning null on error
+ ///
+ public long? ReadLong(string key)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ return null;
+ if (!ContainsKey(key))
+ return null;
+ return this[key] as long?;
+ }
+
+ ///
+ /// Read a key as a string, returning null on error
+ ///
+ public string? ReadString(string key)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ return null;
+ if (!ContainsKey(key))
+ return null;
+ return this[key] as string;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/SabreTools.Models/Internal/DataArea.cs b/SabreTools.Models/Internal/DataArea.cs
new file mode 100644
index 00000000..3d592189
--- /dev/null
+++ b/SabreTools.Models/Internal/DataArea.cs
@@ -0,0 +1,30 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("dataarea"), XmlRoot("dataarea")]
+ public class DataArea : DatItem
+ {
+ #region Keys
+
+ /// (big|little) "little"
+ public const string EndiannessKey = "endianness";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// Rom[]
+ public const string RomKey = "rom";
+
+ /// long
+ public const string SizeKey = "size";
+
+ /// (8|16|32|64) "8"
+ public const string WidthKey = "width";
+
+ #endregion
+
+ public DataArea() => Type = ItemType.DataArea;
+ }
+}
diff --git a/SabreTools.Models/Internal/Device.cs b/SabreTools.Models/Internal/Device.cs
new file mode 100644
index 00000000..abfdec1b
--- /dev/null
+++ b/SabreTools.Models/Internal/Device.cs
@@ -0,0 +1,36 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("device"), XmlRoot("device")]
+ public class Device : DatItem
+ {
+ #region Keys
+
+ /// Extension[]
+ public const string ExtensionKey = "extension";
+
+ /// string
+ public const string FixedImageKey = "fixed_image";
+
+ /// Instance
+ public const string InstanceKey = "instance";
+
+ /// string
+ public const string InterfaceKey = "interface";
+
+ /// (0|1) "0"
+ public const string MandatoryKey = "mandatory";
+
+ /// string
+ public const string TagKey = "tag";
+
+ /// (unknown|cartridge|floppydisk|harddisk|cylinder|cassette|punchcard|punchtape|printout|serial|parallel|snapshot|quickload|memcard|cdrom|magtape|romimage|midiin|midiout|picture|vidfile)
+ public const string DeviceTypeKey = "type";
+
+ #endregion
+
+ public Device() => Type = ItemType.Device;
+ }
+}
diff --git a/SabreTools.Models/Internal/DeviceRef.cs b/SabreTools.Models/Internal/DeviceRef.cs
new file mode 100644
index 00000000..22a1c281
--- /dev/null
+++ b/SabreTools.Models/Internal/DeviceRef.cs
@@ -0,0 +1,18 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("device_ref"), XmlRoot("device_ref")]
+ public class DeviceRef : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public DeviceRef() => Type = ItemType.DeviceRef;
+ }
+}
diff --git a/SabreTools.Models/Internal/DipLocation.cs b/SabreTools.Models/Internal/DipLocation.cs
new file mode 100644
index 00000000..f1f5bb73
--- /dev/null
+++ b/SabreTools.Models/Internal/DipLocation.cs
@@ -0,0 +1,24 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("diplocation"), XmlRoot("diplocation")]
+ public class DipLocation : DatItem
+ {
+ #region Keys
+
+ /// (yes|no) "no"
+ public const string InvertedKey = "inverted";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string, possibly long
+ public const string NumberKey = "number";
+
+ #endregion
+
+ public DipLocation() => Type = ItemType.DipLocation;
+ }
+}
diff --git a/SabreTools.Models/Internal/DipSwitch.cs b/SabreTools.Models/Internal/DipSwitch.cs
new file mode 100644
index 00000000..9bad17b3
--- /dev/null
+++ b/SabreTools.Models/Internal/DipSwitch.cs
@@ -0,0 +1,39 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("dipswitch"), XmlRoot("dipswitch")]
+ public class DipSwitch : DatItem
+ {
+ #region Keys
+
+ /// Condition
+ public const string ConditionKey = "condition";
+
+ /// (yes|no) "no"
+ public const string DefaultKey = "default";
+
+ /// DipLocation[]
+ public const string DipLocationKey = "diplocation";
+
+ /// DipValue[]
+ public const string DipValueKey = "dipvalue";
+
+ /// string[]
+ public const string EntryKey = "entry";
+
+ /// string
+ public const string MaskKey = "mask";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string
+ public const string TagKey = "tag";
+
+ #endregion
+
+ public DipSwitch() => Type = ItemType.DipSwitch;
+ }
+}
diff --git a/SabreTools.Models/Internal/DipValue.cs b/SabreTools.Models/Internal/DipValue.cs
new file mode 100644
index 00000000..a0b75459
--- /dev/null
+++ b/SabreTools.Models/Internal/DipValue.cs
@@ -0,0 +1,27 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("dipvalue"), XmlRoot("dipvalue")]
+ public class DipValue : DatItem
+ {
+ #region Keys
+
+ /// Condition
+ public const string ConditionKey = "condition";
+
+ /// (yes|no) "no"
+ public const string DefaultKey = "default";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string
+ public const string ValueKey = "value";
+
+ #endregion
+
+ public DipValue() => Type = ItemType.DipValue;
+ }
+}
diff --git a/SabreTools.Models/Internal/Disk.cs b/SabreTools.Models/Internal/Disk.cs
new file mode 100644
index 00000000..bd758b9b
--- /dev/null
+++ b/SabreTools.Models/Internal/Disk.cs
@@ -0,0 +1,45 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("disk"), XmlRoot(elementName: "disk")]
+ public class Disk : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string FlagsKey = "flags";
+
+ /// string, possibly long
+ public const string IndexKey = "index";
+
+ /// string
+ public const string MD5Key = "md5";
+
+ /// string
+ public const string MergeKey = "merge";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// (yes|no) "no"
+ public const string OptionalKey = "optional";
+
+ /// string
+ public const string RegionKey = "region";
+
+ /// string
+ public const string SHA1Key = "sha1";
+
+ /// (baddump|nodump|good|verified) "good"
+ public const string StatusKey = "status";
+
+ /// (yes|no) "no"
+ public const string WritableKey = "writable";
+
+ #endregion
+
+ public Disk() => Type = ItemType.Disk;
+ }
+}
diff --git a/SabreTools.Models/Internal/DiskArea.cs b/SabreTools.Models/Internal/DiskArea.cs
new file mode 100644
index 00000000..d8f7f40c
--- /dev/null
+++ b/SabreTools.Models/Internal/DiskArea.cs
@@ -0,0 +1,21 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("diskarea"), XmlRoot("diskarea")]
+ public class DiskArea : DatItem
+ {
+ #region Keys
+
+ /// Disk[]
+ public const string DiskKey = "disk";
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public DiskArea() => Type = ItemType.DiskArea;
+ }
+}
diff --git a/SabreTools.Models/Internal/Display.cs b/SabreTools.Models/Internal/Display.cs
new file mode 100644
index 00000000..79d23489
--- /dev/null
+++ b/SabreTools.Models/Internal/Display.cs
@@ -0,0 +1,57 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("display"), XmlRoot("display")]
+ public class Display : DatItem
+ {
+ #region Keys
+
+ /// (yes|no) "no"
+ public const string FlipXKey = "flipx";
+
+ /// long
+ public const string HBEndKey = "hbend";
+
+ /// long
+ public const string HBStart = "hbstart";
+
+ /// long
+ public const string HeightKey = "height";
+
+ /// long
+ public const string HTotalKey = "htotal";
+
+ /// long
+ public const string PixClockKey = "pixclock";
+
+ /// double
+ public const string RefreshKey = "refresh";
+
+ /// (0|90|180|270)
+ public const string RotateKey = "rotate";
+
+ /// string
+ public const string TagKey = "tag";
+
+ /// (raster|vector|lcd|svg|unknown)
+ public const string DisplayTypeKey = "type";
+
+ /// long
+ public const string VBEndKey = "vbend";
+
+ /// long
+ public const string VBStartKey = "vbstart";
+
+ /// long
+ public const string VTotalKey = "vtotal";
+
+ /// long
+ public const string WidthKey = "width";
+
+ #endregion
+
+ public Display() => Type = ItemType.Display;
+ }
+}
diff --git a/SabreTools.Models/Internal/Driver.cs b/SabreTools.Models/Internal/Driver.cs
new file mode 100644
index 00000000..9916b930
--- /dev/null
+++ b/SabreTools.Models/Internal/Driver.cs
@@ -0,0 +1,51 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("driver"), XmlRoot("driver")]
+ public class Driver : DatItem
+ {
+ #region Keys
+
+ /// (plain|dirty)
+ public const string BlitKey = "blit";
+
+ /// (good|imperfect|preliminary)
+ public const string CocktailKey = "cocktail";
+
+ /// (good|imperfect|preliminary)
+ public const string ColorKey = "color";
+
+ /// (good|imperfect|preliminary)
+ public const string EmulationKey = "emulation";
+
+ /// (yes|no) "no"
+ public const string IncompleteKey = "incomplete";
+
+ /// (yes|no) "no"
+ public const string NoSoundHardwareKey = "nosoundhardware";
+
+ /// string, possibly long
+ public const string PaletteSizeKey = "palettesize";
+
+ /// (yes|no) "no"
+ public const string RequiresArtworkKey = "requiresartwork";
+
+ /// (supported|unsupported)
+ public const string SaveStateKey = "savestate";
+
+ /// (good|imperfect|preliminary)
+ public const string SoundKey = "sound";
+
+ /// (good|imperfect|preliminary|test)
+ public const string StatusKey = "status";
+
+ /// (yes|no) "no"
+ public const string UnofficialKey = "unofficial";
+
+ #endregion
+
+ public Driver() => Type = ItemType.Driver;
+ }
+}
diff --git a/SabreTools.Models/Internal/Dump.cs b/SabreTools.Models/Internal/Dump.cs
new file mode 100644
index 00000000..12bd685c
--- /dev/null
+++ b/SabreTools.Models/Internal/Dump.cs
@@ -0,0 +1,27 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("dump"), XmlRoot("dump")]
+ public class Dump : DatItem
+ {
+ #region Keys
+
+ /// Rom
+ public const string MegaRomKey = "megarom";
+
+ /// Original
+ public const string OriginalKey = "original";
+
+ /// Rom
+ public const string RomKey = "rom";
+
+ /// Rom
+ public const string SCCPlusCartKey = "sccpluscart";
+
+ #endregion
+
+ public Dump() => Type = ItemType.Dump;
+ }
+}
diff --git a/SabreTools.Models/Internal/Extension.cs b/SabreTools.Models/Internal/Extension.cs
new file mode 100644
index 00000000..1d84ca6e
--- /dev/null
+++ b/SabreTools.Models/Internal/Extension.cs
@@ -0,0 +1,18 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("extension"), XmlRoot("extension")]
+ public class Extension : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public Extension() => Type = ItemType.Extension;
+ }
+}
diff --git a/SabreTools.Models/Internal/Feature.cs b/SabreTools.Models/Internal/Feature.cs
new file mode 100644
index 00000000..9bcf9799
--- /dev/null
+++ b/SabreTools.Models/Internal/Feature.cs
@@ -0,0 +1,30 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("feature"), XmlRoot("feature")]
+ public class Feature : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string NameKey = "name";
+
+ /// (unemulated|imperfect)
+ public const string OverallKey = "overall";
+
+ /// (unemulated|imperfect)
+ public const string StatusKey = "status";
+
+ /// (protection|timing|graphics|palette|sound|capture|camera|microphone|controls|keyboard|mouse|media|disk|printer|tape|punch|drum|rom|comms|lan|wan)
+ public const string FeatureTypeKey = "type";
+
+ /// string
+ public const string ValueKey = "value";
+
+ #endregion
+
+ public Feature() => Type = ItemType.Feature;
+ }
+}
diff --git a/SabreTools.Models/Internal/Info.cs b/SabreTools.Models/Internal/Info.cs
new file mode 100644
index 00000000..ae99dd1d
--- /dev/null
+++ b/SabreTools.Models/Internal/Info.cs
@@ -0,0 +1,21 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("info"), XmlRoot("info")]
+ public class Info : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string
+ public const string ValueKey = "value";
+
+ #endregion
+
+ public Info() => Type = ItemType.Info;
+ }
+}
diff --git a/SabreTools.Models/Internal/Input.cs b/SabreTools.Models/Internal/Input.cs
new file mode 100644
index 00000000..3fef021e
--- /dev/null
+++ b/SabreTools.Models/Internal/Input.cs
@@ -0,0 +1,33 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("input"), XmlRoot("input")]
+ public class Input : DatItem
+ {
+ #region Keys
+
+ /// long
+ public const string ButtonsKey = "buttons";
+
+ /// long
+ public const string CoinsKey = "coins";
+
+ /// string / Control[]
+ public const string ControlKey = "control";
+
+ /// long
+ public const string PlayersKey = "players";
+
+ /// (yes|no) "no"
+ public const string ServiceKey = "service";
+
+ /// (yes|no) "no"
+ public const string TiltKey = "tilt";
+
+ #endregion
+
+ public Input() => Type = ItemType.Input;
+ }
+}
diff --git a/SabreTools.Models/Internal/Instance.cs b/SabreTools.Models/Internal/Instance.cs
new file mode 100644
index 00000000..73433a80
--- /dev/null
+++ b/SabreTools.Models/Internal/Instance.cs
@@ -0,0 +1,21 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("instance"), XmlRoot("instance")]
+ public class Instance : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string BriefNameKey = "briefname";
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public Instance() => Type = ItemType.Instance;
+ }
+}
diff --git a/SabreTools.Models/Internal/ItemType.cs b/SabreTools.Models/Internal/ItemType.cs
new file mode 100644
index 00000000..581594ae
--- /dev/null
+++ b/SabreTools.Models/Internal/ItemType.cs
@@ -0,0 +1,60 @@
+namespace SabreTools.Models.Internal
+{
+ ///
+ /// Determine what type of file an item is
+ ///
+ public enum ItemType
+ {
+ ///
+ /// This is a fake flag that is used for filter only
+ ///
+ NULL = 0,
+
+ Adjuster,
+ Analog,
+ Archive,
+ BiosSet,
+ Chip,
+ Condition,
+ Configuration,
+ ConfLocation,
+ ConfSetting,
+ Control,
+ DataArea,
+ Device,
+ DeviceRef,
+ DipLocation,
+ DipSwitch,
+ DipValue,
+ Disk,
+ DiskArea,
+ Display,
+ Driver,
+ Dump,
+ Extension,
+ Feature,
+ Info,
+ Input,
+ Instance,
+ Media,
+ Original,
+ Part,
+ Port,
+ RamOption,
+ Release,
+ Rom,
+ Sample,
+ SharedFeat,
+ Slot,
+ SlotOption,
+ Software,
+ SoftwareList,
+ Sound,
+ Video,
+
+ ///
+ /// This is not a real type, only used internally
+ ///
+ Blank = int.MaxValue,
+ }
+}
\ No newline at end of file
diff --git a/SabreTools.Models/Internal/Media.cs b/SabreTools.Models/Internal/Media.cs
new file mode 100644
index 00000000..e05d01c6
--- /dev/null
+++ b/SabreTools.Models/Internal/Media.cs
@@ -0,0 +1,30 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("media"), XmlRoot("media")]
+ public class Media : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string MD5Key = "md5";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string
+ public const string SHA1Key = "sha1";
+
+ /// string
+ public const string SHA256Key = "sha256";
+
+ /// string
+ public const string SpamSumKey = "spamsum";
+
+ #endregion
+
+ public Media() => Type = ItemType.Media;
+ }
+}
diff --git a/SabreTools.Models/Internal/Original.cs b/SabreTools.Models/Internal/Original.cs
new file mode 100644
index 00000000..37146565
--- /dev/null
+++ b/SabreTools.Models/Internal/Original.cs
@@ -0,0 +1,21 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("original"), XmlRoot("original")]
+ public class Original : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string ContentKey = "content";
+
+ /// bool
+ public const string ValueKey = "value";
+
+ #endregion
+
+ public Original() => Type = ItemType.Original;
+ }
+}
diff --git a/SabreTools.Models/Internal/Part.cs b/SabreTools.Models/Internal/Part.cs
new file mode 100644
index 00000000..cb9f7279
--- /dev/null
+++ b/SabreTools.Models/Internal/Part.cs
@@ -0,0 +1,33 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("part"), XmlRoot("part")]
+ public class Part : DatItem
+ {
+ #region Keys
+
+ /// DataArea[]
+ public const string DataAreaKey = "dataarea";
+
+ /// DiskArea[]
+ public const string DiskAreaKey = "diskarea";
+
+ /// DipSwitch[]
+ public const string DipSwitchKey = "dipswitch";
+
+ /// Feature[]
+ public const string FeatureKey = "feature";
+
+ /// string
+ public const string InterfaceKey = "interface";
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public Part() => Type = ItemType.Part;
+ }
+}
diff --git a/SabreTools.Models/Internal/Port.cs b/SabreTools.Models/Internal/Port.cs
new file mode 100644
index 00000000..2e9275e5
--- /dev/null
+++ b/SabreTools.Models/Internal/Port.cs
@@ -0,0 +1,21 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("port"), XmlRoot("port")]
+ public class Port : DatItem
+ {
+ #region Keys
+
+ /// Analog[]
+ public const string AnalogKey = "analog";
+
+ /// string
+ public const string TagKey = "tag";
+
+ #endregion
+
+ public Port() => Type = ItemType.Port;
+ }
+}
diff --git a/SabreTools.Models/Internal/RamOption.cs b/SabreTools.Models/Internal/RamOption.cs
new file mode 100644
index 00000000..79c91b3f
--- /dev/null
+++ b/SabreTools.Models/Internal/RamOption.cs
@@ -0,0 +1,21 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("ramoption"), XmlRoot("ramoption")]
+ public class RamOption : DatItem
+ {
+ #region Keys
+
+ /// (yes|no) "no"
+ public const string DefaultKey = "default";
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public RamOption() => Type = ItemType.RamOption;
+ }
+}
diff --git a/SabreTools.Models/Internal/Release.cs b/SabreTools.Models/Internal/Release.cs
new file mode 100644
index 00000000..b2ae41b9
--- /dev/null
+++ b/SabreTools.Models/Internal/Release.cs
@@ -0,0 +1,30 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("release"), XmlRoot("release")]
+ public class Release : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string DateKey = "date";
+
+ /// (yes|no) "no"
+ public const string DefaultKey = "default";
+
+ /// string
+ public const string LanguageKey = "language";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string
+ public const string RegionKey = "region";
+
+ #endregion
+
+ public Release() => Type = ItemType.Release;
+ }
+}
diff --git a/SabreTools.Models/Internal/Rom.cs b/SabreTools.Models/Internal/Rom.cs
new file mode 100644
index 00000000..935128fc
--- /dev/null
+++ b/SabreTools.Models/Internal/Rom.cs
@@ -0,0 +1,285 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("rom"), XmlRoot("rom")]
+ public class Rom : DatItem
+ {
+ #region Keys
+
+ /// string; ArchiveDotOrg.File
+ public const string AlbumKey = "album";
+
+ /// string; AttractMode.Row
+ public const string AltRomnameKey = "alt_romname";
+
+ /// string; AttractMode.Row
+ public const string AltTitleKey = "alt_title";
+
+ /// string; ArchiveDotOrg.File
+ public const string ArtistKey = "artist";
+
+ /// string; ArchiveDotOrg.File
+ public const string ASRDetectedLangKey = "asr_detected_lang";
+
+ /// string; ArchiveDotOrg.File
+ public const string ASRDetectedLangConfKey = "asr_detected_lang_conf";
+
+ /// string; ArchiveDotOrg.File
+ public const string ASRTranscribedLang = "asr_transcribed_lang";
+
+ /// string
+ public const string BiosKey = "bios";
+
+ /// string; ArchiveDotOrg.File
+ public const string BitrateKey = "bitrate";
+
+ /// string; ArchiveDotOrg.File
+ public const string BitTorrentMagnetHashKey = "btih";
+
+ /// string; ArchiveDotOrg.File
+ public const string ClothCoverDetectionModuleVersionKey = "cloth_cover_detection_module_version";
+
+ /// string; ArchiveDotOrg.File
+ public const string CollectionCatalogNumberKey = "collection-catalog-number";
+
+ /// string; ArchiveDotOrg.File
+ public const string CommentKey = "comment";
+
+ /// string; Also "crc32" in ArchiveDotOrg.File
+ public const string CRCKey = "crc";
+
+ /// string; ArchiveDotOrg.File
+ public const string CreatorKey = "creator";
+
+ /// string
+ public const string DateKey = "date";
+
+ /// (yes|no) "no"
+ public const string DisposeKey = "dispose";
+
+ /// string; OfflineList.FileRomCRC
+ public const string ExtensionKey = "extension";
+
+ /// long; ArchiveDotOrg.File
+ public const string FileCountKey = "filecount";
+
+ /// bool; AttractMode.Row
+ public const string FileIsAvailable = "file_is_available";
+
+ /// string
+ public const string FlagsKey = "flags";
+
+ /// string; ArchiveDotOrg.File
+ public const string FormatKey = "format";
+
+ /// string
+ public const string HeaderKey = "header";
+
+ /// string, possibly long; ArchiveDotOrg.File
+ public const string HeightKey = "height";
+
+ /// string; ArchiveDotOrg.File
+ public const string hOCRCharToWordhOCRVersionKey = "hocr_char_to_word_hocr_version";
+
+ /// string; ArchiveDotOrg.File
+ public const string hOCRCharToWordModuleVersionKey = "hocr_char_to_word_module_version";
+
+ /// string; ArchiveDotOrg.File
+ public const string hOCRFtsTexthOCRVersionKey = "hocr_fts_text_hocr_version";
+
+ /// string; ArchiveDotOrg.File
+ public const string hOCRFtsTextModuleVersionKey = "hocr_fts_text_module_version";
+
+ /// string; ArchiveDotOrg.File
+ public const string hOCRPageIndexhOCRVersionKey = "hocr_pageindex_hocr_version";
+
+ /// string; ArchiveDotOrg.File
+ public const string hOCRPageIndexModuleVersionKey = "hocr_pageindex_module_version";
+
+ /// (yes|no) "no"
+ public const string InvertedKey = "inverted";
+
+ /// long; ArchiveDotOrg.File
+ public const string LastModifiedTimeKey = "mtime";
+
+ /// string, possibly long; Also in ArchiveDotOrg.File
+ public const string LengthKey = "length";
+
+ /// (load16_byte|load16_word|load16_word_swap|load32_byte|load32_word|load32_word_swap|load32_dword|load64_word|load64_word_swap|reload|fill|continue|reload_plain|ignore)
+ public const string LoadFlagKey = "loadflag";
+
+ /// string; ArchiveDotOrg.File
+ public const string MatrixNumberKey = "matrix_number";
+
+ /// string
+ public const string MD5Key = "md5";
+
+ /// string; OpenMSX.RomBase
+ public const string OpenMSXMediaType = "mediatype";
+
+ /// string
+ public const string MergeKey = "merge";
+
+ /// (yes|no) "no"
+ public const string MIAKey = "mia";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string; ArchiveDotOrg.File
+ public const string TesseractOCRKey = "ocr";
+
+ /// string; ArchiveDotOrg.File
+ public const string TesseractOCRConvertedKey = "ocr_converted";
+
+ /// string; ArchiveDotOrg.File
+ public const string TesseractOCRDetectedLangKey = "ocr_detected_lang";
+
+ /// string; ArchiveDotOrg.File
+ public const string TesseractOCRDetectedLangConfKey = "ocr_detected_lang_conf";
+
+ /// string; ArchiveDotOrg.File
+ public const string TesseractOCRDetectedScriptKey = "ocr_detected_script";
+
+ /// string; ArchiveDotOrg.File
+ public const string TesseractOCRDetectedScriptConfKey = "ocr_detected_script_conf";
+
+ /// string; ArchiveDotOrg.File
+ public const string TesseractOCRModuleVersionKey = "ocr_module_version";
+
+ /// string; ArchiveDotOrg.File
+ public const string TesseractOCRParametersKey = "ocr_parameters";
+
+ /// string, possibly long; Originally "offs"
+ public const string OffsetKey = "offset";
+
+ /// (yes|no) "no"
+ public const string OptionalKey = "optional";
+
+ /// string; ArchiveDotOrg.File
+ public const string OriginalKey = "original";
+
+ /// string; ArchiveDotOrg.File
+ public const string PDFModuleVersionKey = "pdf_module_version";
+
+ /// string; ArchiveDotOrg.File
+ public const string PreviewImageKey = "preview-image";
+
+ /// string; ArchiveDotOrg.File
+ public const string PublisherKey = "publisher";
+
+ /// string
+ public const string RegionKey = "region";
+
+ /// string; OpenMSX.RomBase
+ public const string RemarkKey = "remark";
+
+ /// string, possibly long; ArchiveDotOrg.File
+ public const string RotationKey = "rotation";
+
+ /// string
+ public const string SerialKey = "serial";
+
+ /// string
+ public const string SHA1Key = "sha1";
+
+ /// string
+ public const string SHA256Key = "sha256";
+
+ /// string
+ public const string SHA384Key = "sha384";
+
+ /// string
+ public const string SHA512Key = "sha512";
+
+ /// long
+ public const string SizeKey = "size";
+
+ /// (yes|no) "no"
+ public const string SoundOnlyKey = "soundonly";
+
+ /// string; ArchiveDotOrg.File
+ public const string SourceKey = "source";
+
+ /// string
+ public const string SpamSumKey = "spamsum";
+
+ /// string, possibly long; OpenMSX.RomBase
+ public const string StartKey = "start";
+
+ /// (baddump|nodump|good|verified) "good"
+ public const string StatusKey = "status";
+
+ /// string; ArchiveDotOrg.File
+ public const string SummationKey = "summation";
+
+ /// string; ArchiveDotOrg.File
+ public const string TitleKey = "title";
+
+ /// string, possibly long; ArchiveDotOrg.File
+ public const string TrackKey = "track";
+
+ /// string; OpenMSX.RomBase
+ public const string OpenMSXType = "type";
+
+ /// string
+ public const string ValueKey = "value";
+
+ /// string; ArchiveDotOrg.File
+ public const string WhisperASRModuleVersionKey = "whisper_asr_module_version";
+
+ /// string; ArchiveDotOrg.File
+ public const string WhisperModelHashKey = "whisper_model_hash";
+
+ /// string; ArchiveDotOrg.File
+ public const string WhisperModelNameKey = "whisper_model_name";
+
+ /// string; ArchiveDotOrg.File
+ public const string WhisperVersionKey = "whisper_version";
+
+ /// string, possibly long; ArchiveDotOrg.File
+ public const string WidthKey = "width";
+
+ /// string; ArchiveDotOrg.File
+ public const string WordConfidenceInterval0To10Key = "word_conf_0_10";
+
+ /// string; ArchiveDotOrg.File
+ public const string WordConfidenceInterval11To20Key = "word_conf_11_20";
+
+ /// string; ArchiveDotOrg.File
+ public const string WordConfidenceInterval21To30Key = "word_conf_21_30";
+
+ /// string; ArchiveDotOrg.File
+ public const string WordConfidenceInterval31To40Key = "word_conf_31_40";
+
+ /// string; ArchiveDotOrg.File
+ public const string WordConfidenceInterval41To50Key = "word_conf_41_50";
+
+ /// string; ArchiveDotOrg.File
+ public const string WordConfidenceInterval51To60Key = "word_conf_51_60";
+
+ /// string; ArchiveDotOrg.File
+ public const string WordConfidenceInterval61To70Key = "word_conf_61_70";
+
+ /// string; ArchiveDotOrg.File
+ public const string WordConfidenceInterval71To80Key = "word_conf_71_80";
+
+ /// string; ArchiveDotOrg.File
+ public const string WordConfidenceInterval81To90Key = "word_conf_81_90";
+
+ /// string; ArchiveDotOrg.File
+ public const string WordConfidenceInterval91To100Key = "word_conf_91_100";
+
+ /// string
+ public const string xxHash364Key = "xxh3_64";
+
+ /// string
+ public const string xxHash3128Key = "xxh3_128";
+
+ #endregion
+
+ public Rom() => Type = ItemType.Rom;
+ }
+}
diff --git a/SabreTools.Models/Internal/Sample.cs b/SabreTools.Models/Internal/Sample.cs
new file mode 100644
index 00000000..0274546c
--- /dev/null
+++ b/SabreTools.Models/Internal/Sample.cs
@@ -0,0 +1,18 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("sample"), XmlRoot("sample")]
+ public class Sample : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public Sample() => Type = ItemType.Sample;
+ }
+}
diff --git a/SabreTools.Models/Internal/SharedFeat.cs b/SabreTools.Models/Internal/SharedFeat.cs
new file mode 100644
index 00000000..bccaa275
--- /dev/null
+++ b/SabreTools.Models/Internal/SharedFeat.cs
@@ -0,0 +1,21 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("sharedfeat"), XmlRoot("sharedfeat")]
+ public class SharedFeat : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string
+ public const string ValueKey = "value";
+
+ #endregion
+
+ public SharedFeat() => Type = ItemType.SharedFeat;
+ }
+}
diff --git a/SabreTools.Models/Internal/Slot.cs b/SabreTools.Models/Internal/Slot.cs
new file mode 100644
index 00000000..45325a8e
--- /dev/null
+++ b/SabreTools.Models/Internal/Slot.cs
@@ -0,0 +1,21 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("slot"), XmlRoot("slot")]
+ public class Slot : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string NameKey = "name";
+
+ /// SlotOption[]
+ public const string SlotOptionKey = "slotoption";
+
+ #endregion
+
+ public Slot() => Type = ItemType.Slot;
+ }
+}
diff --git a/SabreTools.Models/Internal/SlotOption.cs b/SabreTools.Models/Internal/SlotOption.cs
new file mode 100644
index 00000000..daafd2f2
--- /dev/null
+++ b/SabreTools.Models/Internal/SlotOption.cs
@@ -0,0 +1,24 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("slotoption"), XmlRoot("slotoption")]
+ public class SlotOption : DatItem
+ {
+ #region Keys
+
+ /// (yes|no) "no"
+ public const string DefaultKey = "default";
+
+ /// string
+ public const string DevNameKey = "devname";
+
+ /// string
+ public const string NameKey = "name";
+
+ #endregion
+
+ public SlotOption() => Type = ItemType.SlotOption;
+ }
+}
diff --git a/SabreTools.Models/Internal/Software.cs b/SabreTools.Models/Internal/Software.cs
new file mode 100644
index 00000000..ba545b41
--- /dev/null
+++ b/SabreTools.Models/Internal/Software.cs
@@ -0,0 +1,45 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("software"), XmlRoot("software")]
+ public class Software : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string CloneOfKey = "cloneof";
+
+ /// string
+ public const string DescriptionKey = "description";
+
+ /// Info[]
+ public const string InfoKey = "info";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string
+ public const string NotesKey = "notes";
+
+ /// Part[]
+ public const string PartKey = "part";
+
+ /// string
+ public const string PublisherKey = "publisher";
+
+ /// SharedFeat[]
+ public const string SharedFeatKey = "sharedfeat";
+
+ /// (yes|partial|no) "yes"
+ public const string SupportedKey = "supported";
+
+ /// string
+ public const string YearKey = "year";
+
+ #endregion
+
+ public Software() => Type = ItemType.Software;
+ }
+}
diff --git a/SabreTools.Models/Internal/SoftwareList.cs b/SabreTools.Models/Internal/SoftwareList.cs
new file mode 100644
index 00000000..100fb71e
--- /dev/null
+++ b/SabreTools.Models/Internal/SoftwareList.cs
@@ -0,0 +1,36 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("softwarelist"), XmlRoot("softwarelist")]
+ public class SoftwareList : DatItem
+ {
+ #region Keys
+
+ /// string
+ public const string DescriptionKey = "description";
+
+ /// string
+ public const string FilterKey = "filter";
+
+ /// string
+ public const string NameKey = "name";
+
+ /// string
+ public const string NotesKey = "notes";
+
+ /// Software[]
+ public const string SoftwareKey = "software";
+
+ /// (original|compatible)
+ public const string StatusKey = "status";
+
+ /// string
+ public const string TagKey = "tag";
+
+ #endregion
+
+ public SoftwareList() => Type = ItemType.SoftwareList;
+ }
+}
diff --git a/SabreTools.Models/Internal/Sound.cs b/SabreTools.Models/Internal/Sound.cs
new file mode 100644
index 00000000..9251ecf8
--- /dev/null
+++ b/SabreTools.Models/Internal/Sound.cs
@@ -0,0 +1,18 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("sound"), XmlRoot("sound")]
+ public class Sound : DatItem
+ {
+ #region Keys
+
+ /// long
+ public const string ChannelsKey = "channels";
+
+ #endregion
+
+ public Sound() => Type = ItemType.Sound;
+ }
+}
diff --git a/SabreTools.Models/Internal/Video.cs b/SabreTools.Models/Internal/Video.cs
new file mode 100644
index 00000000..a1ff8a39
--- /dev/null
+++ b/SabreTools.Models/Internal/Video.cs
@@ -0,0 +1,36 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace SabreTools.Models.Internal
+{
+ [JsonObject("video"), XmlRoot("video")]
+ public class Video : DatItem
+ {
+ #region Keys
+
+ /// long
+ public const string AspectXKey = "aspectx";
+
+ /// long
+ public const string AspectYKey = "aspecty";
+
+ /// long; Originally "y"
+ public const string HeightKey = "height";
+
+ /// (vertical|horizontal)
+ public const string OrientationKey = "orientation";
+
+ /// double; Originally "freq"
+ public const string RefreshKey = "refresh";
+
+ /// (raster|vector)
+ public const string ScreenKey = "screen";
+
+ /// long; Originally "x"
+ public const string WidthKey = "width";
+
+ #endregion
+
+ public Video() => Type = ItemType.Video;
+ }
+}
diff --git a/SabreTools.Models/Listxml/Rom.cs b/SabreTools.Models/Listxml/Rom.cs
index 453b8ad0..6414e417 100644
--- a/SabreTools.Models/Listxml/Rom.cs
+++ b/SabreTools.Models/Listxml/Rom.cs
@@ -28,7 +28,7 @@ namespace SabreTools.Models.Listxml
[XmlAttribute("region")]
public string? Region { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("offset")]
public string? Offset { get; set; }
diff --git a/SabreTools.Models/Listxml/Sound.cs b/SabreTools.Models/Listxml/Sound.cs
index 1165672f..83f958c1 100644
--- a/SabreTools.Models/Listxml/Sound.cs
+++ b/SabreTools.Models/Listxml/Sound.cs
@@ -6,7 +6,7 @@ namespace SabreTools.Models.Listxml
[XmlRoot("sound")]
public class Sound
{
- /// Numeric?
+ /// Numeric
[XmlAttribute("channels")]
public string Channels { get; set; }
diff --git a/SabreTools.Models/Listxml/Video.cs b/SabreTools.Models/Listxml/Video.cs
index d383eb5f..0f035f05 100644
--- a/SabreTools.Models/Listxml/Video.cs
+++ b/SabreTools.Models/Listxml/Video.cs
@@ -14,23 +14,23 @@ namespace SabreTools.Models.Listxml
[XmlAttribute("orientation")]
public string Orientation { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("width")]
public string? Width { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("height")]
public string? Height { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("aspectx")]
public string? AspectX { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("aspecty")]
public string? AspectY { get; set; }
- /// Numeric?
+ /// Numeric
[XmlAttribute("refresh")]
public string? Refresh { get; set; }
diff --git a/SabreTools.Models/OpenMSX/RomBase.cs b/SabreTools.Models/OpenMSX/RomBase.cs
index a15d9d02..dbff0a33 100644
--- a/SabreTools.Models/OpenMSX/RomBase.cs
+++ b/SabreTools.Models/OpenMSX/RomBase.cs
@@ -14,6 +14,7 @@ namespace SabreTools.Models.OpenMSX
[XmlElement("type")]
public string? Type { get; set; }
+ /// SHA-1 hash
[XmlElement("hash")]
public string? Hash { get; set; }
diff --git a/SabreTools.Models/SabreTools.Models.csproj b/SabreTools.Models/SabreTools.Models.csproj
index 5e3ed4b4..dde70861 100644
--- a/SabreTools.Models/SabreTools.Models.csproj
+++ b/SabreTools.Models/SabreTools.Models.csproj
@@ -5,4 +5,8 @@
enable
+
+
+
+