diff options
| author | Mary <1760003+Thog@users.noreply.github.com> | 2021-07-13 16:48:54 +0200 |
|---|---|---|
| committer | Mary <1760003+Thog@users.noreply.github.com> | 2021-07-13 16:48:54 +0200 |
| commit | 208ba1dde2b9a4d31446ace2bba8f0d641d2e300 (patch) | |
| tree | c7478e7eb87061400bab37daf4f2f69cf387d9f2 /Ryujinx.HLE/HOS/ApplicationLoader.cs | |
| parent | 997380d48cb3b74e2438cee7fc3b017d6b59b714 (diff) | |
Revert LibHac update
Users are facing save destruction on failing extra data update apparently
Diffstat (limited to 'Ryujinx.HLE/HOS/ApplicationLoader.cs')
| -rw-r--r-- | Ryujinx.HLE/HOS/ApplicationLoader.cs | 198 |
1 files changed, 48 insertions, 150 deletions
diff --git a/Ryujinx.HLE/HOS/ApplicationLoader.cs b/Ryujinx.HLE/HOS/ApplicationLoader.cs index f794d199..0d48cc81 100644 --- a/Ryujinx.HLE/HOS/ApplicationLoader.cs +++ b/Ryujinx.HLE/HOS/ApplicationLoader.cs @@ -4,17 +4,15 @@ using LibHac.Account; using LibHac.Common; using LibHac.Fs; using LibHac.Fs.Fsa; -using LibHac.Fs.Shim; using LibHac.FsSystem; using LibHac.FsSystem.NcaUtils; -using LibHac.Loader; -using LibHac.Ncm; using LibHac.Ns; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.Loaders.Executables; +using Ryujinx.HLE.Loaders.Npdm; using System; using System.Collections.Generic; using System.Globalization; @@ -59,14 +57,14 @@ namespace Ryujinx.HLE.HOS public string TitleName => _titleName; public string DisplayVersion => _displayVersion; - public ulong TitleId { get; private set; } - public bool TitleIs64Bit { get; private set; } + public ulong TitleId { get; private set; } + public bool TitleIs64Bit { get; private set; } public string TitleIdText => TitleId.ToString("x16"); public ApplicationLoader(Switch device) { - _device = device; + _device = device; _controlData = new BlitStruct<ApplicationControlProperty>(1); } @@ -79,7 +77,7 @@ namespace Ryujinx.HLE.HOS LocalFileSystem codeFs = new LocalFileSystem(exeFsDir); - MetaLoader metaData = ReadNpdm(codeFs); + Npdm metaData = ReadNpdm(codeFs); _device.Configuration.VirtualFileSystem.ModLoader.CollectMods(new[] { TitleId }, _device.Configuration.VirtualFileSystem.ModLoader.GetModsBasePath()); @@ -93,8 +91,8 @@ namespace Ryujinx.HLE.HOS public static (Nca main, Nca patch, Nca control) GetGameData(VirtualFileSystem fileSystem, PartitionFileSystem pfs, int programIndex) { - Nca mainNca = null; - Nca patchNca = null; + Nca mainNca = null; + Nca patchNca = null; Nca controlNca = null; fileSystem.ImportTickets(pfs); @@ -204,7 +202,7 @@ namespace Ryujinx.HLE.HOS public void LoadXci(string xciFile) { FileStream file = new FileStream(xciFile, FileMode.Open, FileAccess.Read); - Xci xci = new Xci(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage()); + Xci xci = new Xci(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage()); if (!xci.HasPartition(XciPartitionType.Secure)) { @@ -222,8 +220,6 @@ namespace Ryujinx.HLE.HOS try { (mainNca, patchNca, controlNca) = GetGameData(_device.Configuration.VirtualFileSystem, securePartition, _device.Configuration.UserChannelPersistence.Index); - - RegisterProgramMapInfo(securePartition).ThrowIfFailure(); } catch (Exception e) { @@ -248,8 +244,8 @@ namespace Ryujinx.HLE.HOS public void LoadNsp(string nspFile) { - FileStream file = new FileStream(nspFile, FileMode.Open, FileAccess.Read); - PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage()); + FileStream file = new FileStream(nspFile, FileMode.Open, FileAccess.Read); + PartitionFileSystem nsp = new PartitionFileSystem(file.AsStorage()); Nca mainNca; Nca patchNca; @@ -258,8 +254,6 @@ namespace Ryujinx.HLE.HOS try { (mainNca, patchNca, controlNca) = GetGameData(_device.Configuration.VirtualFileSystem, nsp, _device.Configuration.UserChannelPersistence.Index); - - RegisterProgramMapInfo(nsp).ThrowIfFailure(); } catch (Exception e) { @@ -292,7 +286,7 @@ namespace Ryujinx.HLE.HOS public void LoadNca(string ncaFile) { FileStream file = new FileStream(ncaFile, FileMode.Open, FileAccess.Read); - Nca nca = new Nca(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage(false)); + Nca nca = new Nca(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage(false)); LoadNca(nca, null, null); } @@ -306,8 +300,8 @@ namespace Ryujinx.HLE.HOS return; } - IStorage dataStorage = null; - IFileSystem codeFs = null; + IStorage dataStorage = null; + IFileSystem codeFs = null; (Nca updatePatchNca, Nca updateControlNca) = GetGameUpdateData(_device.Configuration.VirtualFileSystem, mainNca.Header.TitleId.ToString("x16"), _device.Configuration.UserChannelPersistence.Index, out _); @@ -372,7 +366,7 @@ namespace Ryujinx.HLE.HOS return; } - MetaLoader metaData = ReadNpdm(codeFs); + Npdm metaData = ReadNpdm(codeFs); _device.Configuration.VirtualFileSystem.ModLoader.CollectMods(_device.Configuration.ContentManager.GetAocTitleIds().Prepend(TitleId), _device.Configuration.VirtualFileSystem.ModLoader.GetModsBasePath()); @@ -406,12 +400,9 @@ namespace Ryujinx.HLE.HOS _device.Configuration.VirtualFileSystem.SetRomFs(newStorage.AsStream(FileAccess.Read)); } - // Don't create save data for system programs. - if (TitleId != 0 && (TitleId < SystemProgramId.Start.Value || TitleId > SystemAppletId.End.Value)) + if (TitleId != 0) { - // Multi-program applications can technically use any program ID for the main program, but in practice they always use 0 in the low nibble. - // We'll know if this changes in the future because stuff will get errors when trying to mount the correct save. - EnsureSaveData(new ApplicationId(TitleId & ~0xFul)); + EnsureSaveData(new ApplicationId(TitleId)); } LoadExeFs(codeFs, metaData); @@ -420,11 +411,11 @@ namespace Ryujinx.HLE.HOS } // Sets TitleId, so be sure to call before using it - private MetaLoader ReadNpdm(IFileSystem fs) + private Npdm ReadNpdm(IFileSystem fs) { Result result = fs.OpenFile(out IFile npdmFile, "/main.npdm".ToU8Span(), OpenMode.Read); - MetaLoader metaData; + Npdm metaData; if (ResultFs.PathNotFound.Includes(result)) { @@ -434,20 +425,11 @@ namespace Ryujinx.HLE.HOS } else { - npdmFile.GetSize(out long fileSize).ThrowIfFailure(); - - var npdmBuffer = new byte[fileSize]; - npdmFile.Read(out _, 0, npdmBuffer).ThrowIfFailure(); - - metaData = new MetaLoader(); - metaData.Load(npdmBuffer).ThrowIfFailure(); + metaData = new Npdm(npdmFile.AsStream()); } - metaData.GetNpdm(out var npdm).ThrowIfFailure(); - - TitleId = npdm.Aci.Value.ProgramId.Value; - TitleIs64Bit = (npdm.Meta.Value.Flags & 1) != 0; - _device.System.LibHacHorizonManager.ArpIReader.ApplicationId = new LibHac.ApplicationId(TitleId); + TitleId = metaData.Aci0.TitleId; + TitleIs64Bit = metaData.Is64Bit; return metaData; } @@ -455,7 +437,7 @@ namespace Ryujinx.HLE.HOS private static void ReadControlData(Switch device, Nca controlNca, ref BlitStruct<ApplicationControlProperty> controlData, ref string titleName, ref string displayVersion) { IFileSystem controlFs = controlNca.OpenFileSystem(NcaSectionType.Data, device.System.FsIntegrityCheckLevel); - Result result = controlFs.OpenFile(out IFile controlFile, "/control.nacp".ToU8Span(), OpenMode.Read); + Result result = controlFs.OpenFile(out IFile controlFile, "/control.nacp".ToU8Span(), OpenMode.Read); if (result.IsSuccess()) { @@ -479,7 +461,7 @@ namespace Ryujinx.HLE.HOS } } - private void LoadExeFs(IFileSystem codeFs, MetaLoader metaData = null) + private void LoadExeFs(IFileSystem codeFs, Npdm metaData = null) { if (_device.Configuration.VirtualFileSystem.ModLoader.ReplaceExefsPartition(TitleId, ref codeFs)) { @@ -537,26 +519,22 @@ namespace Ryujinx.HLE.HOS Ptc.Initialize(TitleIdText, DisplayVersion, usePtc, _device.Configuration.MemoryManagerMode); - metaData.GetNpdm(out Npdm npdm).ThrowIfFailure(); - ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, new ProgramInfo(in npdm), executables: programs); + ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, executables: programs); _device.Configuration.VirtualFileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine); } public void LoadProgram(string filePath) { - MetaLoader metaData = GetDefaultNpdm(); - metaData.GetNpdm(out Npdm npdm).ThrowIfFailure(); - ProgramInfo programInfo = new ProgramInfo(in npdm); - - bool isNro = Path.GetExtension(filePath).ToLower() == ".nro"; + Npdm metaData = GetDefaultNpdm(); + bool isNro = Path.GetExtension(filePath).ToLower() == ".nro"; IExecutable executable; if (isNro) { - FileStream input = new FileStream(filePath, FileMode.Open); - NroExecutable obj = new NroExecutable(input.AsStorage()); + FileStream input = new FileStream(filePath, FileMode.Open); + NroExecutable obj = new NroExecutable(input.AsStorage()); executable = obj; @@ -574,13 +552,13 @@ namespace Ryujinx.HLE.HOS if (asetVersion == 0) { ulong iconOffset = reader.ReadUInt64(); - ulong iconSize = reader.ReadUInt64(); + ulong iconSize = reader.ReadUInt64(); ulong nacpOffset = reader.ReadUInt64(); - ulong nacpSize = reader.ReadUInt64(); + ulong nacpSize = reader.ReadUInt64(); ulong romfsOffset = reader.ReadUInt64(); - ulong romfsSize = reader.ReadUInt64(); + ulong romfsSize = reader.ReadUInt64(); if (romfsSize != 0) { @@ -595,28 +573,28 @@ namespace Ryujinx.HLE.HOS ref ApplicationControlProperty nacp = ref ControlData.Value; - programInfo.Name = nacp.Titles[(int)_device.System.State.DesiredTitleLanguage].Name.ToString(); + metaData.TitleName = nacp.Titles[(int)_device.System.State.DesiredTitleLanguage].Name.ToString(); - if (string.IsNullOrWhiteSpace(programInfo.Name)) + if (string.IsNullOrWhiteSpace(metaData.TitleName)) { - programInfo.Name = nacp.Titles.ToArray().FirstOrDefault(x => x.Name[0] != 0).Name.ToString(); + metaData.TitleName = nacp.Titles.ToArray().FirstOrDefault(x => x.Name[0] != 0).Name.ToString(); } if (nacp.PresenceGroupId != 0) { - programInfo.ProgramId = nacp.PresenceGroupId; + metaData.Aci0.TitleId = nacp.PresenceGroupId; } else if (nacp.SaveDataOwnerId.Value != 0) { - programInfo.ProgramId = nacp.SaveDataOwnerId.Value; + metaData.Aci0.TitleId = nacp.SaveDataOwnerId.Value; } else if (nacp.AddOnContentBaseId != 0) { - programInfo.ProgramId = nacp.AddOnContentBaseId - 0x1000; + metaData.Aci0.TitleId = nacp.AddOnContentBaseId - 0x1000; } else { - programInfo.ProgramId = 0000000000000000; + metaData.Aci0.TitleId = 0000000000000000; } } } @@ -634,107 +612,27 @@ namespace Ryujinx.HLE.HOS _device.Configuration.ContentManager.LoadEntries(_device); - _titleName = programInfo.Name; - TitleId = programInfo.ProgramId; - TitleIs64Bit = (npdm.Meta.Value.Flags & 1) != 0; - _device.System.LibHacHorizonManager.ArpIReader.ApplicationId = new LibHac.ApplicationId(TitleId); + _titleName = metaData.TitleName; + TitleId = metaData.Aci0.TitleId; + TitleIs64Bit = metaData.Is64Bit; // Explicitly null titleid to disable the shader cache Graphics.Gpu.GraphicsConfig.TitleId = null; _device.Gpu.HostInitalized.Set(); - ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, programInfo, executables: executable); + ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, executables: executable); _device.Configuration.VirtualFileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine); } - private MetaLoader GetDefaultNpdm() + private Npdm GetDefaultNpdm() { Assembly asm = Assembly.GetCallingAssembly(); using (Stream npdmStream = asm.GetManifestResourceStream("Ryujinx.HLE.Homebrew.npdm")) { - var npdmBuffer = new byte[npdmStream.Length]; - npdmStream.Read(npdmBuffer); - - var metaLoader = new MetaLoader(); - metaLoader.Load(npdmBuffer).ThrowIfFailure(); - - return metaLoader; - } - } - - private static (ulong applicationId, int programCount) GetMultiProgramInfo(VirtualFileSystem fileSystem, PartitionFileSystem pfs) - { - ulong mainProgramId = 0; - Span<bool> hasIndex = stackalloc bool[0x10]; - - fileSystem.ImportTickets(pfs); - - foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca")) - { - pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); - - Nca nca = new Nca(fileSystem.KeySet, ncaFile.AsStorage()); - - if (nca.Header.ContentType != NcaContentType.Program) - { - continue; - } - - int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); - - if (nca.Header.GetFsHeader(dataIndex).IsPatchSection()) - { - continue; - } - - ulong currentProgramId = nca.Header.TitleId; - ulong currentMainProgramId = currentProgramId & ~0xFFFul; - - if (mainProgramId == 0 && currentMainProgramId != 0) - { - mainProgramId = currentMainProgramId; - } - - if (mainProgramId != currentMainProgramId) - { - // As far as I know there aren't any multi-application game cards containing multi-program applications, - // so because multi-application game cards are the only way we should run into multiple applications - // we'll just return that there's a single program. - return (mainProgramId, 1); - } - - hasIndex[(int)(currentProgramId & 0xF)] = true; - } - - int programCount = 0; - - for (int i = 0; i < hasIndex.Length && hasIndex[i]; i++) - { - programCount++; + return new Npdm(npdmStream); } - - return (mainProgramId, programCount); - } - - private Result RegisterProgramMapInfo(PartitionFileSystem pfs) - { - (ulong applicationId, int programCount) = GetMultiProgramInfo(_device.Configuration.VirtualFileSystem, pfs); - - if (programCount <= 0) - return Result.Success; - - Span<ProgramIndexMapInfo> mapInfo = stackalloc ProgramIndexMapInfo[0x10]; - - for (int i = 0; i < programCount; i++) - { - mapInfo[i].ProgramId = new ProgramId(applicationId + (uint)i); - mapInfo[i].MainProgramId = new ProgramId(applicationId); - mapInfo[i].ProgramIndex = (byte)i; - } - - return _device.System.LibHacHorizonManager.NsClient.Fs.RegisterProgramIndexMapInfo(mapInfo.Slice(0, programCount)); } private Result EnsureSaveData(ApplicationId applicationId) @@ -745,7 +643,7 @@ namespace Ryujinx.HLE.HOS ref ApplicationControlProperty control = ref ControlData.Value; - if (LibHac.Utilities.IsZeros(ControlData.ByteSpan)) + if (LibHac.Utilities.IsEmpty(ControlData.ByteSpan)) { // If the current application doesn't have a loaded control property, create a dummy one // and set the savedata sizes so a user savedata will be created. @@ -759,8 +657,8 @@ namespace Ryujinx.HLE.HOS "No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games."); } - HorizonClient hos = _device.System.LibHacHorizonManager.RyujinxClient; - Result resultCode = hos.Fs.EnsureApplicationCacheStorage(out _, out _, applicationId, ref control); + FileSystemClient fileSystem = _device.Configuration.VirtualFileSystem.FsClient; + Result resultCode = fileSystem.EnsureApplicationCacheStorage(out _, applicationId, ref control); if (resultCode.IsFailure()) { @@ -769,7 +667,7 @@ namespace Ryujinx.HLE.HOS return resultCode; } - resultCode = EnsureApplicationSaveData(hos.Fs, out _, applicationId, ref control, ref user); + resultCode = EnsureApplicationSaveData(fileSystem, out _, applicationId, ref control, ref user); if (resultCode.IsFailure()) { |
