Add content storage and content meta DB interfaces

This commit is contained in:
Alex Barney 2019-07-22 20:38:59 -05:00
parent e9376efba7
commit c3dfaf14e8
13 changed files with 439 additions and 115 deletions

View file

@ -1,6 +1,8 @@
using System.IO;
using System.Linq;
using LibHac.Fs.NcaUtils;
using LibHac.Ncm;
using ContentType = LibHac.Ncm.ContentType;
namespace LibHac
{
@ -8,7 +10,7 @@ namespace LibHac
{
public ulong TitleId { get; }
public TitleVersion TitleVersion { get; }
public TitleType Type { get; }
public ContentMetaType Type { get; }
public byte FieldD { get; }
public int TableOffset { get; }
public int ContentEntryCount { get; }
@ -34,8 +36,8 @@ namespace LibHac
{
TitleId = reader.ReadUInt64();
uint version = reader.ReadUInt32();
Type = (TitleType)reader.ReadByte();
TitleVersion = new TitleVersion(version, Type < TitleType.Application);
Type = (ContentMetaType)reader.ReadByte();
TitleVersion = new TitleVersion(version, Type < ContentMetaType.Application);
FieldD = reader.ReadByte();
TableOffset = reader.ReadUInt16();
ContentEntryCount = reader.ReadUInt16();
@ -44,16 +46,16 @@ namespace LibHac
switch (Type)
{
case TitleType.Application:
case ContentMetaType.Application:
ApplicationTitleId = TitleId;
PatchTitleId = reader.ReadUInt64();
MinimumSystemVersion = new TitleVersion(reader.ReadUInt32(), true);
break;
case TitleType.Patch:
case ContentMetaType.Patch:
ApplicationTitleId = reader.ReadUInt64();
MinimumSystemVersion = new TitleVersion(reader.ReadUInt32(), true);
break;
case TitleType.AddOnContent:
case ContentMetaType.AddOnContent:
ApplicationTitleId = reader.ReadUInt64();
MinimumApplicationVersion = new TitleVersion(reader.ReadUInt32());
break;
@ -74,7 +76,7 @@ namespace LibHac
MetaEntries[i] = new CnmtContentMetaEntry(reader);
}
if (Type == TitleType.Patch)
if (Type == ContentMetaType.Patch)
{
ExtendedData = new CnmtExtended(reader);
}
@ -89,7 +91,7 @@ namespace LibHac
public byte[] Hash { get; set; }
public byte[] NcaId { get; set; }
public long Size { get; set; }
public CnmtContentType Type { get; set; }
public ContentType Type { get; set; }
public CnmtContentEntry() { }
@ -99,7 +101,7 @@ namespace LibHac
NcaId = reader.ReadBytes(0x10);
Size = reader.ReadUInt32();
Size |= (long)reader.ReadUInt16() << 32;
Type = (CnmtContentType)reader.ReadByte();
Type = (ContentType)reader.ReadByte();
reader.BaseStream.Position += 1;
}
}
@ -108,7 +110,7 @@ namespace LibHac
{
public ulong TitleId { get; }
public TitleVersion Version { get; }
public CnmtContentType Type { get; }
public ContentType Type { get; }
public CnmtContentMetaEntry() { }
@ -116,7 +118,7 @@ namespace LibHac
{
TitleId = reader.ReadUInt64();
Version = new TitleVersion(reader.ReadUInt32(), true);
Type = (CnmtContentType)reader.ReadByte();
Type = (ContentType)reader.ReadByte();
reader.BaseStream.Position += 3;
}
}
@ -199,7 +201,7 @@ namespace LibHac
{
public ulong TitleId { get; }
public TitleVersion Version { get; }
public TitleType Type { get; }
public ContentMetaType Type { get; }
public byte[] Hash { get; }
public short ContentCount { get; }
public short CnmtPrevMetaEntryField32 { get; }
@ -209,7 +211,7 @@ namespace LibHac
{
TitleId = reader.ReadUInt64();
Version = new TitleVersion(reader.ReadUInt32());
Type = (TitleType)reader.ReadByte();
Type = (ContentMetaType)reader.ReadByte();
reader.BaseStream.Position += 3;
Hash = reader.ReadBytes(0x20);
ContentCount = reader.ReadInt16();
@ -265,8 +267,8 @@ namespace LibHac
public long SizeOld { get; }
public long SizeNew { get; }
public short FragmentCount { get; }
public CnmtContentType Type { get; }
public CnmtDeltaType DeltaType { get; }
public ContentType Type { get; }
public UpdateType DeltaType { get; }
public int FragmentSetInfoField30 { get; }
@ -281,8 +283,8 @@ namespace LibHac
SizeNew = reader.ReadUInt32();
FragmentCount = reader.ReadInt16();
Type = (CnmtContentType)reader.ReadByte();
DeltaType = (CnmtDeltaType)reader.ReadByte();
Type = (ContentType)reader.ReadByte();
DeltaType = (UpdateType)reader.ReadByte();
FragmentSetInfoField30 = reader.ReadInt32();
}
}
@ -291,14 +293,14 @@ namespace LibHac
{
public byte[] NcaId { get; }
public long Size { get; }
public CnmtContentType Type { get; }
public ContentType Type { get; }
public CnmtPrevContent(BinaryReader reader)
{
NcaId = reader.ReadBytes(0x10);
Size = reader.ReadUInt32();
Size |= (long)reader.ReadUInt16() << 32;
Type = (CnmtContentType)reader.ReadByte();
Type = (ContentType)reader.ReadByte();
reader.BaseStream.Position += 1;
}
}
@ -314,35 +316,4 @@ namespace LibHac
FragmentIndex = reader.ReadInt16();
}
}
public enum CnmtContentType
{
Meta,
Program,
Data,
Control,
HtmlDocument,
LegalInformation,
DeltaFragment
}
public enum CnmtDeltaType
{
Delta,
Replace,
NewContent
}
public enum TitleType
{
SystemProgram = 1,
SystemData,
SystemUpdate,
BootImagePackage,
BootImagePackageSafe,
Application = 0x80,
Patch,
AddOnContent,
Delta
}
}

