diff --git a/Wrappers/XMID.cs b/Wrappers/XMID.cs new file mode 100644 index 00000000..1bf1554b --- /dev/null +++ b/Wrappers/XMID.cs @@ -0,0 +1,119 @@ +using System.IO; +using System.Text; +using static SabreTools.Models.Xbox.Constants; + +namespace SabreTools.Serialization.Wrappers +{ + public class XMID : WrapperBase + { + #region Descriptive Properties + + /// + public override string DescriptionString => "Xbox Media Identifier"; + + #endregion + + #region Extension Properties + + /// + /// Get the human-readable publisher string + /// + public string Publisher + { + get + { + var publisherIdentifier = this.Model.PublisherIdentifier; + if (string.IsNullOrWhiteSpace(publisherIdentifier)) + return "Unknown"; + + if (Publishers.ContainsKey(publisherIdentifier)) + return Publishers[publisherIdentifier]; + + return $"Unknown ({publisherIdentifier})"; + } + } + + /// + /// Get the human-readable region string + /// + public string Region + { + get + { + var regionIdentifier = this.Model.RegionIdentifier; + if (Regions.ContainsKey(regionIdentifier)) + return Regions[regionIdentifier]; + + return $"Unknown ({regionIdentifier})"; + } + } + + /// + /// Get the human-readable serial string + /// + public string Serial => $"{this.Model.PublisherIdentifier}-{this.Model.GameID}"; + + /// + /// Get the human-readable version string + /// + public string Version => $"1.{this.Model.VersionNumber}"; + + #endregion + + #region Constructors + + /// +#if NET48 + public XMID(Models.Xbox.XMID model, byte[] data, int offset) +#else + public XMID(Models.Xbox.XMID? model, byte[]? data, int offset) +#endif + : base(model, data, offset) + { + // All logic is handled by the base class + } + + /// +#if NET48 + public XMID(Models.Xbox.XMID model, Stream data) +#else + public XMID(Models.Xbox.XMID? model, Stream? data) +#endif + : base(model, data) + { + // All logic is handled by the base class + } + + /// + /// Create a XMID from a string + /// + /// String representing the data + /// A XMID wrapper on success, null on failure +#if NET48 + public static XMID Create(string data) +#else + public static XMID? Create(string? data) +#endif + { + // If the data is invalid + if (data == null || data.Length == 0) + return null; + + var binary = new Strings.XMID().Deserialize(data); + if (binary == null) + return null; + + try + { + var ms = new MemoryStream(Encoding.ASCII.GetBytes(data)); + return new XMID(binary, ms); + } + catch + { + return null; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/Wrappers/XeMID.cs b/Wrappers/XeMID.cs new file mode 100644 index 00000000..74a97565 --- /dev/null +++ b/Wrappers/XeMID.cs @@ -0,0 +1,134 @@ +using System.IO; +using System.Text; +using static SabreTools.Models.Xbox.Constants; + +namespace SabreTools.Serialization.Wrappers +{ + public class XeMID : WrapperBase + { + #region Descriptive Properties + + /// + public override string DescriptionString => "Xbox 360 Media Identifier"; + + #endregion + + #region Extension Properties + + /// + /// Get the human-readable media subtype string + /// + public string MediaSubtype + { + get + { + char mediaSubtype = this.Model.MediaSubtypeIdentifier; + if (MediaSubtypes.ContainsKey(mediaSubtype)) + return MediaSubtypes[mediaSubtype]; + + return $"Unknown ({mediaSubtype})"; + } + } + + /// + /// Get the human-readable publisher string + /// + public string Publisher + { + get + { + var publisherIdentifier = this.Model.PublisherIdentifier; + if (string.IsNullOrWhiteSpace(publisherIdentifier)) + return "Unknown"; + + if (Publishers.ContainsKey(publisherIdentifier)) + return Publishers[publisherIdentifier]; + + return $"Unknown ({publisherIdentifier})"; + } + } + + /// + /// Get the human-readable region string + /// + public string Region + { + get + { + var regionIdentifier = this.Model.RegionIdentifier; + if (Regions.ContainsKey(regionIdentifier)) + return Regions[regionIdentifier]; + + return $"Unknown ({regionIdentifier})"; + } + } + + /// + /// Get the human-readable serial string + /// + public string Serial => $"{this.Model.PublisherIdentifier}-{this.Model.PlatformIdentifier}{this.Model.GameID}"; + + /// + /// Get the human-readable version string + /// + public string Version => $"1.{this.Model.SKU}"; + + #endregion + + #region Constructors + + /// +#if NET48 + public XeMID(Models.Xbox.XeMID model, byte[] data, int offset) +#else + public XeMID(Models.Xbox.XeMID? model, byte[]? data, int offset) +#endif + : base(model, data, offset) + { + // All logic is handled by the base class + } + + /// +#if NET48 + public XeMID(Models.Xbox.XeMID model, Stream data) +#else + public XeMID(Models.Xbox.XeMID? model, Stream? data) +#endif + : base(model, data) + { + // All logic is handled by the base class + } + + /// + /// Create a XeMID from a string + /// + /// String representing the data + /// A XeMID wrapper on success, null on failure +#if NET48 + public static XeMID Create(string data) +#else + public static XeMID? Create(string? data) +#endif + { + // If the data is invalid + if (data == null || data.Length == 0) + return null; + + var binary = new Strings.XeMID().Deserialize(data); + if (binary == null) + return null; + + try + { + var ms = new MemoryStream(Encoding.ASCII.GetBytes(data)); + return new XeMID(binary, ms); + } + catch + { + return null; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/Wrappers/XgdInfo.cs b/Wrappers/XgdInfo.cs deleted file mode 100644 index 88821430..00000000 --- a/Wrappers/XgdInfo.cs +++ /dev/null @@ -1,279 +0,0 @@ -using static SabreTools.Models.Xbox.Constants; - -namespace SabreTools.Serialization.Wrappers -{ - /// - /// Contains information specific to an XGD disc - /// - /// TODO: Convert this to a proper WrapperBase implementation - public class XgdInfo - { - #region Properties - - /// - /// Indicates whether the information in this object is fully instantiated or not - /// - public bool Initialized { get; private set; } - - /// - /// Raw XMID/XeMID string that all other information is derived from - /// -#if NET48 - public string RawXMID { get; private set; } -#else - public string? RawXMID { get; private set; } -#endif - - /// - /// XGD1 XMID - /// -#if NET48 - public Models.Xbox.XMID XMID { get; private set; } -#else - public Models.Xbox.XMID? XMID { get; private set; } -#endif - - /// - /// XGD2/3 XeMID - /// -#if NET48 - public Models.Xbox.XeMID XeMID { get; private set; } -#else - public Models.Xbox.XeMID? XeMID { get; private set; } -#endif - - #endregion - - #region Extension Properties - - /// - /// Get the human-readable media subtype string - /// -#if NET48 - public string MediaSubtype -#else - public string? MediaSubtype -#endif - { - get - { - if (!this.Initialized) - return null; - - // Media subtype is only valid for XGD2/3 - if (XeMID == null) - return null; - - char mediaSubtype = XeMID.MediaSubtypeIdentifier; - if (MediaSubtypes.ContainsKey(mediaSubtype)) - return MediaSubtypes[mediaSubtype]; - - return $"Unknown ({mediaSubtype})"; - } - } - - /// - /// Get the human-readable publisher string - /// -#if NET48 - public string Publisher -#else - public string? Publisher -#endif - { - get - { - if (!this.Initialized) - return null; - -#if NET48 - string publisherIdentifier = null; -#else - string? publisherIdentifier = null; -#endif - if (XMID != null) - publisherIdentifier = XMID.PublisherIdentifier; - else if (XeMID != null) - publisherIdentifier = XeMID.PublisherIdentifier; - - if (string.IsNullOrWhiteSpace(publisherIdentifier)) - return null; - - if (Publishers.ContainsKey(publisherIdentifier)) - return Publishers[publisherIdentifier]; - - return $"Unknown ({publisherIdentifier})"; - } - } - - /// - /// Get the human-readable region string - /// -#if NET48 - public string Region -#else - public string? Region -#endif - { - get - { - if (!this.Initialized) - return null; - - char? regionIdentifier = null; - if (XMID != null) - regionIdentifier = XMID.RegionIdentifier; - else if (XeMID != null) - regionIdentifier = XeMID.RegionIdentifier; - - if (regionIdentifier == null) - return null; - - if (Regions.ContainsKey((char)regionIdentifier)) - return Regions[(char)regionIdentifier]; - - return $"Unknown ({regionIdentifier})"; - } - } - - /// - /// Get the human-readable serial string - /// -#if NET48 - public string Serial -#else - public string? Serial -#endif - { - get - { - if (!this.Initialized) - return null; - - try - { - // XGD1 doesn't use PlatformIdentifier - if (XMID != null) - return $"{XMID.PublisherIdentifier}-{XMID.GameID}"; - - // XGD2/3 uses a specific identifier - else if (XeMID?.PlatformIdentifier == '2') - return $"{XeMID.PublisherIdentifier}-{XeMID.PlatformIdentifier}{XeMID.GameID}"; - - return null; - } - catch - { - return null; - } - } - } - - /// - /// Get the human-readable version string - /// -#if NET48 - public string Version -#else - public string? Version -#endif - { - get - { - if (!this.Initialized) - return null; - - try - { - if (XMID != null) - return $"1.{XMID.VersionNumber}"; - else if (XeMID?.PlatformIdentifier == '2') - return $"1.{XeMID.SKU}"; - - return null; - } - catch - { - return null; - } - } - } - - #endregion - - #region Constructors - - /// - /// Populate a set of XGD information from a Master ID (XMID/XeMID) string - /// - /// XMID/XeMID string representing the DMI information - public XgdInfo(string xmid) - { - this.Initialized = false; - if (string.IsNullOrWhiteSpace(xmid)) - return; - - this.RawXMID = xmid.TrimEnd('\0'); - if (string.IsNullOrWhiteSpace(this.RawXMID)) - return; - - // XGD1 information is 8 characters - if (this.RawXMID.Length == 8) - this.Initialized = ParseXGD1XMID(this.RawXMID); - - // XGD2/3 information is semi-variable length - else if (this.RawXMID.Length == 13 || this.RawXMID.Length == 14 || this.RawXMID.Length == 21 || this.RawXMID.Length == 22) - this.Initialized = ParseXGD23XeMID(this.RawXMID); - } - - #endregion - - #region Helpers - - /// - /// Parse an XGD1 XMID string - /// - /// XMID string to attempt to parse - /// True if the XMID could be parsed, false otherwise - private bool ParseXGD1XMID(string rawXmid) - { - try - { - var xmid = new Strings.XMID().Deserialize(rawXmid); - if (xmid == null) - return false; - - this.XMID = xmid; - return true; - } - catch - { - return false; - } - } - - /// - /// Parse an XGD2/3 XeMID string - /// - /// XeMID string to attempt to parse - /// True if the XeMID could be parsed, false otherwise - private bool ParseXGD23XeMID(string rawXemid) - { - try - { - var xemid = new Strings.XeMID().Deserialize(rawXemid); - if (xemid == null) - return false; - - this.XeMID = xemid; - return true; - } - catch - { - return false; - } - } - - #endregion - } -}