Update to LibHac v0.14.3 (#2925)

* Update to LibHac v0.14.3

* Fix loading NCAs that don't have a data partition
This commit is contained in:
Alex Barney
2021-12-23 09:55:50 -07:00
committed by GitHub
parent cb43cc7e32
commit aa932a6df1
33 changed files with 554 additions and 406 deletions

View File

@ -14,6 +14,7 @@ using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using Path = System.IO.Path;
namespace Ryujinx.HLE.FileSystem.Content
{
@ -203,40 +204,37 @@ namespace Ryujinx.HLE.FileSystem.Content
foreach (var ncaPath in fs.EnumerateEntries("*.cnmt.nca", SearchOptions.Default))
{
fs.OpenFile(out IFile ncaFile, ncaPath.FullPath.ToU8Span(), OpenMode.Read);
using (ncaFile)
using var ncaFile = new UniqueRef<IFile>();
fs.OpenFile(ref ncaFile.Ref(), ncaPath.FullPath.ToU8Span(), OpenMode.Read);
var nca = new Nca(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage());
if (nca.Header.ContentType != NcaContentType.Meta)
{
var nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
if (nca.Header.ContentType != NcaContentType.Meta)
{
Logger.Warning?.Print(LogClass.Application, $"{ncaPath} is not a valid metadata file");
Logger.Warning?.Print(LogClass.Application, $"{ncaPath} is not a valid metadata file");
continue;
}
continue;
}
using var pfs0 = nca.OpenFileSystem(0, integrityCheckLevel);
using var pfs0 = nca.OpenFileSystem(0, integrityCheckLevel);
using var cnmtFile = new UniqueRef<IFile>();
pfs0.OpenFile(out IFile cnmtFile, pfs0.EnumerateEntries().Single().FullPath.ToU8Span(), OpenMode.Read);
pfs0.OpenFile(ref cnmtFile.Ref(), pfs0.EnumerateEntries().Single().FullPath.ToU8Span(), OpenMode.Read);
using (cnmtFile)
{
var cnmt = new Cnmt(cnmtFile.AsStream());
var cnmt = new Cnmt(cnmtFile.Get.AsStream());
if (cnmt.Type != ContentMetaType.AddOnContent || (cnmt.TitleId & 0xFFFFFFFFFFFFE000) != aocBaseId)
{
continue;
}
if (cnmt.Type != ContentMetaType.AddOnContent || (cnmt.TitleId & 0xFFFFFFFFFFFFE000) != aocBaseId)
{
continue;
}
string ncaId = BitConverter.ToString(cnmt.ContentEntries[0].NcaId).Replace("-", "").ToLower();
if (!_aocData.TryAdd(cnmt.TitleId, new AocItem(containerPath, $"{ncaId}.nca", true)))
{
Logger.Warning?.Print(LogClass.Application, $"Duplicate AddOnContent detected. TitleId {cnmt.TitleId:X16}");
}
else
{
Logger.Info?.Print(LogClass.Application, $"Found AddOnContent with TitleId {cnmt.TitleId:X16}");
}
}
string ncaId = BitConverter.ToString(cnmt.ContentEntries[0].NcaId).Replace("-", "").ToLower();
if (!_aocData.TryAdd(cnmt.TitleId, new AocItem(containerPath, $"{ncaId}.nca", true)))
{
Logger.Warning?.Print(LogClass.Application, $"Duplicate AddOnContent detected. TitleId {cnmt.TitleId:X16}");
}
else
{
Logger.Info?.Print(LogClass.Application, $"Found AddOnContent with TitleId {cnmt.TitleId:X16}");
}
}
}
@ -272,24 +270,24 @@ namespace Ryujinx.HLE.FileSystem.Content
if (_aocData.TryGetValue(aocTitleId, out AocItem aoc) && aoc.Enabled)
{
var file = new FileStream(aoc.ContainerPath, FileMode.Open, FileAccess.Read);
using var ncaFile = new UniqueRef<IFile>();
PartitionFileSystem pfs;
IFile ncaFile;
switch (Path.GetExtension(aoc.ContainerPath))
{
case ".xci":
pfs = new Xci(_virtualFileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure);
pfs.OpenFile(out ncaFile, aoc.NcaPath.ToU8Span(), OpenMode.Read);
pfs.OpenFile(ref ncaFile.Ref(), aoc.NcaPath.ToU8Span(), OpenMode.Read);
break;
case ".nsp":
pfs = new PartitionFileSystem(file.AsStorage());
pfs.OpenFile(out ncaFile, aoc.NcaPath.ToU8Span(), OpenMode.Read);
pfs.OpenFile(ref ncaFile.Ref(), aoc.NcaPath.ToU8Span(), OpenMode.Read);
break;
default:
return false; // Print error?
}
aocStorage = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage()).OpenStorage(NcaSectionType.Data, integrityCheckLevel);
aocStorage = new Nca(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage()).OpenStorage(NcaSectionType.Data, integrityCheckLevel);
return true;
}
@ -625,18 +623,18 @@ namespace Ryujinx.HLE.FileSystem.Content
private IFile OpenPossibleFragmentedFile(IFileSystem filesystem, string path, OpenMode mode)
{
IFile file;
using var file = new UniqueRef<IFile>();
if (filesystem.FileExists($"{path}/00"))
{
filesystem.OpenFile(out file, $"{path}/00".ToU8Span(), mode);
filesystem.OpenFile(ref file.Ref(), $"{path}/00".ToU8Span(), mode);
}
else
{
filesystem.OpenFile(out file, path.ToU8Span(), mode);
filesystem.OpenFile(ref file.Ref(), path.ToU8Span(), mode);
}
return file;
return file.Release();
}
private Stream GetZipStream(ZipArchiveEntry entry)
@ -753,9 +751,11 @@ namespace Ryujinx.HLE.FileSystem.Content
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
if (fs.OpenFile(out IFile metaFile, cnmtPath.ToU8Span(), OpenMode.Read).IsSuccess())
using var metaFile = new UniqueRef<IFile>();
if (fs.OpenFile(ref metaFile.Ref(), cnmtPath.ToU8Span(), OpenMode.Read).IsSuccess())
{
var meta = new Cnmt(metaFile.AsStream());
var meta = new Cnmt(metaFile.Get.AsStream());
if (meta.Type == ContentMetaType.SystemUpdate)
{
@ -781,9 +781,11 @@ namespace Ryujinx.HLE.FileSystem.Content
var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess())
using var systemVersionFile = new UniqueRef<IFile>();
if (romfs.OpenFile(ref systemVersionFile.Ref(), "/file".ToU8Span(), OpenMode.Read).IsSuccess())
{
systemVersion = new SystemVersion(systemVersionFile.AsStream());
systemVersion = new SystemVersion(systemVersionFile.Get.AsStream());
}
}
}
@ -818,9 +820,11 @@ namespace Ryujinx.HLE.FileSystem.Content
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
if (fs.OpenFile(out IFile metaFile, cnmtPath.ToU8Span(), OpenMode.Read).IsSuccess())
using var metaFile = new UniqueRef<IFile>();
if (fs.OpenFile(ref metaFile.Ref(), cnmtPath.ToU8Span(), OpenMode.Read).IsSuccess())
{
var meta = new Cnmt(metaFile.AsStream());
var meta = new Cnmt(metaFile.Get.AsStream());
IStorage contentStorage = contentNcaStream.AsStorage();
if (contentStorage.GetSize(out long size).IsSuccess())
@ -887,9 +891,11 @@ namespace Ryujinx.HLE.FileSystem.Content
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
if (fs.OpenFile(out IFile metaFile, cnmtPath.ToU8Span(), OpenMode.Read).IsSuccess())
using var metaFile = new UniqueRef<IFile>();
if (fs.OpenFile(ref metaFile.Ref(), cnmtPath.ToU8Span(), OpenMode.Read).IsSuccess())
{
var meta = new Cnmt(metaFile.AsStream());
var meta = new Cnmt(metaFile.Get.AsStream());
if (meta.Type == ContentMetaType.SystemUpdate)
{
@ -903,9 +909,11 @@ namespace Ryujinx.HLE.FileSystem.Content
{
var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess())
using var systemVersionFile = new UniqueRef<IFile>();
if (romfs.OpenFile(ref systemVersionFile.Ref(), "/file".ToU8Span(), OpenMode.Read).IsSuccess())
{
systemVersion = new SystemVersion(systemVersionFile.AsStream());
systemVersion = new SystemVersion(systemVersionFile.Get.AsStream());
}
}
@ -952,9 +960,11 @@ namespace Ryujinx.HLE.FileSystem.Content
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
if (fs.OpenFile(out IFile metaFile, cnmtPath.ToU8Span(), OpenMode.Read).IsSuccess())
using var metaFile = new UniqueRef<IFile>();
if (fs.OpenFile(ref metaFile.Ref(), cnmtPath.ToU8Span(), OpenMode.Read).IsSuccess())
{
var meta = new Cnmt(metaFile.AsStream());
var meta = new Cnmt(metaFile.Get.AsStream());
if (contentStorage.GetSize(out long size).IsSuccess())
{
@ -1020,9 +1030,11 @@ namespace Ryujinx.HLE.FileSystem.Content
{
var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess())
using var systemVersionFile = new UniqueRef<IFile>();
if (romfs.OpenFile(ref systemVersionFile.Ref(), "/file".ToU8Span(), OpenMode.Read).IsSuccess())
{
return new SystemVersion(systemVersionFile.AsStream());
return new SystemVersion(systemVersionFile.Get.AsStream());
}
}

View File

@ -3,25 +3,23 @@ using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Fsa;
using LibHac.FsSrv.FsCreator;
using LibHac.FsSystem;
namespace Ryujinx.HLE.FileSystem
{
public class EncryptedFileSystemCreator : IEncryptedFileSystemCreator
{
public Result Create(out ReferenceCountedDisposable<IFileSystem> encryptedFileSystem, ReferenceCountedDisposable<IFileSystem> baseFileSystem,
EncryptedFsKeyId keyId, in EncryptionSeed encryptionSeed)
{
UnsafeHelpers.SkipParamInit(out encryptedFileSystem);
if (keyId < EncryptedFsKeyId.Save || keyId > EncryptedFsKeyId.CustomStorage)
public Result Create(ref SharedRef<IFileSystem> outEncryptedFileSystem,
ref SharedRef<IFileSystem> baseFileSystem, IEncryptedFileSystemCreator.KeyId idIndex,
in EncryptionSeed encryptionSeed)
{
if (idIndex < IEncryptedFileSystemCreator.KeyId.Save || idIndex > IEncryptedFileSystemCreator.KeyId.CustomStorage)
{
return ResultFs.InvalidArgument.Log();
}
// Force all-zero keys for now since people can open the emulator with different keys or sd seeds sometimes
var fs = new AesXtsFileSystem(baseFileSystem, new byte[0x32], 0x4000);
encryptedFileSystem = new ReferenceCountedDisposable<IFileSystem>(fs);
// Todo: Reenable when AesXtsFileSystem is fixed
outEncryptedFileSystem = SharedRef<IFileSystem>.CreateMove(ref baseFileSystem);
return Result.Success;
}

View File

@ -17,6 +17,8 @@ using System.Buffers.Text;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using Path = System.IO.Path;
using RightsId = LibHac.Fs.RightsId;
namespace Ryujinx.HLE.FileSystem
@ -240,11 +242,13 @@ namespace Ryujinx.HLE.FileSystem
{
foreach (DirectoryEntryEx ticketEntry in fs.EnumerateEntries("/", "*.tik"))
{
Result result = fs.OpenFile(out IFile ticketFile, ticketEntry.FullPath.ToU8Span(), OpenMode.Read);
using var ticketFile = new UniqueRef<IFile>();
Result result = fs.OpenFile(ref ticketFile.Ref(), ticketEntry.FullPath.ToU8Span(), OpenMode.Read);
if (result.IsSuccess())
{
Ticket ticket = new Ticket(ticketFile.AsStream());
Ticket ticket = new Ticket(ticketFile.Get.AsStream());
if (ticket.TitleKeyType == TitleKeyType.Common)
{
@ -280,12 +284,14 @@ namespace Ryujinx.HLE.FileSystem
{
Span<SaveDataInfo> info = stackalloc SaveDataInfo[8];
Result rc = hos.Fs.OpenSaveDataIterator(out var iterator, spaceId);
using var iterator = new UniqueRef<SaveDataIterator>();
Result rc = hos.Fs.OpenSaveDataIterator(ref iterator.Ref(), spaceId);
if (rc.IsFailure()) return rc;
while (true)
{
rc = iterator.ReadSaveDataInfo(out long count, info);
rc = iterator.Get.ReadSaveDataInfo(out long count, info);
if (rc.IsFailure()) return rc;
if (count == 0)