mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-09-22 06:45:11 +00:00
Implement IRD serializers
This commit is contained in:
28
Bytes/IRD.Deserializer.cs
Normal file
28
Bytes/IRD.Deserializer.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Bytes
|
||||
{
|
||||
public partial class IRD : IByteSerializer<Models.IRD.IRD>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Models.IRD.IRD Deserialize(byte[] data, int offset)
|
||||
#else
|
||||
public Models.IRD.IRD? Deserialize(byte[]? data, int offset)
|
||||
#endif
|
||||
{
|
||||
// If the data is invalid
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
// If the offset is out of bounds
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
return null;
|
||||
|
||||
// Create a memory stream and parse that
|
||||
MemoryStream dataStream = new MemoryStream(data, offset, data.Length - offset);
|
||||
return new Streams.IRD().Deserialize(dataStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Files/IRD.Deserializer.cs
Normal file
20
Files/IRD.Deserializer.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class IRD : IFileSerializer<Models.IRD.IRD>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Models.IRD.IRD Deserialize(string path)
|
||||
#else
|
||||
public Models.IRD.IRD? Deserialize(string? path)
|
||||
#endif
|
||||
{
|
||||
using (var stream = PathProcessor.OpenStream(path))
|
||||
{
|
||||
return new Streams.IRD().Deserialize(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Files/IRD.Serializer.cs
Normal file
30
Files/IRD.Serializer.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Files
|
||||
{
|
||||
public partial class IRD : IFileSerializer<Models.IRD.IRD>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public bool Serialize(Models.IRD.IRD obj, string path)
|
||||
#else
|
||||
public bool Serialize(Models.IRD.IRD? obj, string? path)
|
||||
#endif
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
return false;
|
||||
|
||||
using (var stream = new Streams.IRD().Serialize(obj))
|
||||
{
|
||||
if (stream == null)
|
||||
return false;
|
||||
|
||||
using (var fs = System.IO.File.OpenWrite(path))
|
||||
{
|
||||
stream.CopyTo(fs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
119
Streams/IRD.Deserializer.cs
Normal file
119
Streams/IRD.Deserializer.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
{
|
||||
public partial class IRD : IStreamSerializer<Models.IRD.IRD>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Models.IRD.IRD Deserialize(Stream data)
|
||||
#else
|
||||
public Models.IRD.IRD? 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;
|
||||
|
||||
// Cache the current offset
|
||||
int initialOffset = (int)data.Position;
|
||||
|
||||
// Create a new media key block to fill
|
||||
var ird = new Models.IRD.IRD();
|
||||
|
||||
ird.Magic = data.ReadBytes(4);
|
||||
if (ird.Magic == null)
|
||||
return null;
|
||||
|
||||
string magic = Encoding.ASCII.GetString(ird.Magic);
|
||||
if (magic != "3IRD")
|
||||
return null;
|
||||
|
||||
ird.Version = data.ReadByteValue();
|
||||
if (ird.Version < 6)
|
||||
return null;
|
||||
|
||||
var titleId = data.ReadBytes(9);
|
||||
if (titleId == null)
|
||||
return null;
|
||||
|
||||
ird.TitleID = Encoding.ASCII.GetString(titleId);
|
||||
|
||||
ird.TitleLength = data.ReadByteValue();
|
||||
var title = data.ReadBytes(ird.TitleLength);
|
||||
if (title == null)
|
||||
return null;
|
||||
|
||||
ird.Title = Encoding.ASCII.GetString(title);
|
||||
|
||||
var systemVersion = data.ReadBytes(4);
|
||||
if (systemVersion == null)
|
||||
return null;
|
||||
|
||||
ird.SystemVersion = Encoding.ASCII.GetString(systemVersion);
|
||||
|
||||
var gameVersion = data.ReadBytes(5);
|
||||
if (gameVersion == null)
|
||||
return null;
|
||||
|
||||
ird.GameVersion = Encoding.ASCII.GetString(gameVersion);
|
||||
|
||||
var appVersion = data.ReadBytes(5);
|
||||
if (appVersion == null)
|
||||
return null;
|
||||
|
||||
ird.AppVersion = Encoding.ASCII.GetString(appVersion);
|
||||
|
||||
if (ird.Version == 7)
|
||||
ird.UID = data.ReadUInt32();
|
||||
|
||||
ird.HeaderLength = data.ReadByteValue();
|
||||
ird.Header = data.ReadBytes((int)ird.HeaderLength);
|
||||
ird.FooterLength = data.ReadByteValue();
|
||||
ird.Footer = data.ReadBytes((int)ird.FooterLength);
|
||||
|
||||
ird.RegionCount = data.ReadByteValue();
|
||||
ird.RegionHashes = new byte[ird.RegionCount][];
|
||||
for (int i = 0; i < ird.RegionCount; i++)
|
||||
{
|
||||
ird.RegionHashes[i] = data.ReadBytes(16) ?? Array.Empty<byte>();
|
||||
}
|
||||
|
||||
ird.FileCount = data.ReadByteValue();
|
||||
ird.FileKeys = new ulong[ird.FileCount];
|
||||
ird.FileHashes = new byte[ird.FileCount][];
|
||||
for (int i = 0; i < ird.FileCount; i++)
|
||||
{
|
||||
ird.FileKeys[i] = data.ReadUInt64();
|
||||
ird.FileHashes[i] = data.ReadBytes(16) ?? Array.Empty<byte>();
|
||||
}
|
||||
|
||||
ird.ExtraConfig = data.ReadUInt16();
|
||||
ird.Attachments = data.ReadUInt16();
|
||||
|
||||
if (ird.Version >= 9)
|
||||
ird.PIC = data.ReadBytes(115);
|
||||
|
||||
ird.Data1Key = data.ReadBytes(16);
|
||||
ird.Data2Key = data.ReadBytes(16);
|
||||
|
||||
if (ird.Version < 9)
|
||||
ird.PIC = data.ReadBytes(115);
|
||||
|
||||
if (ird.Version > 7)
|
||||
ird.UID = data.ReadUInt32();
|
||||
|
||||
ird.CRC = data.ReadUInt32();
|
||||
|
||||
return ird;
|
||||
}
|
||||
}
|
||||
}
|
||||
136
Streams/IRD.Serializer.cs
Normal file
136
Streams/IRD.Serializer.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Streams
|
||||
{
|
||||
public partial class IRD : IStreamSerializer<Models.IRD.IRD>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public Stream Serialize(Models.IRD.IRD obj)
|
||||
#else
|
||||
public Stream? Serialize(Models.IRD.IRD? obj)
|
||||
#endif
|
||||
{
|
||||
// If the data is invalid
|
||||
if (obj?.Magic == null)
|
||||
return null;
|
||||
|
||||
// If the magic doesn't match
|
||||
string magic = Encoding.ASCII.GetString(obj.Magic);
|
||||
if (magic != "3IRD")
|
||||
return null;
|
||||
|
||||
// If the version is less than the supported
|
||||
if (obj.Version < 6)
|
||||
return null;
|
||||
|
||||
// If any static-length fields aren't the correct length
|
||||
if (obj.TitleID == null || obj.TitleID.Length != 9)
|
||||
return null;
|
||||
if (obj.Title == null || obj.Title.Length != obj.TitleLength)
|
||||
return null;
|
||||
if (obj.SystemVersion == null || obj.SystemVersion.Length != 4)
|
||||
return null;
|
||||
if (obj.GameVersion == null || obj.GameVersion.Length != 5)
|
||||
return null;
|
||||
if (obj.AppVersion == null || obj.AppVersion.Length != 5)
|
||||
return null;
|
||||
if (obj.Header == null || obj.Header.Length != obj.HeaderLength)
|
||||
return null;
|
||||
if (obj.Footer == null || obj.Footer.Length != obj.FooterLength)
|
||||
return null;
|
||||
if (obj.RegionHashes == null || obj.RegionHashes.Length != obj.RegionCount || obj.RegionHashes.Any(h => h == null || h.Length != 16))
|
||||
return null;
|
||||
if (obj.FileKeys == null || obj.FileKeys.Length != obj.FileCount)
|
||||
return null;
|
||||
if (obj.FileHashes == null || obj.FileHashes.Length != obj.FileCount || obj.FileHashes.Any(h => h == null || h.Length != 16))
|
||||
return null;
|
||||
if (obj.PIC == null || obj.PIC.Length != 115)
|
||||
return null;
|
||||
if (obj.Data1Key == null || obj.Data1Key.Length != 16)
|
||||
return null;
|
||||
if (obj.Data2Key == null || obj.Data2Key.Length != 16)
|
||||
return null;
|
||||
|
||||
// Create the output stream
|
||||
var stream = new MemoryStream();
|
||||
|
||||
stream.Write(obj.Magic, 0, obj.Magic.Length);
|
||||
stream.WriteByte(obj.Version);
|
||||
|
||||
byte[] titleId = Encoding.ASCII.GetBytes(obj.TitleID);
|
||||
stream.Write(titleId, 0, titleId.Length);
|
||||
|
||||
stream.WriteByte(obj.TitleLength);
|
||||
byte[] title = Encoding.ASCII.GetBytes(obj.Title);
|
||||
stream.Write(title, 0, title.Length);
|
||||
|
||||
byte[] systemVersion = Encoding.ASCII.GetBytes(obj.SystemVersion);
|
||||
stream.Write(systemVersion, 0, systemVersion.Length);
|
||||
|
||||
byte[] gameVersion = Encoding.ASCII.GetBytes(obj.GameVersion);
|
||||
stream.Write(gameVersion, 0, gameVersion.Length);
|
||||
|
||||
byte[] appVersion = Encoding.ASCII.GetBytes(obj.AppVersion);
|
||||
stream.Write(appVersion, 0, appVersion.Length);
|
||||
|
||||
if (obj.Version == 7)
|
||||
{
|
||||
byte[] uid = BitConverter.GetBytes(obj.UID);
|
||||
stream.Write(uid, 0, uid.Length);
|
||||
}
|
||||
|
||||
byte[] headerLength = BitConverter.GetBytes(obj.HeaderLength);
|
||||
stream.Write(headerLength, 0, headerLength.Length);
|
||||
stream.Write(obj.Header, 0, obj.Header.Length);
|
||||
|
||||
byte[] footerLength = BitConverter.GetBytes(obj.FooterLength);
|
||||
stream.Write(footerLength, 0, footerLength.Length);
|
||||
stream.Write(obj.Footer, 0, obj.Footer.Length);
|
||||
|
||||
stream.WriteByte(obj.RegionCount);
|
||||
for (int i = 0; i < obj.RegionCount; i++)
|
||||
{
|
||||
stream.Write(obj.RegionHashes[i], 0, obj.RegionHashes[i].Length);
|
||||
}
|
||||
|
||||
byte[] fileCount = BitConverter.GetBytes(obj.FileCount);
|
||||
stream.Write(fileCount, 0, fileCount.Length);
|
||||
for (int i = 0; i < obj.FileCount; i++)
|
||||
{
|
||||
byte[] fileKey = BitConverter.GetBytes(obj.FileKeys[i]);
|
||||
stream.Write(fileKey, 0, fileKey.Length);
|
||||
stream.Write(obj.FileHashes[i], 0, obj.FileHashes[i].Length);
|
||||
}
|
||||
|
||||
byte[] extraConfig = BitConverter.GetBytes(obj.ExtraConfig);
|
||||
stream.Write(extraConfig, 0, extraConfig.Length);
|
||||
byte[] attachments = BitConverter.GetBytes(obj.Attachments);
|
||||
stream.Write(attachments, 0, attachments.Length);
|
||||
|
||||
if (obj.Version >= 9)
|
||||
stream.Write(obj.PIC, 0, obj.PIC.Length);
|
||||
|
||||
stream.Write(obj.Data1Key, 0, obj.Data1Key.Length);
|
||||
stream.Write(obj.Data2Key, 0, obj.Data2Key.Length);
|
||||
|
||||
if (obj.Version < 9)
|
||||
stream.Write(obj.PIC, 0, obj.PIC.Length);
|
||||
|
||||
if (obj.Version > 7)
|
||||
{
|
||||
byte[] uid = BitConverter.GetBytes(obj.UID);
|
||||
stream.Write(uid, 0, uid.Length);
|
||||
}
|
||||
|
||||
byte[] crc = BitConverter.GetBytes(obj.CRC);
|
||||
stream.Write(crc, 0, crc.Length);
|
||||
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user