diff --git a/LibHac/Cnmt.cs b/LibHac/Cnmt.cs index e1a6bf82..1ebd26db 100644 --- a/LibHac/Cnmt.cs +++ b/LibHac/Cnmt.cs @@ -4,22 +4,24 @@ namespace LibHac { public class Cnmt { - public ulong TitleId { get; set; } - public TitleVersion TitleVersion { get; set; } - public TitleType Type { get; set; } - public byte FieldD { get; set; } - public int TableOffset { get; set; } - public int ContentEntryCount { get; set; } - public int MetaEntryCount { get; set; } + public ulong TitleId { get; } + public TitleVersion TitleVersion { get; } + public TitleType Type { get; } + public byte FieldD { get; } + public int TableOffset { get; } + public int ContentEntryCount { get; } + public int MetaEntryCount { get; } - public CnmtContentEntry[] ContentEntries { get; set; } - public CnmtMetaEntry[] MetaEntries { get; set; } + public CnmtContentEntry[] ContentEntries { get; } + public CnmtContentMetaEntry[] MetaEntries { get; } - public ulong ApplicationTitleId { get; set; } - public ulong PatchTitleId { get; set; } + public ulong ApplicationTitleId { get; } + public ulong PatchTitleId { get; } public TitleVersion MinimumSystemVersion { get; } public TitleVersion MinimumApplicationVersion { get; } + public CnmtExtended ExtendedData { get; } + public Cnmt() { } public Cnmt(Stream file) @@ -56,7 +58,7 @@ namespace LibHac file.Position = 0x20 + TableOffset; ContentEntries = new CnmtContentEntry[ContentEntryCount]; - MetaEntries = new CnmtMetaEntry[MetaEntryCount]; + MetaEntries = new CnmtContentMetaEntry[MetaEntryCount]; for (int i = 0; i < ContentEntryCount; i++) { @@ -65,7 +67,12 @@ namespace LibHac for (int i = 0; i < MetaEntryCount; i++) { - MetaEntries[i] = new CnmtMetaEntry(reader); + MetaEntries[i] = new CnmtContentMetaEntry(reader); + } + + if (Type == TitleType.Patch) + { + ExtendedData = new CnmtExtended(reader); } } } @@ -91,15 +98,15 @@ namespace LibHac } } - public class CnmtMetaEntry + public class CnmtContentMetaEntry { public ulong TitleId { get; } public TitleVersion Version { get; } public CnmtContentType Type { get; } - public CnmtMetaEntry() { } + public CnmtContentMetaEntry() { } - public CnmtMetaEntry(BinaryReader reader) + public CnmtContentMetaEntry(BinaryReader reader) { TitleId = reader.ReadUInt64(); Version = new TitleVersion(reader.ReadUInt32(), true); @@ -108,15 +115,188 @@ namespace LibHac } } + public class CnmtExtended + { + public int PrevMetaCount { get; } + public int PrevDeltaCount { get; } + public int DeltaInfoCount { get; } + public int DeltaApplyCount { get; } + public int PrevContentCount { get; } + public int DeltaContentCount { get; } + + public CnmtPrevMetaEntry[] PrevMetas { get; } + public CnmtPrevDelta[] PrevDeltas { get; } + public CnmtDeltaInfo[] DeltaInfos { get; } + public CnmtDeltaApplyInfo[] DeltaApplyInfos { get; } + public CnmtPrevContent[] PrevContents { get; } + public CnmtContentEntry[] DeltaContents { get; } + + public CnmtExtended(BinaryReader reader) + { + PrevMetaCount = reader.ReadInt32(); + PrevDeltaCount = reader.ReadInt32(); + DeltaInfoCount = reader.ReadInt32(); + DeltaApplyCount = reader.ReadInt32(); + PrevContentCount = reader.ReadInt32(); + DeltaContentCount = reader.ReadInt32(); + reader.BaseStream.Position += 4; + + PrevMetas = new CnmtPrevMetaEntry[PrevMetaCount]; + PrevDeltas = new CnmtPrevDelta[PrevDeltaCount]; + DeltaInfos = new CnmtDeltaInfo[DeltaInfoCount]; + DeltaApplyInfos = new CnmtDeltaApplyInfo[DeltaApplyCount]; + PrevContents = new CnmtPrevContent[PrevContentCount]; + DeltaContents = new CnmtContentEntry[DeltaContentCount]; + + for (int i = 0; i < PrevMetaCount; i++) + { + PrevMetas[i] = new CnmtPrevMetaEntry(reader); + } + + for (int i = 0; i < PrevDeltaCount; i++) + { + PrevDeltas[i] = new CnmtPrevDelta(reader); + } + + for (int i = 0; i < DeltaInfoCount; i++) + { + DeltaInfos[i] = new CnmtDeltaInfo(reader); + } + + for (int i = 0; i < DeltaApplyCount; i++) + { + DeltaApplyInfos[i] = new CnmtDeltaApplyInfo(reader); + } + + for (int i = 0; i < PrevContentCount; i++) + { + PrevContents[i] = new CnmtPrevContent(reader); + } + + for (int i = 0; i < DeltaContentCount; i++) + { + DeltaContents[i] = new CnmtContentEntry(reader); + } + } + } + + public class CnmtPrevMetaEntry + { + public ulong TitleId { get; } + public TitleVersion Version { get; } + public TitleType Type { get; } + public byte[] Hash { get; } + public short Field30 { get; } + public short Field32 { get; } + public int Field34 { get; } + + public CnmtPrevMetaEntry(BinaryReader reader) + { + TitleId = reader.ReadUInt64(); + Version = new TitleVersion(reader.ReadUInt32()); + Type = (TitleType)reader.ReadByte(); + reader.BaseStream.Position += 3; + Hash = reader.ReadBytes(0x20); + Field30 = reader.ReadInt16(); + Field32 = reader.ReadInt16(); + Field34 = reader.ReadInt32(); + } + } + + public class CnmtPrevDelta + { + public ulong TitleIdOld { get; } + public ulong TitleIdNew { get; } + public TitleVersion VersionOld { get; } + public TitleVersion VersionNew { get; } + public long Size { get; } + public long Field20 { get; } + + public CnmtPrevDelta(BinaryReader reader) + { + TitleIdOld = reader.ReadUInt64(); + TitleIdNew = reader.ReadUInt64(); + VersionOld = new TitleVersion(reader.ReadUInt32()); + VersionNew = new TitleVersion(reader.ReadUInt32()); + Size = reader.ReadInt64(); + Field20 = reader.ReadInt64(); + } + } + + public class CnmtDeltaInfo + { + public ulong TitleIdOld { get; } + public ulong TitleIdNew { get; } + public TitleVersion VersionOld { get; } + public TitleVersion VersionNew { get; } + public long Field18 { get; } + public long Field20 { get; } + + public CnmtDeltaInfo(BinaryReader reader) + { + TitleIdOld = reader.ReadUInt64(); + TitleIdNew = reader.ReadUInt64(); + VersionOld = new TitleVersion(reader.ReadUInt32()); + VersionNew = new TitleVersion(reader.ReadUInt32()); + Field18 = reader.ReadInt64(); + Field20 = reader.ReadInt64(); + } + } + + public class CnmtDeltaApplyInfo + { + public byte[] NcaIdOld { get; } + public byte[] NcaIdNew { get; } + public long SizeOld { get; } + public long SizeNew { get; } + public short Field2C { get; } + public CnmtContentType Type { get; } + public short Field2F { get; } + public int Field30 { get; } + + + public CnmtDeltaApplyInfo(BinaryReader reader) + { + NcaIdOld = reader.ReadBytes(0x10); + NcaIdNew = reader.ReadBytes(0x10); + + SizeOld = reader.ReadUInt32(); + SizeOld |= ((long)reader.ReadUInt16() << 32); + SizeNew |= ((long)reader.ReadUInt16() << 32); + SizeNew = reader.ReadUInt32(); + + Field2C = reader.ReadInt16(); + Type = (CnmtContentType)reader.ReadByte(); + Field2F = reader.ReadByte(); + Field30 = reader.ReadInt32(); + } + } + + public class CnmtPrevContent + { + public byte[] NcaId { get; } + public long Size { get; } + public CnmtContentType Type { get; } + + public CnmtPrevContent(BinaryReader reader) + { + NcaId = reader.ReadBytes(0x10); + Size = reader.ReadUInt32(); + Size |= ((long)reader.ReadUInt16() << 32); + Type = (CnmtContentType)reader.ReadByte(); + reader.BaseStream.Position += 1; + } + } + public enum CnmtContentType { Meta, Program, Data, Control, - OfflineManualHtml, - LegalHtml, - UpdatePatch + HtmlDocument, + LegalInformation, + DeltaFragment } public enum TitleType @@ -129,6 +309,6 @@ namespace LibHac Application = 0x80, Patch, AddOnContent, - DeltaTitle + Delta } } diff --git a/LibHac/SwitchFs.cs b/LibHac/SwitchFs.cs index da6818cf..0649ffa2 100644 --- a/LibHac/SwitchFs.cs +++ b/LibHac/SwitchFs.cs @@ -304,7 +304,7 @@ namespace LibHac public long GetSize() { return Metadata.ContentEntries - .Where(x => x.Type < CnmtContentType.UpdatePatch) + .Where(x => x.Type < CnmtContentType.DeltaFragment) .Sum(x => x.Size); } } @@ -339,7 +339,7 @@ namespace LibHac case TitleType.AddOnContent: AddOnContent.Add(title); break; - case TitleType.DeltaTitle: + case TitleType.Delta: break; }