Make VirtualFileSystem only instanciable once (#901)

This fix a regression caused by #888 on temporary saves for SNES Online.
(and probably other games)
This commit is contained in:
Thog 2020-01-24 17:01:21 +01:00 committed by Ac_K
parent 4232a15187
commit 1d8da18334
4 changed files with 39 additions and 25 deletions

View file

@ -20,12 +20,14 @@ namespace Ryujinx.HLE.FileSystem
public static string SystemNandPath = Path.Combine(NandPath, "system"); public static string SystemNandPath = Path.Combine(NandPath, "system");
public static string UserNandPath = Path.Combine(NandPath, "user"); public static string UserNandPath = Path.Combine(NandPath, "user");
private static bool _isInitialized = false;
public Keyset KeySet { get; private set; } public Keyset KeySet { get; private set; }
public FileSystemServer FsServer { get; private set; } public FileSystemServer FsServer { get; private set; }
public FileSystemClient FsClient { get; private set; } public FileSystemClient FsClient { get; private set; }
public EmulatedGameCard GameCard { get; private set; } public EmulatedGameCard GameCard { get; private set; }
public VirtualFileSystem() private VirtualFileSystem()
{ {
Reload(); Reload();
} }
@ -272,5 +274,17 @@ namespace Ryujinx.HLE.FileSystem
Unload(); Unload();
} }
} }
public static VirtualFileSystem CreateInstance()
{
if (_isInitialized)
{
throw new InvalidOperationException($"VirtualFileSystem can only be instanciated once!");
}
_isInitialized = true;
return new VirtualFileSystem();
}
} }
} }

View file