101
src/LibHac/Common/Id128.cs Normal file
View file

@ -0,0 +1,101 @@
using System;
using System.Runtime.InteropServices;
namespace LibHac.Common
{
/// <summary>
/// A generic 128-bit ID value.
/// </summary>
[StructLayout(LayoutKind.Sequential, Size = 0x10)]
public struct Id128 : IEquatable<Id128>, IComparable<Id128>, IComparable
{
public readonly ulong High;
public readonly ulong Low;
public static Id128 InvalidId = new Id128(0, 0);
public Id128(ulong high, ulong low)
{
High = high;
Low = low;
}
public Id128(ReadOnlySpan<byte> uid)
{
ReadOnlySpan<ulong> longs = MemoryMarshal.Cast<byte, ulong>(uid);
High = longs[0];
Low = longs[1];
}
public bool Equals(Id128 other)
{
return High == other.High && Low == other.Low;
}
public override bool Equals(object obj)
{
return obj is Fs.UserId other && Equals(other);
}
public override int GetHashCode()
{
unchecked
{
return (High.GetHashCode() * 397) ^ Low.GetHashCode();
}
}
public int CompareTo(Id128 other)
{
// ReSharper disable ImpureMethodCallOnReadonlyValueField
int highComparison = High.CompareTo(other.High);
if (highComparison != 0) return highComparison;
return Low.CompareTo(other.Low);
// ReSharper restore ImpureMethodCallOnReadonlyValueField
}
public int CompareTo(object obj)
{
if (obj is null) return 1;
return obj is Id128 other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(Id128)}");
}
public void ToBytes(Span<byte> output)
{
Span<ulong> longs = MemoryMarshal.Cast<byte, ulong>(output);
longs[0] = High;
longs[1] = Low;
}
public static bool operator ==(Id128 left, Id128 right)
{
return left.Equals(right);
}
public static bool operator !=(Id128 left, Id128 right)
{
return !left.Equals(right);
}
public static bool operator <(Id128 left, Id128 right)
{
return left.CompareTo(right) < 0;
}
public static bool operator >(Id128 left, Id128 right)
{
return left.CompareTo(right) > 0;
}
public static bool operator <=(Id128 left, Id128 right)
{
return left.CompareTo(right) <= 0;
}
public static bool operator >=(Id128 left, Id128 right)
{
return left.CompareTo(right) >= 0;
}
}
}

