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:
parent
4232a15187
commit
1d8da18334
4 changed files with 39 additions and 25 deletions
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,7 +34,7 @@ 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)
|
||||||
|
@ -42,7 +42,7 @@ namespace Ryujinx.Ui
|
||||||
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 });
|
||||||
|
|
|
@ -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,10 +26,10 @@ 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);
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
_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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
Reference in a new issue