Call EnsureApplicationSaveData when launching a game (#871)

* Workaround for the lack of a program registry

* Call EnsureApplicationSaveData when launching a game
This commit is contained in:
Alex Barney 2020-01-12 04:15:17 -07:00 committed by Thog
parent 9c8d48edff
commit e348f95495
5 changed files with 85 additions and 14 deletions

View file

@ -1,9 +1,11 @@
using LibHac;
using LibHac.Account;
using LibHac.Common;
using LibHac.Fs;
using LibHac.FsService;
using LibHac.FsSystem;
using LibHac.FsSystem.NcaUtils;
using LibHac.Ncm;
using LibHac.Ns;
using LibHac.Spl;
using Ryujinx.Common.Logging;
@ -32,6 +34,8 @@ using System.Threading;
using TimeServiceManager = Ryujinx.HLE.HOS.Services.Time.TimeManager;
using NxStaticObject = Ryujinx.HLE.Loaders.Executables.NxStaticObject;
using static LibHac.Fs.ApplicationSaveDataManagement;
namespace Ryujinx.HLE.HOS
{
public class Horizon : IDisposable
@ -109,7 +113,8 @@ namespace Ryujinx.HLE.HOS
public string TitleName { get; private set; }
public string TitleId { get; private set; }
public ulong TitleId { get; private set; }
public string TitleIdText => TitleId.ToString("x16");
public IntegrityCheckLevel FsIntegrityCheckLevel { get; set; }
@ -513,7 +518,7 @@ namespace Ryujinx.HLE.HOS
LoadExeFs(codeFs, out Npdm metaData);
TitleId = metaData.Aci0.TitleId.ToString("x16");
TitleId = metaData.Aci0.TitleId;
if (controlNca != null)
{
@ -523,6 +528,11 @@ namespace Ryujinx.HLE.HOS
{
ControlData.ByteSpan.Clear();
}
if (TitleId != 0)
{
EnsureSaveData(new TitleId(TitleId));
}
}
private void LoadExeFs(IFileSystem codeFs, out Npdm metaData)
@ -561,7 +571,7 @@ namespace Ryujinx.HLE.HOS
}
}
TitleId = metaData.Aci0.TitleId.ToString("x16");
TitleId = metaData.Aci0.TitleId;
LoadNso("rtld");
LoadNso("main");
@ -664,7 +674,7 @@ namespace Ryujinx.HLE.HOS
ContentManager.LoadEntries();
TitleName = metaData.TitleName;
TitleId = metaData.Aci0.TitleId.ToString("x16");
TitleId = metaData.Aci0.TitleId;
ProgramLoader.LoadStaticObjects(this, metaData, new IExecutable[] { staticObject });
}
@ -679,6 +689,39 @@ namespace Ryujinx.HLE.HOS
}
}
private Result EnsureSaveData(TitleId titleId)
{
Logger.PrintInfo(LogClass.Application, "Ensuring required savedata exists.");
UInt128 lastOpenedUser = State.Account.LastOpenedUser.UserId;
Uid user = new Uid((ulong)lastOpenedUser.Low, (ulong)lastOpenedUser.High);
ref ApplicationControlProperty control = ref ControlData.Value;
if (LibHac.Util.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.
control = ref new BlitStruct<ApplicationControlProperty>(1).Value;
// The set sizes don't actually matter as long as they're non-zero because we use directory savedata.
control.UserAccountSaveDataSize = 0x4000;
control.UserAccountSaveDataJournalSize = 0x4000;
Logger.PrintWarning(LogClass.Application,
"No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games.");
}
Result rc = EnsureApplicationSaveData(FsClient, out _, titleId, ref ControlData.Value, ref user);
if (rc.IsFailure())
{
Logger.PrintError(LogClass.Application, $"Error calling EnsureApplicationSaveData. Result code {rc.ToStringWithName()}");
}
return rc;
}
public void LoadKeySet()
{
string keyFile = null;