View file

@ -516,7 +516,7 @@ namespace LibHac.Fs.NcaUtils
return Header.VerifySignature1(Keyset.NcaHdrFixedKeyModulus);
}
internal void GenerateAesCounter(int sectionIndex, CnmtContentType type, int minorVersion)
internal void GenerateAesCounter(int sectionIndex, Ncm.ContentType type, int minorVersion)
{
int counterType;
int counterVersion;
@ -527,14 +527,14 @@ namespace LibHac.Fs.NcaUtils
switch (type)
{
case CnmtContentType.Program:
case Ncm.ContentType.Program:
counterType = sectionIndex + 1;
break;
case CnmtContentType.HtmlDocument:
counterType = (int)CnmtContentType.HtmlDocument;
case Ncm.ContentType.HtmlDocument:
counterType = (int)Ncm.ContentType.HtmlDocument;
break;
case CnmtContentType.LegalInformation:
counterType = (int)CnmtContentType.LegalInformation;
case Ncm.ContentType.LegalInformation:
counterType = (int)Ncm.ContentType.LegalInformation;
break;
default:
counterType = 0;

47
src/LibHac/Fs/RightsId.cs Normal file
View file

@ -0,0 +1,47 @@
using System;
using System.Runtime.InteropServices;
using LibHac.Common;
namespace LibHac.Fs
{
[StructLayout(LayoutKind.Sequential, Size = 0x10)]
public struct RightsId : IEquatable<RightsId>, IComparable<RightsId>, IComparable
{
public readonly Id128 Id;
public RightsId(ulong high, ulong low)
{
Id = new Id128(high, low);
}
public RightsId(ReadOnlySpan<byte> uid)
{
Id = new Id128(uid);
}
public bool Equals(RightsId other) => Id == other.Id;
public override bool Equals(object obj) => obj is RightsId other && Equals(other);
public override int GetHashCode() => Id.GetHashCode();
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
public int CompareTo(RightsId other) => Id.CompareTo(other.Id);
public int CompareTo(object obj)
{
if (obj is null) return 1;
return obj is RightsId other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(RightsId)}");
}
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
public void ToBytes(Span<byte> output) => Id.ToBytes(output);
public static bool operator ==(RightsId left, RightsId right) => left.Equals(right);
public static bool operator !=(RightsId left, RightsId right) => !left.Equals(right);
public static bool operator <(RightsId left, RightsId right) => left.CompareTo(right) < 0;
public static bool operator >(RightsId left, RightsId right) => left.CompareTo(right) > 0;
public static bool operator <=(RightsId left, RightsId right) => left.CompareTo(right) <= 0;
public static bool operator >=(RightsId left, RightsId right) => left.CompareTo(right) >= 0;
}
}

View file

@ -1,66 +1,47 @@
using System;
using System.Runtime.InteropServices;
using LibHac.Common;
namespace LibHac.Fs
{
[StructLayout(LayoutKind.Sequential, Size = 0x10)]
public struct UserId : IEquatable<UserId>, IComparable<UserId>, IComparable
{
public readonly ulong High;
public readonly ulong Low;
public readonly Id128 Id;
public UserId(ulong high, ulong low)
{
High = high;
Low = low;
Id = new Id128(high, low);
}
public UserId(ReadOnlySpan<byte> uid)
{
ReadOnlySpan<ulong> longs = MemoryMarshal.Cast<byte, ulong>(uid);
High = longs[0];
Low = longs[1];
Id = new Id128(uid);
}
public bool Equals(UserId other)
{
return High == other.High && Low == other.Low;
}
public bool Equals(UserId other) => Id == other.Id;
public override bool Equals(object obj) => obj is UserId other && Equals(other);
public override bool Equals(object obj)
{
return obj is UserId other && Equals(other);
}
public override int GetHashCode() => Id.GetHashCode();
public override int GetHashCode()
{
unchecked
{
return (High.GetHashCode() * 397) ^ Low.GetHashCode();
}
}
public int CompareTo(UserId other)
{
// ReSharper disable ImpureMethodCallOnReadonlyValueField
int highComparison = High.CompareTo(other.High);
if (highComparison != 0) return highComparison;
return Low.CompareTo(other.Low);
// ReSharper restore ImpureMethodCallOnReadonlyValueField
}
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
public int CompareTo(UserId other) => Id.CompareTo(other.Id);
public int CompareTo(object obj)
{
if (ReferenceEquals(null, obj)) return 1;
if (obj is null) return 1;
return obj is UserId other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(UserId)}");
}
public void ToBytes(Span<byte> output)
{
Span<ulong> longs = MemoryMarshal.Cast<byte, ulong>(output);
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
public void ToBytes(Span<byte> output) => Id.ToBytes(output);
longs[0] = High;
longs[1] = Low;
}
public static bool operator ==(UserId left, UserId right) => left.Equals(right);
public static bool operator !=(UserId left, UserId right) => !left.Equals(right);
public static bool operator <(UserId left, UserId right) => left.CompareTo(right) < 0;
public static bool operator >(UserId left, UserId right) => left.CompareTo(right) > 0;
public static bool operator <=(UserId left, UserId right) => left.CompareTo(right) <= 0;
public static bool operator >=(UserId left, UserId right) => left.CompareTo(right) >= 0;
}
}