@ -34,15 +34,15 @@ namespace Ryujinx.Ui
private static readonly byte[] _nroIcon = GetResourceBytes("Ryujinx.Ui.assets.NROIcon.png"); private static readonly byte[] _nroIcon = GetResourceBytes("Ryujinx.Ui.assets.NROIcon.png");
private static readonly byte[] _nsoIcon = GetResourceBytes("Ryujinx.Ui.assets.NSOIcon.png"); private static readonly byte[] _nsoIcon = GetResourceBytes("Ryujinx.Ui.assets.NSOIcon.png");
private static Keyset _keySet; private static VirtualFileSystem _virtualFileSystem;
private static Language _desiredTitleLanguage; private static Language _desiredTitleLanguage;
public static void LoadApplications(List<string> appDirs, VirtualFileSystem virtualFileSystem, Language desiredTitleLanguage) public static void LoadApplications(List<string> appDirs, VirtualFileSystem virtualFileSystem, Language desiredTitleLanguage)
{ {
int numApplicationsFound = 0; int numApplicationsFound = 0;
int numApplicationsLoaded = 0; int numApplicationsLoaded = 0;
_keySet = virtualFileSystem.KeySet; _virtualFileSystem = virtualFileSystem;
_desiredTitleLanguage = desiredTitleLanguage; _desiredTitleLanguage = desiredTitleLanguage;
// Builds the applications list with paths to found applications // Builds the applications list with paths to found applications
@ -77,7 +77,7 @@ namespace Ryujinx.Ui
{ {
nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure(); nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure();
Nca nca = new Nca(_keySet, ncaFile.AsStorage()); Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
if (nca.Header.ContentType == NcaContentType.Program && !nca.Header.GetFsHeader(dataIndex).IsPatchSection()) if (nca.Header.ContentType == NcaContentType.Program && !nca.Header.GetFsHeader(dataIndex).IsPatchSection())
@ -103,7 +103,7 @@ namespace Ryujinx.Ui
{ {
try try
{ {
Nca nca = new Nca(_keySet, new FileStream(app, FileMode.Open, FileAccess.Read).AsStorage()); Nca nca = new Nca(_virtualFileSystem.KeySet, new FileStream(app, FileMode.Open, FileAccess.Read).AsStorage());
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
if (nca.Header.ContentType != NcaContentType.Program || nca.Header.GetFsHeader(dataIndex).IsPatchSection()) if (nca.Header.ContentType != NcaContentType.Program || nca.Header.GetFsHeader(dataIndex).IsPatchSection())
@ -145,7 +145,7 @@ namespace Ryujinx.Ui
if (Path.GetExtension(applicationPath) == ".xci") if (Path.GetExtension(applicationPath) == ".xci")
{ {
Xci xci = new Xci(_keySet, file.AsStorage()); Xci xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage());
pfs = xci.OpenPartition(XciPartitionType.Secure); pfs = xci.OpenPartition(XciPartitionType.Secure);
} }
@ -409,7 +409,7 @@ namespace Ryujinx.Ui
{ {
Ticket ticket = new Ticket(ticketFile.AsStream()); Ticket ticket = new Ticket(ticketFile.AsStream());
_keySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(_keySet))); _virtualFileSystem.KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(_virtualFileSystem.KeySet)));
} }
} }
@ -418,7 +418,7 @@ namespace Ryujinx.Ui
{ {
pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure(); pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure();
Nca nca = new Nca(_keySet, ncaFile.AsStorage()); Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
if (nca.Header.ContentType == NcaContentType.Control) if (nca.Header.ContentType == NcaContentType.Control)
{ {
@ -432,7 +432,7 @@ namespace Ryujinx.Ui
internal static ApplicationMetadata LoadAndSaveMetaData(string titleId, Action<ApplicationMetadata> modifyFunction = null) internal static ApplicationMetadata LoadAndSaveMetaData(string titleId, Action<ApplicationMetadata> modifyFunction = null)
{ {
string metadataFolder = Path.Combine(new VirtualFileSystem().GetBasePath(), "games", titleId, "gui"); string metadataFolder = Path.Combine(_virtualFileSystem.GetBasePath(), "games", titleId, "gui");
string metadataFile = Path.Combine(metadataFolder, "metadata.json"); string metadataFile = Path.Combine(metadataFolder, "metadata.json");
IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase }); IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase });

View file

@ -18,7 +18,7 @@ namespace Ryujinx.Ui
{ {
private static ListStore _gameTableStore; private static ListStore _gameTableStore;
private static TreeIter _rowIter; private static TreeIter _rowIter;
private FileSystemClient _fsClient; private VirtualFileSystem _virtualFileSystem;
#pragma warning disable CS0649 #pragma warning disable CS0649
#pragma warning disable IDE0044 #pragma warning disable IDE0044
@ -26,18 +26,18 @@ namespace Ryujinx.Ui
#pragma warning restore CS0649 #pragma warning restore CS0649
#pragma warning restore IDE0044 #pragma warning restore IDE0044
public GameTableContextMenu(ListStore gameTableStore, TreeIter rowIter, FileSystemClient fsClient) public GameTableContextMenu(ListStore gameTableStore, TreeIter rowIter, VirtualFileSystem virtualFileSystem)
: this(new Builder("Ryujinx.Ui.GameTableContextMenu.glade"), gameTableStore, rowIter, fsClient) { } : this(new Builder("Ryujinx.Ui.GameTableContextMenu.glade"), gameTableStore, rowIter, virtualFileSystem) { }
private GameTableContextMenu(Builder builder, ListStore gameTableStore, TreeIter rowIter, FileSystemClient fsClient) : base(builder.GetObject("_contextMenu").Handle) private GameTableContextMenu(Builder builder, ListStore gameTableStore, TreeIter rowIter, VirtualFileSystem virtualFileSystem) : base(builder.GetObject("_contextMenu").Handle)
{ {
builder.Autoconnect(this); builder.Autoconnect(this);
_openSaveDir.Activated += OpenSaveDir_Clicked; _openSaveDir.Activated += OpenSaveDir_Clicked;
_gameTableStore = gameTableStore; _gameTableStore = gameTableStore;
_rowIter = rowIter; _rowIter = rowIter;
_fsClient = fsClient; _virtualFileSystem = virtualFileSystem;
} }
//Events //Events
@ -76,7 +76,7 @@ namespace Ryujinx.Ui
filter.SetUserId(new UserId(1, 0)); filter.SetUserId(new UserId(1, 0));
filter.SetTitleId(new TitleId(titleId)); filter.SetTitleId(new TitleId(titleId));
Result result = _fsClient.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter); Result result = _virtualFileSystem.FsClient.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter);
if (result == ResultFs.TargetNotFound) if (result == ResultFs.TargetNotFound)
{ {
@ -95,7 +95,7 @@ namespace Ryujinx.Ui
return false; return false;
} }
result = _fsClient.CreateSaveData(new TitleId(titleId), new UserId(1, 0), new TitleId(titleId), 0, 0, 0); result = _virtualFileSystem.FsClient.CreateSaveData(new TitleId(titleId), new UserId(1, 0), new TitleId(titleId), 0, 0, 0);
if (result.IsFailure()) if (result.IsFailure())
{ {
@ -105,7 +105,7 @@ namespace Ryujinx.Ui
} }
// Try to find the savedata again after creating it // Try to find the savedata again after creating it
result = _fsClient.FindSaveDataWithFilter(out saveDataInfo, SaveDataSpaceId.User, ref filter); result = _virtualFileSystem.FsClient.FindSaveDataWithFilter(out saveDataInfo, SaveDataSpaceId.User, ref filter);
} }
if (result.IsSuccess()) if (result.IsSuccess())
@ -122,7 +122,7 @@ namespace Ryujinx.Ui
private string GetSaveDataDirectory(ulong saveDataId) private string GetSaveDataDirectory(ulong saveDataId)
{ {
string saveRootPath = System.IO.Path.Combine(new VirtualFileSystem().GetNandPath(), $"user/save/{saveDataId:x16}"); string saveRootPath = System.IO.Path.Combine(_virtualFileSystem.GetNandPath(), $"user/save/{saveDataId:x16}");
if (!Directory.Exists(saveRootPath)) if (!Directory.Exists(saveRootPath))
{ {

View file

@ -83,7 +83,7 @@ namespace Ryujinx.Ui
End(null); End(null);
} }
_virtualFileSystem = new VirtualFileSystem(); _virtualFileSystem = VirtualFileSystem.CreateInstance();
_contentManager = new ContentManager(_virtualFileSystem); _contentManager = new ContentManager(_virtualFileSystem);
if (migrationNeeded) if (migrationNeeded)
@ -461,7 +461,7 @@ namespace Ryujinx.Ui
if (treeIter.UserData == IntPtr.Zero) return; if (treeIter.UserData == IntPtr.Zero) return;
GameTableContextMenu contextMenu = new GameTableContextMenu(_tableStore, treeIter, _virtualFileSystem.FsClient); GameTableContextMenu contextMenu = new GameTableContextMenu(_tableStore, treeIter, _virtualFileSystem);
contextMenu.ShowAll(); contextMenu.ShowAll();
contextMenu.PopupAtPointer(null); contextMenu.PopupAtPointer(null);
} }
@ -502,7 +502,7 @@ namespace Ryujinx.Ui
{ {
Process.Start(new ProcessStartInfo() Process.Start(new ProcessStartInfo()
{ {
FileName = new VirtualFileSystem().GetBasePath(), FileName = _virtualFileSystem.GetBasePath(),
UseShellExecute = true, UseShellExecute = true,
Verb = "open" Verb = "open"
}); });
@ -738,7 +738,7 @@ namespace Ryujinx.Ui
private void Update_Pressed(object sender, EventArgs args) private void Update_Pressed(object sender, EventArgs args)
{ {
string ryuUpdater = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "RyuUpdater.exe"); string ryuUpdater = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "RyuUpdater.exe");
try try
{ {