aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.HLE/FileSystem/VirtualFileSystem.cs38
-rw-r--r--Ryujinx.HLE/HOS/ApplicationLoader.cs30
-rw-r--r--Ryujinx.HLE/HOS/ProgramLoader.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs9
4 files changed, 61 insertions, 24 deletions
diff --git a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
index c958c6e8..95a2fcda 100644
--- a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
+++ b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
@@ -16,6 +16,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS;
using System;
using System.Buffers.Text;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
@@ -35,7 +36,8 @@ namespace Ryujinx.HLE.FileSystem
public EmulatedGameCard GameCard { get; private set; }
public EmulatedSdCard SdCard { get; private set; }
public ModLoader ModLoader { get; private set; }
- public Stream RomFs { get; private set; }
+
+ private readonly ConcurrentDictionary<ulong, Stream> _romFsByPid;
private static bool _isInitialized = false;
@@ -55,17 +57,34 @@ namespace Ryujinx.HLE.FileSystem
{
ReloadKeySet();
ModLoader = new ModLoader(); // Should only be created once
+ _romFsByPid = new ConcurrentDictionary<ulong, Stream>();
+ }
+
+ public void LoadRomFs(ulong pid, string fileName)
+ {
+ var romfsStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
+
+ _romFsByPid.AddOrUpdate(pid, romfsStream, (pid, oldStream) =>
+ {
+ oldStream.Close();
+
+ return romfsStream;
+ });
}
- public void LoadRomFs(string fileName)
+ public void SetRomFs(ulong pid, Stream romfsStream)
{
- RomFs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
+ _romFsByPid.AddOrUpdate(pid, romfsStream, (pid, oldStream) =>
+ {
+ oldStream.Close();
+
+ return romfsStream;
+ });
}
- public void SetRomFs(Stream romfsStream)
+ public Stream GetRomFs(ulong pid)
{
- RomFs?.Close();
- RomFs = romfsStream;
+ return _romFsByPid[pid];
}
public string GetFullPath(string basePath, string fileName)
@@ -583,7 +602,12 @@ namespace Ryujinx.HLE.FileSystem
{
if (disposing)
{
- RomFs?.Dispose();
+ foreach (var stream in _romFsByPid.Values)
+ {
+ stream.Close();
+ }
+
+ _romFsByPid.Clear();
}
}
}
diff --git a/Ryujinx.HLE/HOS/ApplicationLoader.cs b/Ryujinx.HLE/HOS/ApplicationLoader.cs
index 06281b49..67e0a9c7 100644
--- a/Ryujinx.HLE/HOS/ApplicationLoader.cs
+++ b/Ryujinx.HLE/HOS/ApplicationLoader.cs
@@ -76,11 +76,6 @@ namespace Ryujinx.HLE.HOS
public void LoadCart(string exeFsDir, string romFsFile = null)
{
- if (romFsFile != null)
- {
- _device.Configuration.VirtualFileSystem.LoadRomFs(romFsFile);
- }
-
LocalFileSystem codeFs = new LocalFileSystem(exeFsDir);
MetaLoader metaData = ReadNpdm(codeFs);
@@ -95,7 +90,12 @@ namespace Ryujinx.HLE.HOS
EnsureSaveData(new ApplicationId(TitleId));
}
- LoadExeFs(codeFs, string.Empty, metaData);
+ ulong pid = LoadExeFs(codeFs, string.Empty, metaData);
+
+ if (romFsFile != null)
+ {
+ _device.Configuration.VirtualFileSystem.LoadRomFs(pid, romFsFile);
+ }
}
public static (Nca main, Nca patch, Nca control) GetGameData(VirtualFileSystem fileSystem, PartitionFileSystem pfs, int programIndex)
@@ -491,6 +491,8 @@ namespace Ryujinx.HLE.HOS
_displayVersion = displayVersion;
+ ulong pid = LoadExeFs(codeFs, displayVersion, metaData);
+
if (dataStorage == null)
{
Logger.Warning?.Print(LogClass.Loader, "No RomFS found in NCA");
@@ -499,7 +501,7 @@ namespace Ryujinx.HLE.HOS
{
IStorage newStorage = _device.Configuration.VirtualFileSystem.ModLoader.ApplyRomFsMods(TitleId, dataStorage);
- _device.Configuration.VirtualFileSystem.SetRomFs(newStorage.AsStream(FileAccess.Read));
+ _device.Configuration.VirtualFileSystem.SetRomFs(pid, newStorage.AsStream(FileAccess.Read));
}
// Don't create save data for system programs.
@@ -510,8 +512,6 @@ namespace Ryujinx.HLE.HOS
EnsureSaveData(new ApplicationId(TitleId & ~0xFul));
}
- LoadExeFs(codeFs, displayVersion, metaData);
-
Logger.Info?.Print(LogClass.Loader, $"Application Loaded: {TitleName} v{DisplayVersion} [{TitleIdText}] [{(TitleIs64Bit ? "64-bit" : "32-bit")}]");
}
@@ -579,7 +579,7 @@ namespace Ryujinx.HLE.HOS
}
}
- private void LoadExeFs(IFileSystem codeFs, string displayVersion, MetaLoader metaData = null, bool isHomebrew = false)
+ private ulong LoadExeFs(IFileSystem codeFs, string displayVersion, MetaLoader metaData = null, bool isHomebrew = false)
{
if (_device.Configuration.VirtualFileSystem.ModLoader.ReplaceExefsPartition(TitleId, ref codeFs))
{
@@ -654,6 +654,8 @@ namespace Ryujinx.HLE.HOS
DiskCacheLoadState = result.DiskCacheLoadState;
_device.Configuration.VirtualFileSystem.ModLoader.LoadCheats(TitleId, result.TamperInfo, _device.TamperMachine);
+
+ return result.ProcessId;
}
public void LoadProgram(string filePath)
@@ -665,6 +667,7 @@ namespace Ryujinx.HLE.HOS
bool isNro = Path.GetExtension(filePath).ToLower() == ".nro";
IExecutable executable;
+ Stream romfsStream = null;
if (isNro)
{
@@ -697,7 +700,7 @@ namespace Ryujinx.HLE.HOS
if (romfsSize != 0)
{
- _device.Configuration.VirtualFileSystem.SetRomFs(new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset));
+ romfsStream = new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset);
}
if (nacpSize != 0)
@@ -758,6 +761,11 @@ namespace Ryujinx.HLE.HOS
ProgramLoadResult result = ProgramLoader.LoadNsos(_device.System.KernelContext, metaData, programInfo, executables: executable);
+ if (romfsStream != null)
+ {
+ _device.Configuration.VirtualFileSystem.SetRomFs(result.ProcessId, romfsStream);
+ }
+
DiskCacheLoadState = result.DiskCacheLoadState;
_device.Configuration.VirtualFileSystem.ModLoader.LoadCheats(TitleId, result.TamperInfo, _device.TamperMachine);
diff --git a/Ryujinx.HLE/HOS/ProgramLoader.cs b/Ryujinx.HLE/HOS/ProgramLoader.cs
index b6a39a20..695f4672 100644
--- a/Ryujinx.HLE/HOS/ProgramLoader.cs
+++ b/Ryujinx.HLE/HOS/ProgramLoader.cs
@@ -41,17 +41,19 @@ namespace Ryujinx.HLE.HOS
struct ProgramLoadResult
{
- public static ProgramLoadResult Failed => new ProgramLoadResult(false, null, null);
+ public static ProgramLoadResult Failed => new ProgramLoadResult(false, null, null, 0);
public readonly bool Success;
public readonly ProcessTamperInfo TamperInfo;
public readonly IDiskCacheLoadState DiskCacheLoadState;
+ public readonly ulong ProcessId;
- public ProgramLoadResult(bool success, ProcessTamperInfo tamperInfo, IDiskCacheLoadState diskCacheLoadState)
+ public ProgramLoadResult(bool success, ProcessTamperInfo tamperInfo, IDiskCacheLoadState diskCacheLoadState, ulong pid)
{
Success = success;
TamperInfo = tamperInfo;
DiskCacheLoadState = diskCacheLoadState;
+ ProcessId = pid;
}
}
@@ -366,7 +368,7 @@ namespace Ryujinx.HLE.HOS
process.MemoryManager.AliasRegionStart,
process.MemoryManager.CodeRegionStart);
- return new ProgramLoadResult(true, tamperInfo, processContextFactory.DiskCacheLoadState);
+ return new ProgramLoadResult(true, tamperInfo, processContextFactory.DiskCacheLoadState, process.Pid);
}
private static Result LoadIntoMemory(KProcess process, IExecutable image, ulong baseAddress)
diff --git a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
index d812e374..a4bc6254 100644
--- a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
+++ b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
@@ -27,6 +27,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
class IFileSystemProxy : DisposableIpcService
{
private SharedRef<LibHac.FsSrv.Sf.IFileSystemProxy> _baseFileSystemProxy;
+ private ulong _pid;
public IFileSystemProxy(ServiceCtx context) : base(context.Device.System.FsServer)
{
@@ -38,6 +39,8 @@ namespace Ryujinx.HLE.HOS.Services.Fs
// SetCurrentProcess(u64, pid)
public ResultCode SetCurrentProcess(ServiceCtx context)
{
+ _pid = context.Request.HandleDesc.PId;
+
return ResultCode.Success;
}
@@ -702,7 +705,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
// OpenDataStorageByCurrentProcess() -> object<nn::fssrv::sf::IStorage> dataStorage
public ResultCode OpenDataStorageByCurrentProcess(ServiceCtx context)
{
- var storage = context.Device.FileSystem.RomFs.AsStorage(true);
+ var storage = context.Device.FileSystem.GetRomFs(_pid).AsStorage(true);
using var sharedStorage = new SharedRef<LibHac.Fs.IStorage>(storage);
using var sfStorage = new SharedRef<IStorage>(new StorageInterfaceAdapter(ref sharedStorage.Ref()));
@@ -791,7 +794,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
// OpenPatchDataStorageByCurrentProcess() -> object<nn::fssrv::sf::IStorage>
public ResultCode OpenPatchDataStorageByCurrentProcess(ServiceCtx context)
{
- var storage = context.Device.FileSystem.RomFs.AsStorage(true);
+ var storage = context.Device.FileSystem.GetRomFs(_pid).AsStorage(true);
using var sharedStorage = new SharedRef<LibHac.Fs.IStorage>(storage);
using var sfStorage = new SharedRef<IStorage>(new StorageInterfaceAdapter(ref sharedStorage.Ref()));
@@ -811,7 +814,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
throw new NotImplementedException($"Accessing storage from other programs is not supported (program index = {programIndex}).");
}
- var storage = context.Device.FileSystem.RomFs.AsStorage(true);
+ var storage = context.Device.FileSystem.GetRomFs(_pid).AsStorage(true);
using var sharedStorage = new SharedRef<LibHac.Fs.IStorage>(storage);
using var sfStorage = new SharedRef<IStorage>(new StorageInterfaceAdapter(ref sharedStorage.Ref()));