View file

@ -0,0 +1,40 @@
namespace LibHac.Ncm
{
public enum ContentType : byte
{
Meta = 0,
Program = 1,
Data = 2,
Control = 3,
HtmlDocument = 4,
LegalInformation = 5,
DeltaFragment = 6
}
public enum ContentMetaType : byte
{
SystemProgram = 1,
SystemData = 2,
SystemUpdate = 3,
BootImagePackage = 4,
BootImagePackageSafe = 5,
Application = 0x80,
Patch = 0x81,
AddOnContent = 0x82,
Delta = 0x83
}
public enum ContentMetaAttribute : byte
{
None = 0,
IncludesExFatDriver = 1,
Rebootless = 2
}
public enum UpdateType : byte
{
ApplyAsDelta = 0,
Overwrite = 1,
Create = 2
}
}

View file

@ -0,0 +1,47 @@
using System;
using System.Runtime.InteropServices;
using LibHac.Common;
namespace LibHac.Ncm
{
[StructLayout(LayoutKind.Sequential, Size = 0x10)]
public struct ContentId : IEquatable<ContentId>, IComparable<ContentId>, IComparable
{
public readonly Id128 Id;
public ContentId(ulong high, ulong low)
{
Id = new Id128(high, low);
}
public ContentId(ReadOnlySpan<byte> uid)
{
Id = new Id128(uid);
}
public bool Equals(ContentId other) => Id == other.Id;
public override bool Equals(object obj) => obj is ContentId other && Equals(other);
public override int GetHashCode() => Id.GetHashCode();
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
public int CompareTo(ContentId other) => Id.CompareTo(other.Id);
public int CompareTo(object obj)
{
if (obj is null) return 1;
return obj is ContentId other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(ContentId)}");
}
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
public void ToBytes(Span<byte> output) => Id.ToBytes(output);
public static bool operator ==(ContentId left, ContentId right) => left.Equals(right);
public static bool operator !=(ContentId left, ContentId right) => !left.Equals(right);
public static bool operator <(ContentId left, ContentId right) => left.CompareTo(right) < 0;
public static bool operator >(ContentId left, ContentId right) => left.CompareTo(right) > 0;
public static bool operator <=(ContentId left, ContentId right) => left.CompareTo(right) <= 0;
public static bool operator >=(ContentId left, ContentId right) => left.CompareTo(right) >= 0;
}
}

