diff options
Diffstat (limited to 'src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs')
-rw-r--r-- | src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs new file mode 100644 index 00000000..58759ddb --- /dev/null +++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs @@ -0,0 +1,133 @@ +using LibHac.Common; +using LibHac.Fs; +using LibHac.Fs.Fsa; +using LibHac.Loader; +using LibHac.Ns; +using LibHac.Tools.FsSystem; +using Ryujinx.Common.Configuration; +using Ryujinx.Common.Logging; +using Ryujinx.HLE.Loaders.Executables; +using Ryujinx.Memory; +using System.Linq; +using static Ryujinx.HLE.HOS.ModLoader; + +namespace Ryujinx.HLE.Loaders.Processes.Extensions +{ + static class FileSystemExtensions + { + public static MetaLoader GetNpdm(this IFileSystem fileSystem) + { + MetaLoader metaLoader = new(); + + if (fileSystem == null || !fileSystem.FileExists(ProcessConst.MainNpdmPath)) + { + Logger.Warning?.Print(LogClass.Loader, "NPDM file not found, using default values!"); + + metaLoader.LoadDefault(); + } + else + { + metaLoader.LoadFromFile(fileSystem); + } + + return metaLoader; + } + + public static ProcessResult Load(this IFileSystem exeFs, Switch device, BlitStruct<ApplicationControlProperty> nacpData, MetaLoader metaLoader, bool isHomebrew = false) + { + ulong programId = metaLoader.GetProgramId(); + + // Replace the whole ExeFs partition by the modded one. + if (device.Configuration.VirtualFileSystem.ModLoader.ReplaceExefsPartition(programId, ref exeFs)) + { + metaLoader = null; + } + + // Reload the MetaLoader in case of ExeFs partition replacement. + metaLoader ??= exeFs.GetNpdm(); + + NsoExecutable[] nsoExecutables = new NsoExecutable[ProcessConst.ExeFsPrefixes.Length]; + + for (int i = 0; i < nsoExecutables.Length; i++) + { + string name = ProcessConst.ExeFsPrefixes[i]; + + if (!exeFs.FileExists($"/{name}")) + { + continue; // File doesn't exist, skip. + } + + Logger.Info?.Print(LogClass.Loader, $"Loading {name}..."); + + using var nsoFile = new UniqueRef<IFile>(); + + exeFs.OpenFile(ref nsoFile.Ref, $"/{name}".ToU8Span(), OpenMode.Read).ThrowIfFailure(); + + nsoExecutables[i] = new NsoExecutable(nsoFile.Release().AsStorage(), name); + } + + // ExeFs file replacements. + ModLoadResult modLoadResult = device.Configuration.VirtualFileSystem.ModLoader.ApplyExefsMods(programId, nsoExecutables); + + // Take the Npdm from mods if present. + if (modLoadResult.Npdm != null) + { + metaLoader = modLoadResult.Npdm; + } + + // Collect the Nsos, ignoring ones that aren't used. + nsoExecutables = nsoExecutables.Where(x => x != null).ToArray(); + + // Apply Nsos patches. + device.Configuration.VirtualFileSystem.ModLoader.ApplyNsoPatches(programId, nsoExecutables); + + // Don't use PTC if ExeFS files have been replaced. + bool enablePtc = device.System.EnablePtc && !modLoadResult.Modified; + if (!enablePtc) + { + Logger.Warning?.Print(LogClass.Ptc, $"Detected unsupported ExeFs modifications. PTC disabled."); + } + + // We allow it for nx-hbloader because it can be used to launch homebrew. + bool allowCodeMemoryForJit = programId == 0x010000000000100DUL || isHomebrew; + + string programName = ""; + + if (!isHomebrew && programId > 0x010000000000FFFF) + { + programName = nacpData.Value.Title[(int)device.System.State.DesiredTitleLanguage].NameString.ToString(); + + if (string.IsNullOrWhiteSpace(programName)) + { + programName = nacpData.Value.Title.ItemsRo.ToArray().FirstOrDefault(x => x.Name[0] != 0).NameString.ToString(); + } + } + + // Initialize GPU. + Graphics.Gpu.GraphicsConfig.TitleId = $"{programId:x16}"; + device.Gpu.HostInitalized.Set(); + + if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible)) + { + device.Configuration.MemoryManagerMode = MemoryManagerMode.SoftwarePageTable; + } + + ProcessResult processResult = ProcessLoaderHelper.LoadNsos( + device, + device.System.KernelContext, + metaLoader, + nacpData.Value, + enablePtc, + allowCodeMemoryForJit, + programName, + metaLoader.GetProgramId(), + null, + nsoExecutables); + + // TODO: This should be stored using ProcessId instead. + device.System.LibHacHorizonManager.ArpIReader.ApplicationId = new LibHac.ApplicationId(metaLoader.GetProgramId()); + + return processResult; + } + } +}
\ No newline at end of file |