using System.IO; using SabreTools.Data.Models.PCEngineCDROM; using SabreTools.IO.Extensions; using SabreTools.Matching; using SabreTools.Numerics.Extensions; namespace SabreTools.Wrappers { public partial class PCEngineDiscImage : WrapperBase
{ #region Descriptive Properties /// public override string DescriptionString => "PC Engine CD-ROM² / TurboGrafx-CD Disc Image"; #endregion #region Extension Properties /// public BootSector BootSector => Model.BootSector; /// public IPL IPL => Model.IPL; #endregion #region Constructors /// public PCEngineDiscImage(Header model, byte[] data) : base(model, data) { } /// public PCEngineDiscImage(Header model, byte[] data, int offset) : base(model, data, offset) { } /// public PCEngineDiscImage(Header model, byte[] data, int offset, int length) : base(model, data, offset, length) { } /// public PCEngineDiscImage(Header model, Stream data) : base(model, data) { } /// public PCEngineDiscImage(Header model, Stream data, long offset) : base(model, data, offset) { } /// public PCEngineDiscImage(Header model, Stream data, long offset, long length) : base(model, data, offset, length) { } #endregion #region Static Constructors /// /// Create a PCEngineCDROM Header from a byte array and offset /// /// Byte array representing the PCEngineCDROM Header /// Offset within the array to parse /// A PCEngineCDROM Header wrapper on success, null on failure public static PCEngineCDROM? Create(byte[]? data, int offset) { // If the data is invalid if (data is null || data.Length == 0) return null; // If the offset is out of bounds if (offset < 0 || offset >= data.Length) return null; // Create a memory stream and use that var dataStream = new MemoryStream(data, offset, data.Length - offset); return Create(dataStream); } /// /// Create a PCEngineCDROM Header from a Stream /// /// Stream representing the PCEngineCDROM Header /// A PCEngineCDROM Header wrapper on success, null on failure public static PCEngineCDROM? Create(Stream? data) { // If the data is invalid if (data is null || !data.CanRead) return null; try { // Create user data sub-stream var userData = new Data.Extensions.CDROMExtensions.UserDataStream(data); // Quit early if no data in stream if (userData.Length - userData.Position < 2 * Constants.SectorSize) return null; // PC Engine CD-ROM header can exist after some amount of pre-gap (check 250 sectors) for (int i = 0; i < 250; i++) { byte[] startBytes = userData.PeekBytes(16); if (startBytes.EqualsExactly(Constants.MagicBytes)) break; else if (startBytes.EqualsExactly(Constants.PregapBytes) && userData.Length - userData.Position >= 3 * Constants.SectorSize) userData.SeekIfPossible(Constants.SectorSize, SeekOrigin.Current); else return null; } // Cache the current offset (after the pregap) long currentOffset = userData.Position; var model = new Serialization.Readers.PCEngineCDROM().Deserialize(userData); if (model is null) return null; // Reset stream userData.Seek(currentOffset, SeekOrigin.Begin); return new PCEngineCDROM(model, userData, currentOffset); } catch { return null; } } #endregion } }