View file

@ -8,8 +8,8 @@ namespace LibHac.Ncm
{
public ulong TitleId { get; private set; }
public uint Version { get; private set; }
public byte Type { get; private set; }
public byte Flags { get; private set; }
public ContentMetaType Type { get; private set; }
public ContentMetaAttribute Attributes { get; private set; }
public int ExportSize => 0x10;
private bool _isFrozen;
@ -20,8 +20,8 @@ namespace LibHac.Ncm
BinaryPrimitives.WriteUInt64LittleEndian(output, TitleId);
BinaryPrimitives.WriteUInt32LittleEndian(output.Slice(8), Version);
output[0xC] = Type;
output[0xD] = Flags;
output[0xC] = (byte)Type;
output[0xD] = (byte)Attributes;
}
public void FromBytes(ReadOnlySpan<byte> input)
@ -31,8 +31,8 @@ namespace LibHac.Ncm
TitleId = BinaryPrimitives.ReadUInt64LittleEndian(input);
Version = BinaryPrimitives.ReadUInt32LittleEndian(input.Slice(8));
Type = input[0xC];
Flags = input[0xD];
Type = (ContentMetaType)input[0xC];
Attributes = (ContentMetaAttribute)input[0xD];
}
public void Freeze() => _isFrozen = true;
@ -40,7 +40,7 @@ namespace LibHac.Ncm
public bool Equals(ContentMetaKey other)
{
return other != null && TitleId == other.TitleId && Version == other.Version &&
Type == other.Type && Flags == other.Flags;
Type == other.Type && Attributes == other.Attributes;
}
public override bool Equals(object obj)
@ -56,7 +56,7 @@ namespace LibHac.Ncm
int hashCode = TitleId.GetHashCode();
hashCode = (hashCode * 397) ^ (int)Version;
hashCode = (hashCode * 397) ^ Type.GetHashCode();
hashCode = (hashCode * 397) ^ Flags.GetHashCode();
hashCode = (hashCode * 397) ^ Attributes.GetHashCode();
return hashCode;
// ReSharper restore NonReadonlyMemberInGetHashCode
}
@ -72,7 +72,7 @@ namespace LibHac.Ncm
if (versionComparison != 0) return versionComparison;
int typeComparison = Type.CompareTo(other.Type);
if (typeComparison != 0) return typeComparison;
return Flags.CompareTo(other.Flags);
return Attributes.CompareTo(other.Attributes);
}
public int CompareTo(object obj)

View file

@ -0,0 +1,20 @@
using System.Runtime.InteropServices;
namespace LibHac.Ncm
{
[StructLayout(LayoutKind.Sequential, Size = 0x18, Pack = 1)]
public struct ContentInfo
{
public ContentId contentId;
public uint size1;
public ushort size2;
private ContentType contentType;
private byte IdOffset;
}
public class ApplicationContentMetaKey
{
public ContentMetaKey Key { get; set; }
public ulong TitleId { get; set; }
}
}

View file

@ -0,0 +1,32 @@
using System;
namespace LibHac.Ncm
{
public interface IContentMetaDatabase
{
Result Set(ContentMetaKey key, ReadOnlySpan<byte> value);
Result Get(out long valueSize, ContentMetaKey key, Span<byte> valueBuffer);
Result Remove(ContentMetaKey key);
Result GetContentIdByType(out ContentId contentId, ContentMetaKey key, ContentType type);
Result ListContentInfo(out int count, Span<ContentInfo> outInfo, ContentMetaKey key, int startIndex);
Result List(out int totalEntryCount, out int matchedEntryCount, Span<ContentMetaKey> keys, ContentMetaType type,
ulong applicationTitleId, ulong minTitleId, ulong maxTitleId, ContentMetaAttribute attributes);
Result GetLatestContentMetaKey(out ContentMetaKey key, ulong titleId);
Result ListApplication(out int totalEntryCount, out int matchedEntryCount, Span<ApplicationContentMetaKey> keys, ContentMetaType type);
Result Has(out bool hasKey, ContentMetaKey key);
Result HasAll(out bool hasAllKeys, ReadOnlySpan<ContentMetaKey> key);
Result GetSize(out long size, ContentMetaKey key);
Result GetRequiredSystemVersion(out int version, ContentMetaKey key);
Result GetPatchId(out ulong titleId, ContentMetaKey key);
Result DisableForcibly();
Result LookupOrphanContent(Span<bool> outOrphaned, ReadOnlySpan<ContentId> contentIds);
Result Commit();
Result HasContent(out bool hasContent, ContentMetaKey key, ContentId contentId);
Result ListContentMetaInfo(out int entryCount, Span<ContentMetaKey> outInfo, ContentMetaKey key, int startIndex);
Result GetAttributes(out ContentMetaAttribute attributes, ContentMetaKey key);
Result GetRequiredApplicationVersion(out int version, ContentMetaKey key);
//Result GetContentIdByTypeAndIdOffset(out ContentId contentId, ContentMetaKey key, ContentType type, byte idOffset);
}
}

