diff --git a/SabreTools.Serialization.Test/Deserializers/AppPkgHeaderTests.cs b/SabreTools.Serialization.Test/Deserializers/AppPkgHeaderTests.cs new file mode 100644 index 00000000..e6b7cc48 --- /dev/null +++ b/SabreTools.Serialization.Test/Deserializers/AppPkgHeaderTests.cs @@ -0,0 +1,73 @@ +using System.IO; +using System.Linq; +using SabreTools.Serialization.Deserializers; +using Xunit; + +namespace SabreTools.Serialization.Test.Deserializers +{ + public class AppPkgHeaderTests + { + [Fact] + public void NullArray_Null() + { + byte[]? data = null; + int offset = 0; + var deserializer = new AppPkgHeader(); + + var actual = deserializer.Deserialize(data, offset); + Assert.Null(actual); + } + + [Fact] + public void EmptyArray_Null() + { + byte[]? data = []; + int offset = 0; + var deserializer = new AppPkgHeader(); + + var actual = deserializer.Deserialize(data, offset); + Assert.Null(actual); + } + + [Fact] + public void InvalidArray_Null() + { + byte[]? data = [.. Enumerable.Repeat(0xFF, 1024)]; + int offset = 0; + var deserializer = new AppPkgHeader(); + + var actual = deserializer.Deserialize(data, offset); + Assert.Null(actual); + } + + [Fact] + public void NullStream_Null() + { + Stream? data = null; + var deserializer = new AppPkgHeader(); + + var actual = deserializer.Deserialize(data); + Assert.Null(actual); + } + + [Fact] + public void EmptyStream_Null() + { + Stream? data = new MemoryStream([]); + var deserializer = new AppPkgHeader(); + + var actual = deserializer.Deserialize(data); + Assert.Null(actual); + } + + [Fact] + public void InvalidStream_Null() + { + Stream? data = new MemoryStream([.. Enumerable.Repeat(0xFF, 1024)]); + var deserializer = new AppPkgHeader(); + + var actual = deserializer.Deserialize(data); + Assert.Null(actual); + } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Deserializers/AppPkgHeader.cs b/SabreTools.Serialization/Deserializers/AppPkgHeader.cs new file mode 100644 index 00000000..2b9f6da3 --- /dev/null +++ b/SabreTools.Serialization/Deserializers/AppPkgHeader.cs @@ -0,0 +1,79 @@ +using System.IO; +using System.Text; +using SabreTools.IO.Extensions; +using static SabreTools.Models.PlayStation4.Constants; + +namespace SabreTools.Serialization.Deserializers +{ + public class AppPkgHeader : BaseBinaryDeserializer + { + /// + public override Models.PlayStation4.AppPkgHeader? Deserialize(Stream? data) + { + // If the data is invalid + if (data == null || !data.CanRead) + return null; + + try + { + // Create a new app.pkg header to fill + var appPkgHeader = new Models.PlayStation4.AppPkgHeader(); + + appPkgHeader.Magic = data.ReadUInt32BigEndian(); + if (appPkgHeader.Magic != AppPkgMagic) + return null; + + appPkgHeader.Type = data.ReadUInt32BigEndian(); + appPkgHeader.PKGUnknown = data.ReadUInt32BigEndian(); + appPkgHeader.FileCount = data.ReadUInt32BigEndian(); + appPkgHeader.EntryCount = data.ReadUInt32BigEndian(); + appPkgHeader.SCEntryCount = data.ReadUInt16BigEndian(); + appPkgHeader.EntryCount2 = data.ReadUInt16BigEndian(); + appPkgHeader.TableOffset = data.ReadUInt32BigEndian(); + appPkgHeader.EntryDataSize = data.ReadUInt32BigEndian(); + appPkgHeader.BodyOffset = data.ReadUInt64BigEndian(); + appPkgHeader.BodySize = data.ReadUInt64BigEndian(); + appPkgHeader.ContentOffset = data.ReadUInt64BigEndian(); + appPkgHeader.ContentSize = data.ReadUInt64BigEndian(); + byte[] contentID = data.ReadBytes(0x24); + appPkgHeader.ContentID = Encoding.ASCII.GetString(contentID).TrimEnd('\0'); + appPkgHeader.ContentZeroes = data.ReadBytes(0xC); + appPkgHeader.DRMType = data.ReadUInt32BigEndian(); + appPkgHeader.ContentType = data.ReadUInt32BigEndian(); + appPkgHeader.ContentFlags = data.ReadUInt32BigEndian(); + appPkgHeader.PromoteSize = data.ReadUInt32BigEndian(); + appPkgHeader.VersionDate = data.ReadUInt32BigEndian(); + appPkgHeader.VersionHash = data.ReadUInt32BigEndian(); + appPkgHeader.Zeroes1 = data.ReadBytes(0x78); + appPkgHeader.MainEntry1SHA256 = data.ReadBytes(0x20); + appPkgHeader.MainEntry2SHA256 = data.ReadBytes(0x20); + appPkgHeader.DigestTableSHA256 = data.ReadBytes(0x20); + appPkgHeader.MainTableSHA256 = data.ReadBytes(0x20); + appPkgHeader.Zeroes2 = data.ReadBytes(0x280); + appPkgHeader.PFSUnknown = data.ReadUInt32BigEndian(); + appPkgHeader.PFSImageCount = data.ReadUInt32BigEndian(); + appPkgHeader.PFSImageFlags = data.ReadUInt64BigEndian(); + appPkgHeader.PFSImageOffset = data.ReadUInt64BigEndian(); + appPkgHeader.PFSImageSize = data.ReadUInt64BigEndian(); + appPkgHeader.MountImageOffset = data.ReadUInt64BigEndian(); + appPkgHeader.MountImageSize = data.ReadUInt64BigEndian(); + appPkgHeader.PKGSize = data.ReadUInt64BigEndian(); + appPkgHeader.PKGSignedSize = data.ReadUInt32BigEndian(); + appPkgHeader.PKGCacheSize = data.ReadUInt32BigEndian(); + appPkgHeader.PFSImageSHA256 = data.ReadBytes(0x20); + appPkgHeader.PFSSignedSHA256 = data.ReadBytes(0x20); + appPkgHeader.PFSSplitSize0 = data.ReadUInt64BigEndian(); + appPkgHeader.PFSSplitSize1 = data.ReadUInt64BigEndian(); + appPkgHeader.Zeroes3 = data.ReadBytes(0xB50); + appPkgHeader.PKGSHA256 = data.ReadBytes(0x20); + + return appPkgHeader; + } + catch + { + // Ignore the actual error + return null; + } + } + } +} \ No newline at end of file