Files

123 lines
3.9 KiB
C#
Raw Permalink Normal View History

2023-10-25 14:43:43 -04:00
using System;
using System.IO;
using System.Text;
2026-04-19 09:33:55 -04:00
using SabreTools.Numerics.Extensions;
2023-10-25 14:43:43 -04:00
2025-09-26 14:59:45 -04:00
namespace SabreTools.Serialization.Writers
2023-10-25 14:43:43 -04:00
{
public class IRD : BaseBinaryWriter<Data.Models.IRD.File>
2023-10-25 14:43:43 -04:00
{
/// <inheritdoc/>
2025-09-26 13:06:18 -04:00
public override Stream? SerializeStream(Data.Models.IRD.File? obj)
2023-10-25 14:43:43 -04:00
{
2026-04-19 09:33:55 -04:00
#region Validation
2023-10-25 14:43:43 -04:00
// If the data is invalid
2026-01-25 14:30:18 -05:00
if (obj?.Magic is null)
2023-10-25 14:43:43 -04:00
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
2025-10-30 21:54:27 -04:00
if (obj.TitleID.Length != 9)
2023-10-25 14:43:43 -04:00
return null;
2025-10-30 21:54:27 -04:00
if (obj.Title.Length != obj.TitleLength)
2023-10-25 14:43:43 -04:00
return null;
2025-10-30 21:54:27 -04:00
if (obj.SystemVersion.Length != 4)
2023-10-25 14:43:43 -04:00
return null;
2025-10-30 21:54:27 -04:00
if (obj.GameVersion.Length != 5)
2023-10-25 14:43:43 -04:00
return null;
2025-10-30 21:54:27 -04:00
if (obj.AppVersion.Length != 5)
2023-10-25 14:43:43 -04:00
return null;
2025-10-30 21:54:27 -04:00
if (obj.Header.Length != obj.HeaderLength)
2023-10-25 14:43:43 -04:00
return null;
2025-10-30 21:54:27 -04:00
if (obj.Footer.Length != obj.FooterLength)
2023-10-25 14:43:43 -04:00
return null;
2026-01-25 14:30:18 -05:00
if (obj.RegionHashes.Length != obj.RegionCount || !Array.TrueForAll(obj.RegionHashes, h => h is null || h.Length != 16))
2023-10-25 14:43:43 -04:00
return null;
2025-10-30 21:54:27 -04:00
if (obj.FileKeys.Length != obj.FileCount)
2023-10-25 14:43:43 -04:00
return null;
2026-01-25 14:30:18 -05:00
if (obj.FileHashes.Length != obj.FileCount || !Array.TrueForAll(obj.FileHashes, h => h is null || h.Length != 16))
2023-10-25 14:43:43 -04:00
return null;
2025-10-30 21:54:27 -04:00
if (obj.PIC.Length != 115)
2023-10-25 14:43:43 -04:00
return null;
2025-10-30 21:54:27 -04:00
if (obj.Data1Key.Length != 16)
2023-10-25 14:43:43 -04:00
return null;
2025-10-30 21:54:27 -04:00
if (obj.Data2Key.Length != 16)
2023-10-25 14:43:43 -04:00
return null;
2026-04-19 09:33:55 -04:00
#endregion
2023-10-25 14:43:43 -04:00
// Create the output stream
var stream = new MemoryStream();
2026-04-19 09:33:55 -04:00
stream.Write(obj.Magic);
stream.Write(obj.Version);
2023-10-25 14:43:43 -04:00
byte[] titleId = Encoding.ASCII.GetBytes(obj.TitleID);
2026-04-19 09:33:55 -04:00
stream.Write(titleId);
2023-10-25 14:43:43 -04:00
2026-04-19 09:33:55 -04:00
stream.Write(obj.TitleLength);
2023-10-25 14:43:43 -04:00
byte[] title = Encoding.ASCII.GetBytes(obj.Title);
2026-04-19 09:33:55 -04:00
stream.Write(title);
2023-10-25 14:43:43 -04:00
byte[] systemVersion = Encoding.ASCII.GetBytes(obj.SystemVersion);
2026-04-19 09:33:55 -04:00
stream.Write(systemVersion);
2023-10-25 14:43:43 -04:00
byte[] gameVersion = Encoding.ASCII.GetBytes(obj.GameVersion);
2026-04-19 09:33:55 -04:00
stream.Write(gameVersion);
2023-10-25 14:43:43 -04:00
byte[] appVersion = Encoding.ASCII.GetBytes(obj.AppVersion);
2026-04-19 09:33:55 -04:00
stream.Write(appVersion);
2023-10-25 14:43:43 -04:00
if (obj.Version == 7)
2026-04-19 09:33:55 -04:00
stream.WriteLittleEndian(obj.UID);
2023-10-25 14:43:43 -04:00
2026-04-19 09:33:55 -04:00
stream.WriteLittleEndian(obj.HeaderLength);
stream.Write(obj.Header);
2023-10-25 14:43:43 -04:00
2026-04-19 09:33:55 -04:00
stream.WriteLittleEndian(obj.FooterLength);
stream.Write(obj.Footer);
2023-10-25 14:43:43 -04:00
2026-04-19 09:33:55 -04:00
stream.Write(obj.RegionCount);
2023-10-25 14:43:43 -04:00
for (int i = 0; i < obj.RegionCount; i++)
{
2026-04-19 09:33:55 -04:00
stream.Write(obj.RegionHashes[i]);
2023-10-25 14:43:43 -04:00
}
2026-04-19 09:33:55 -04:00
stream.WriteLittleEndian(obj.FileCount);
2023-10-25 14:43:43 -04:00
for (int i = 0; i < obj.FileCount; i++)
{
2026-04-19 09:33:55 -04:00
stream.WriteLittleEndian(obj.FileKeys[i]);
stream.Write(obj.FileHashes[i]);
2023-10-25 14:43:43 -04:00
}
2026-04-19 09:33:55 -04:00
stream.WriteLittleEndian(obj.ExtraConfig);
stream.WriteLittleEndian(obj.Attachments);
2023-10-25 14:43:43 -04:00
if (obj.Version >= 9)
2026-04-19 09:33:55 -04:00
stream.Write(obj.PIC);
2023-10-25 14:43:43 -04:00
2026-04-19 09:33:55 -04:00
stream.Write(obj.Data1Key);
stream.Write(obj.Data2Key);
2023-10-25 14:43:43 -04:00
if (obj.Version < 9)
2026-04-19 09:33:55 -04:00
stream.Write(obj.PIC);
2023-10-25 14:43:43 -04:00
if (obj.Version > 7)
2026-04-19 09:33:55 -04:00
stream.WriteLittleEndian(obj.UID);
2023-10-25 14:43:43 -04:00
2026-04-19 09:33:55 -04:00
stream.WriteLittleEndian(obj.CRC);
2023-10-25 14:43:43 -04:00
return stream;
}
}
}