View file

@ -0,0 +1,37 @@
using System;
using LibHac.Fs;
namespace LibHac.Ncm
{
public interface IContentStorage
{
Result GeneratePlaceHolderId(out PlaceHolderId placeHolderId);
Result CreatePlaceHolder(PlaceHolderId placeHolderId, ContentId contentId, long fileSize);
Result DeletePlaceHolder(PlaceHolderId placeHolderId);
Result HasPlaceHolder(out bool hasPlaceHolder, PlaceHolderId placeHolderId);
Result WritePlaceHolder(PlaceHolderId placeHolderId, long offset, ReadOnlySpan<byte> buffer);
Result Register(PlaceHolderId placeHolderId, ContentId contentId);
Result Delete(ContentId contentId);
Result Has(out bool hasContent, ContentId contentId);
Result GetPath(Span<byte> outPath, ContentId contentId);
Result GetPlaceHolderPath(Span<byte> outPath, PlaceHolderId placeHolderId);
Result CleanupAllPlaceHolder();
Result ListPlaceHolder(out int count, Span<PlaceHolderId> placeHolderIds);
Result GetContentCount(out int count);
Result ListContentId(out int count, Span<ContentId> contentIds, int startOffset);
Result GetSizeFromContentId(out long size, ContentId contentId);
Result DisableForcibly();
Result RevertToPlaceHolder(PlaceHolderId placeHolderId, ContentId oldContentId, ContentId newContentId);
Result SetPlaceHolderSize(PlaceHolderId placeHolderId, long size);
Result ReadContentIdFile(Span<byte> buffer, long size, ContentId contentId, long offset);
Result GetRightsIdFromPlaceHolderId(out RightsId rightsId, out byte keyGeneration, PlaceHolderId placeHolderId);
Result GetRightsIdFromContentId(out RightsId rightsId, out byte keyGeneration, ContentId contentId);
Result WriteContentForDebug(ContentId contentId, long offset, ReadOnlySpan<byte> buffer);
Result GetFreeSpaceSize(out long size);
Result GetTotalSpaceSize(out long size);
Result FlushPlaceHolder();
//Result GetSizeFromPlaceHolderId(out long size, PlaceHolderId placeHolderId);
//Result RepairInvalidFileAttribute();
//Result GetRightsIdFromPlaceHolderIdWithCache(out RightsId rightsId, out byte keyGeneration, PlaceHolderId placeHolderId, out ContentId cacheContentId);
}
}

View file

