mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-09-21 22:35:06 +00:00
Port PIC serialization from MPF
This commit is contained in:
20
Files/PIC.Deserializer.cs
Normal file
20
Files/PIC.Deserializer.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using SabreTools.Models.PIC;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class PIC : IFileSerializer<DiscInformation>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public DiscInformation Deserialize(string path)
|
||||
#else
|
||||
public DiscInformation? Deserialize(string? path)
|
||||
#endif
|
||||
{
|
||||
using (var stream = PathProcessor.OpenStream(path))
|
||||
{
|
||||
return new Streams.PIC().Deserialize(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Files/PIC.Serializer.cs
Normal file
30
Files/PIC.Serializer.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using SabreTools.Models.PIC;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class PIC : IFileSerializer<DiscInformation>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public bool Serialize(DiscInformation obj, string path)
|
||||
#else
|
||||
public bool Serialize(DiscInformation? obj, string? path)
|
||||
#endif
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
return false;
|
||||
|
||||
using (var stream = new Streams.PIC().Serialize(obj))
|
||||
{
|
||||
if (stream == null)
|
||||
return false;
|
||||
|
||||
using (var fs = System.IO.File.OpenWrite(path))
|
||||
{
|
||||
stream.CopyTo(fs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
202
Streams/PIC.Deserializer.cs
Normal file
202
Streams/PIC.Deserializer.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Models.PIC;
|
||||
using static SabreTools.Models.PIC.Constants;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
{
|
||||
public partial class PIC : IStreamSerializer<DiscInformation>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public DiscInformation Deserialize(Stream data)
|
||||
#else
|
||||
public DiscInformation? Deserialize(Stream? data)
|
||||
#endif
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead)
|
||||
return null;
|
||||
|
||||
// If the offset is out of bounds
|
||||
if (data.Position < 0 || data.Position >= data.Length)
|
||||
return null;
|
||||
|
||||
var di = new DiscInformation();
|
||||
|
||||
// Read the initial disc information
|
||||
di.DataStructureLength = data.ReadUInt16BigEndian();
|
||||
di.Reserved0 = data.ReadByteValue();
|
||||
di.Reserved1 = data.ReadByteValue();
|
||||
|
||||
// Create a list for the units
|
||||
var diUnits = new List<DiscInformationUnit>();
|
||||
|
||||
// Loop and read all available units
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
var unit = ParseDiscInformationUnit(data);
|
||||
if (unit == null)
|
||||
continue;
|
||||
|
||||
diUnits.Add(unit);
|
||||
}
|
||||
|
||||
// Assign the units and return
|
||||
di.Units = diUnits.ToArray();
|
||||
return di;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a disc information unit
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled disc information unit on success, null on error</returns>
|
||||
#if NET48
|
||||
private static DiscInformationUnit ParseDiscInformationUnit(Stream data)
|
||||
#else
|
||||
private static DiscInformationUnit? ParseDiscInformationUnit(Stream data)
|
||||
#endif
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var unit = new DiscInformationUnit();
|
||||
|
||||
#region Header
|
||||
|
||||
// Try to parse the header
|
||||
var header = ParseDiscInformationUnitHeader(data);
|
||||
if (header == null)
|
||||
return null;
|
||||
|
||||
// Set the information unit header
|
||||
unit.Header = header;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Body
|
||||
|
||||
// Try to parse the body
|
||||
var body = ParseDiscInformationUnitBody(data);
|
||||
if (body == null)
|
||||
return null;
|
||||
|
||||
// Set the information unit body
|
||||
unit.Body = body;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Trailer
|
||||
|
||||
if (unit.Body.DiscTypeIdentifier == DiscTypeIdentifierReWritable || unit.Body.DiscTypeIdentifier == DiscTypeIdentifierRecordable)
|
||||
{
|
||||
// Try to parse the trailer
|
||||
var trailer = ParseDiscInformationUnitTrailer(data);
|
||||
if (trailer == null)
|
||||
return null;
|
||||
|
||||
// Set the information unit trailer
|
||||
unit.Trailer = trailer;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
return unit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a disc information unit header
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled disc information unit header on success, null on error</returns>
|
||||
#if NET48
|
||||
private static DiscInformationUnitHeader ParseDiscInformationUnitHeader(Stream data)
|
||||
#else
|
||||
private static DiscInformationUnitHeader? ParseDiscInformationUnitHeader(Stream data)
|
||||
#endif
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var header = new DiscInformationUnitHeader();
|
||||
|
||||
// We only accept Disc Information units, not Emergency Brake or other
|
||||
#if NET48
|
||||
byte[] dic = data.ReadBytes(2);
|
||||
#else
|
||||
byte[]? dic = data.ReadBytes(2);
|
||||
#endif
|
||||
if (dic == null)
|
||||
return null;
|
||||
|
||||
header.DiscInformationIdentifier = Encoding.ASCII.GetString(dic);
|
||||
if (header.DiscInformationIdentifier != "DI")
|
||||
return null;
|
||||
|
||||
header.DiscInformationFormat = data.ReadByteValue();
|
||||
header.NumberOfUnitsInBlock = data.ReadByteValue();
|
||||
header.Reserved0 = data.ReadByteValue();
|
||||
header.SequenceNumber = data.ReadByteValue();
|
||||
header.BytesInUse = data.ReadByteValue();
|
||||
header.Reserved1 = data.ReadByteValue();
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a disc information unit body
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled disc information unit body on success, null on error</returns>
|
||||
#if NET48
|
||||
private static DiscInformationUnitBody ParseDiscInformationUnitBody(Stream data)
|
||||
#else
|
||||
private static DiscInformationUnitBody? ParseDiscInformationUnitBody(Stream data)
|
||||
#endif
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var body = new DiscInformationUnitBody();
|
||||
|
||||
#if NET48
|
||||
byte[] dti = data.ReadBytes(3);
|
||||
#else
|
||||
byte[]? dti = data.ReadBytes(3);
|
||||
#endif
|
||||
if (dti == null)
|
||||
return null;
|
||||
|
||||
body.DiscTypeIdentifier = Encoding.ASCII.GetString(dti);
|
||||
body.DiscSizeClassVersion = data.ReadByteValue();
|
||||
switch (body.DiscTypeIdentifier)
|
||||
{
|
||||
case DiscTypeIdentifierROM:
|
||||
case DiscTypeIdentifierROMUltra:
|
||||
body.FormatDependentContents = data.ReadBytes(52);
|
||||
break;
|
||||
case DiscTypeIdentifierReWritable:
|
||||
case DiscTypeIdentifierRecordable:
|
||||
body.FormatDependentContents = data.ReadBytes(100);
|
||||
break;
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a disc information unit trailer
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled disc information unit trailer on success, null on error</returns>
|
||||
private static DiscInformationUnitTrailer ParseDiscInformationUnitTrailer(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var trailer = new DiscInformationUnitTrailer();
|
||||
|
||||
trailer.DiscManufacturerID = data.ReadBytes(6);
|
||||
trailer.MediaTypeID = data.ReadBytes(3);
|
||||
trailer.TimeStamp = data.ReadUInt16();
|
||||
trailer.ProductRevisionNumber = data.ReadByteValue();
|
||||
|
||||
return trailer;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Streams/PIC.Serializer.cs
Normal file
16
Streams/PIC.Serializer.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.Models.PIC;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
{
|
||||
public partial class PIC : IStreamSerializer<DiscInformation>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Stream Serialize(DiscInformation obj) => throw new NotImplementedException();
|
||||
#else
|
||||
public Stream? Serialize(DiscInformation? obj) => throw new NotImplementedException();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user