@ -0,0 +1,47 @@
using System;
using System.Runtime.InteropServices;
using LibHac.Common;
namespace LibHac.Ncm
{
[StructLayout(LayoutKind.Sequential, Size = 0x10)]
public struct PlaceHolderId : IEquatable<PlaceHolderId>, IComparable<PlaceHolderId>, IComparable
{
public readonly Id128 Id;
public PlaceHolderId(ulong high, ulong low)
{
Id = new Id128(high, low);
}
public PlaceHolderId(ReadOnlySpan<byte> uid)
{
Id = new Id128(uid);
}
public bool Equals(PlaceHolderId other) => Id == other.Id;
public override bool Equals(object obj) => obj is PlaceHolderId other && Equals(other);
public override int GetHashCode() => Id.GetHashCode();
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
public int CompareTo(PlaceHolderId other) => Id.CompareTo(other.Id);
public int CompareTo(object obj)
{
if (obj is null) return 1;
return obj is PlaceHolderId other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(PlaceHolderId)}");
}
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
public void ToBytes(Span<byte> output) => Id.ToBytes(output);
public static bool operator ==(PlaceHolderId left, PlaceHolderId right) => left.Equals(right);
public static bool operator !=(PlaceHolderId left, PlaceHolderId right) => !left.Equals(right);
public static bool operator <(PlaceHolderId left, PlaceHolderId right) => left.CompareTo(right) < 0;
public static bool operator >(PlaceHolderId left, PlaceHolderId right) => left.CompareTo(right) > 0;
public static bool operator <=(PlaceHolderId left, PlaceHolderId right) => left.CompareTo(right) <= 0;
public static bool operator >=(PlaceHolderId left, PlaceHolderId right) => left.CompareTo(right) >= 0;
}
}

View file

@ -6,6 +6,7 @@ using System.Linq;
using LibHac.Fs;
using LibHac.Fs.NcaUtils;
using LibHac.Fs.Save;
using LibHac.Ncm;
namespace LibHac
{
@ -81,7 +82,7 @@ namespace LibHac
nca = new SwitchFsNca(new Nca(Keyset, storage));
nca.NcaId = GetNcaFilename(fileEntry.Name, nca);
string extension = nca.Nca.Header.ContentType == ContentType.Meta ? ".cnmt.nca" : ".nca";
string extension = nca.Nca.Header.ContentType == Fs.NcaUtils.ContentType.Meta ? ".cnmt.nca" : ".nca";
nca.Filename = nca.NcaId + extension;
}
catch (MissingKeyException ex)
@ -131,7 +132,7 @@ namespace LibHac
private void ReadTitles()
{
foreach (SwitchFsNca nca in Ncas.Values.Where(x => x.Nca.Header.ContentType == ContentType.Meta))
foreach (SwitchFsNca nca in Ncas.Values.Where(x => x.Nca.Header.ContentType == Fs.NcaUtils.ContentType.Meta))
{
try
{
@ -160,11 +161,11 @@ namespace LibHac
switch (content.Type)
{
case CnmtContentType.Program:
case CnmtContentType.Data:
case Ncm.ContentType.Program:
case Ncm.ContentType.Data:
title.MainNca = contentNca;
break;
case CnmtContentType.Control:
case Ncm.ContentType.Control:
title.ControlNca = contentNca;
break;
}
@ -201,7 +202,7 @@ namespace LibHac
private void CreateApplications()
{
foreach (Title title in Titles.Values.Where(x => x.Metadata.Type >= TitleType.Application))
foreach (Title title in Titles.Values.Where(x => x.Metadata.Type >= ContentMetaType.Application))
{
Cnmt meta = title.Metadata;
ulong appId = meta.ApplicationTitleId;
@ -229,7 +230,7 @@ namespace LibHac
private string GetNcaFilename(string name, SwitchFsNca nca)
{
if (nca.Nca.Header.ContentType != ContentType.Meta || !name.EndsWith(".cnmt.nca"))
if (nca.Nca.Header.ContentType != Fs.NcaUtils.ContentType.Meta || !name.EndsWith(".cnmt.nca"))
{
return Path.GetFileNameWithoutExtension(name);
}
@ -343,16 +344,16 @@ namespace LibHac
switch (title.Metadata.Type)
{
case TitleType.Application:
case ContentMetaType.Application:
Main = title;
break;
case TitleType.Patch:
case ContentMetaType.Patch:
Patch = title;
break;
case TitleType.AddOnContent:
case ContentMetaType.AddOnContent:
AddOnContent.Add(title);
break;
case TitleType.Delta:
case ContentMetaType.Delta:
break;
}