Update LibHac to v0.16.0 (#3159)

This commit is contained in:
Alex Barney 2022-02-26 16:52:25 -07:00 committed by GitHub
parent 7b35ebc64a
commit 3705c20668
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 64 additions and 79 deletions

View file

@ -481,14 +481,14 @@ namespace Ryujinx.HLE.HOS
if (result.IsSuccess() && bytesRead == controlData.ByteSpan.Length) if (result.IsSuccess() && bytesRead == controlData.ByteSpan.Length)
{ {
titleName = controlData.Value.Titles[(int)device.System.State.DesiredTitleLanguage].Name.ToString(); titleName = controlData.Value.Title[(int)device.System.State.DesiredTitleLanguage].NameString.ToString();
if (string.IsNullOrWhiteSpace(titleName)) if (string.IsNullOrWhiteSpace(titleName))
{ {
titleName = controlData.Value.Titles.ToArray().FirstOrDefault(x => x.Name[0] != 0).Name.ToString(); titleName = controlData.Value.Title.ItemsRo.ToArray().FirstOrDefault(x => x.Name[0] != 0).NameString.ToString();
} }
displayVersion = controlData.Value.DisplayVersion.ToString(); displayVersion = controlData.Value.DisplayVersionString.ToString();
} }
} }
else else
@ -615,20 +615,20 @@ namespace Ryujinx.HLE.HOS
ref ApplicationControlProperty nacp = ref ControlData.Value; ref ApplicationControlProperty nacp = ref ControlData.Value;
programInfo.Name = nacp.Titles[(int)_device.System.State.DesiredTitleLanguage].Name.ToString(); programInfo.Name = nacp.Title[(int)_device.System.State.DesiredTitleLanguage].NameString.ToString();
if (string.IsNullOrWhiteSpace(programInfo.Name)) if (string.IsNullOrWhiteSpace(programInfo.Name))
{ {
programInfo.Name = nacp.Titles.ToArray().FirstOrDefault(x => x.Name[0] != 0).Name.ToString(); programInfo.Name = nacp.Title.ItemsRo.ToArray().FirstOrDefault(x => x.Name[0] != 0).NameString.ToString();
} }
if (nacp.PresenceGroupId != 0) if (nacp.PresenceGroupId != 0)
{ {
programInfo.ProgramId = nacp.PresenceGroupId; programInfo.ProgramId = nacp.PresenceGroupId;
} }
else if (nacp.SaveDataOwnerId.Value != 0) else if (nacp.SaveDataOwnerId != 0)
{ {
programInfo.ProgramId = nacp.SaveDataOwnerId.Value; programInfo.ProgramId = nacp.SaveDataOwnerId;
} }
else if (nacp.AddOnContentBaseId != 0) else if (nacp.AddOnContentBaseId != 0)
{ {
@ -776,14 +776,14 @@ namespace Ryujinx.HLE.HOS
// The set sizes don't actually matter as long as they're non-zero because we use directory savedata. // The set sizes don't actually matter as long as they're non-zero because we use directory savedata.
control.UserAccountSaveDataSize = 0x4000; control.UserAccountSaveDataSize = 0x4000;
control.UserAccountSaveDataJournalSize = 0x4000; control.UserAccountSaveDataJournalSize = 0x4000;
control.SaveDataOwnerId = applicationId; control.SaveDataOwnerId = applicationId.Value;
Logger.Warning?.Print(LogClass.Application, Logger.Warning?.Print(LogClass.Application,
"No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games."); "No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games.");
} }
HorizonClient hos = _device.System.LibHacHorizonManager.RyujinxClient; HorizonClient hos = _device.System.LibHacHorizonManager.RyujinxClient;
Result resultCode = hos.Fs.EnsureApplicationCacheStorage(out _, out _, applicationId, ref control); Result resultCode = hos.Fs.EnsureApplicationCacheStorage(out _, out _, applicationId, in control);
if (resultCode.IsFailure()) if (resultCode.IsFailure())
{ {
@ -792,7 +792,7 @@ namespace Ryujinx.HLE.HOS
return resultCode; return resultCode;
} }
resultCode = EnsureApplicationSaveData(hos.Fs, out _, applicationId, ref control, ref user); resultCode = hos.Fs.EnsureApplicationSaveData(out _, applicationId, in control, in user);
if (resultCode.IsFailure()) if (resultCode.IsFailure())
{ {

View file

@ -466,7 +466,7 @@ namespace Ryujinx.HLE.HOS
AudioRendererManager.Dispose(); AudioRendererManager.Dispose();
LibHacHorizonManager.AmClient.Fs.UnregisterProgram(LibHacHorizonManager.ApplicationClient.Os.GetCurrentProcessId().Value); LibHacHorizonManager.PmClient.Fs.UnregisterProgram(LibHacHorizonManager.ApplicationClient.Os.GetCurrentProcessId().Value).ThrowIfFailure();
KernelContext.Dispose(); KernelContext.Dispose();
} }

View file

@ -24,6 +24,7 @@ namespace Ryujinx.HLE.HOS
public HorizonClient BcatClient { get; private set; } public HorizonClient BcatClient { get; private set; }
public HorizonClient FsClient { get; private set; } public HorizonClient FsClient { get; private set; }
public HorizonClient NsClient { get; private set; } public HorizonClient NsClient { get; private set; }
public HorizonClient PmClient { get; private set; }
public HorizonClient SdbClient { get; private set; } public HorizonClient SdbClient { get; private set; }
private SharedRef<LibHacIReader> _arpIReader; private SharedRef<LibHacIReader> _arpIReader;
@ -65,6 +66,7 @@ namespace Ryujinx.HLE.HOS
public void InitializeSystemClients() public void InitializeSystemClients()
{ {
PmClient = Server.CreatePrivilegedHorizonClient();
AccountClient = Server.CreateHorizonClient(new ProgramLocation(SystemProgramId.Account, StorageId.BuiltInSystem), AccountFsPermissions); AccountClient = Server.CreateHorizonClient(new ProgramLocation(SystemProgramId.Account, StorageId.BuiltInSystem), AccountFsPermissions);
AmClient = Server.CreateHorizonClient(new ProgramLocation(SystemProgramId.Am, StorageId.BuiltInSystem), AmFsPermissions); AmClient = Server.CreateHorizonClient(new ProgramLocation(SystemProgramId.Am, StorageId.BuiltInSystem), AmFsPermissions);
NsClient = Server.CreateHorizonClient(new ProgramLocation(SystemProgramId.Ns, StorageId.BuiltInSystem), NsFsPermissions); NsClient = Server.CreateHorizonClient(new ProgramLocation(SystemProgramId.Ns, StorageId.BuiltInSystem), NsFsPermissions);

View file

@ -695,7 +695,7 @@ namespace Ryujinx.HLE.HOS
var buildIds = programs.Select(p => p switch var buildIds = programs.Select(p => p switch
{ {
NsoExecutable nso => BitConverter.ToString(nso.BuildId.Bytes.ToArray()).Replace("-", "").TrimEnd('0'), NsoExecutable nso => BitConverter.ToString(nso.BuildId.ItemsRo.ToArray()).Replace("-", "").TrimEnd('0'),
NroExecutable nro => BitConverter.ToString(nro.Header.BuildId).Replace("-", "").TrimEnd('0'), NroExecutable nro => BitConverter.ToString(nro.Header.BuildId).Replace("-", "").TrimEnd('0'),
_ => string.Empty _ => string.Empty
}).ToList(); }).ToList();

View file

@ -160,7 +160,7 @@ namespace Ryujinx.HLE.HOS
var buildIds = executables.Select(e => (e switch var buildIds = executables.Select(e => (e switch
{ {
NsoExecutable nso => BitConverter.ToString(nso.BuildId.Bytes.ToArray()), NsoExecutable nso => BitConverter.ToString(nso.BuildId.ItemsRo.ToArray()),
NroExecutable nro => BitConverter.ToString(nro.Header.BuildId), NroExecutable nro => BitConverter.ToString(nro.Header.BuildId),
_ => "" _ => ""
}).Replace("-", "").ToUpper()); }).Replace("-", "").ToUpper());

View file

@ -168,8 +168,8 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
private void DeleteSaveData(UserId userId) private void DeleteSaveData(UserId userId)
{ {
SaveDataFilter saveDataFilter = new SaveDataFilter(); var saveDataFilter = SaveDataFilter.Make(programId: default, saveType: default,
saveDataFilter.SetUserId(new LibHac.Fs.UserId((ulong)userId.High, (ulong)userId.Low)); new LibHac.Fs.UserId((ulong)userId.High, (ulong)userId.Low), saveDataId: default, index: default);
using var saveDataIterator = new UniqueRef<SaveDataIterator>(); using var saveDataIterator = new UniqueRef<SaveDataIterator>();

View file

@ -169,7 +169,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
// TODO: Account actually calls nn::arp::detail::IReader::GetApplicationControlProperty() with the current Pid and store the result (NACP file) internally. // TODO: Account actually calls nn::arp::detail::IReader::GetApplicationControlProperty() with the current Pid and store the result (NACP file) internally.
// But since we use LibHac and we load one Application at a time, it's not necessary. // But since we use LibHac and we load one Application at a time, it's not necessary.
context.ResponseData.Write(context.Device.Application.ControlData.Value.UserAccountSwitchLock); context.ResponseData.Write((byte)context.Device.Application.ControlData.Value.UserAccountSwitchLock);
Logger.Stub?.PrintStub(LogClass.ServiceAcc); Logger.Stub?.PrintStub(LogClass.ServiceAcc);

View file

@ -131,7 +131,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
} }
HorizonClient hos = context.Device.System.LibHacHorizonManager.AmClient; HorizonClient hos = context.Device.System.LibHacHorizonManager.AmClient;
Result result = EnsureApplicationSaveData(hos.Fs, out long requiredSize, applicationId, ref control, ref userId); Result result = hos.Fs.EnsureApplicationSaveData(out long requiredSize, applicationId, in control, in userId);
context.ResponseData.Write(requiredSize); context.ResponseData.Write(requiredSize);
@ -148,7 +148,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
// TODO: When above calls are implemented, switch to using ns:am // TODO: When above calls are implemented, switch to using ns:am
long desiredLanguageCode = context.Device.System.State.DesiredLanguageCode; long desiredLanguageCode = context.Device.System.State.DesiredLanguageCode;
int supportedLanguages = (int)context.Device.Application.ControlData.Value.SupportedLanguages; int supportedLanguages = (int)context.Device.Application.ControlData.Value.SupportedLanguageFlag;
int firstSupported = BitOperations.TrailingZeroCount(supportedLanguages); int firstSupported = BitOperations.TrailingZeroCount(supportedLanguages);
if (firstSupported > (int)SystemState.TitleLanguage.BrazilianPortuguese) if (firstSupported > (int)SystemState.TitleLanguage.BrazilianPortuguese)
@ -190,7 +190,6 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
// GetDisplayVersion() -> nn::oe::DisplayVersion // GetDisplayVersion() -> nn::oe::DisplayVersion
public ResultCode GetDisplayVersion(ServiceCtx context) public ResultCode GetDisplayVersion(ServiceCtx context)
{ {
// This should work as DisplayVersion U8Span always gives a 0x10 size byte array.
// If an NACP isn't found, the buffer will be all '\0' which seems to be the correct implementation. // If an NACP isn't found, the buffer will be all '\0' which seems to be the correct implementation.
context.ResponseData.Write(context.Device.Application.ControlData.Value.DisplayVersion); context.ResponseData.Write(context.Device.Application.ControlData.Value.DisplayVersion);
@ -252,7 +251,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
BlitStruct<ApplicationControlProperty> controlHolder = context.Device.Application.ControlData; BlitStruct<ApplicationControlProperty> controlHolder = context.Device.Application.ControlData;
Result result = _horizon.Fs.CreateApplicationCacheStorage(out long requiredSize, Result result = _horizon.Fs.CreateApplicationCacheStorage(out long requiredSize,
out CacheStorageTargetMedia storageTarget, applicationId, ref controlHolder.Value, index, saveSize, out CacheStorageTargetMedia storageTarget, applicationId, in controlHolder.Value, index, saveSize,
journalSize); journalSize);
if (result.IsFailure()) return (ResultCode)result.Value; if (result.IsFailure()) return (ResultCode)result.Value;

View file

@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Arp
{ {
launchProperty = new LibHac.Arp.ApplicationLaunchProperty launchProperty = new LibHac.Arp.ApplicationLaunchProperty
{ {
BaseStorageId = StorageId.BuiltInUser, StorageId = StorageId.BuiltInUser,
ApplicationId = ApplicationId ApplicationId = ApplicationId
}; };
@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.Arp
{ {
launchProperty = new LibHac.Arp.ApplicationLaunchProperty launchProperty = new LibHac.Arp.ApplicationLaunchProperty
{ {
BaseStorageId = StorageId.BuiltInUser, StorageId = StorageId.BuiltInUser,
ApplicationId = applicationId ApplicationId = applicationId
}; };

View file

@ -132,23 +132,11 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
} }
} }
public static Result ReadFsPath(out FsPath path, ServiceCtx context, int index = 0) public static ref readonly FspPath GetFspPath(ServiceCtx context, int index = 0)
{ {
ulong position = context.Request.PtrBuff[index].Position; ulong position = context.Request.PtrBuff[index].Position;
ulong size = context.Request.PtrBuff[index].Size; ulong size = context.Request.PtrBuff[index].Size;
byte[] pathBytes = new byte[size];
context.Memory.Read(position, pathBytes);
return FsPath.FromSpan(out path, pathBytes);
}
public static ref readonly FspPath GetFspPath(ServiceCtx context, int index = 0)
{
ulong position = (ulong)context.Request.PtrBuff[index].Position;
ulong size = (ulong)context.Request.PtrBuff[index].Size;
ReadOnlySpan<byte> buffer = context.Memory.GetSpan(position, (int)size); ReadOnlySpan<byte> buffer = context.Memory.GetSpan(position, (int)size);
ReadOnlySpan<FspPath> fspBuffer = MemoryMarshal.Cast<byte, FspPath>(buffer); ReadOnlySpan<FspPath> fspBuffer = MemoryMarshal.Cast<byte, FspPath>(buffer);
@ -157,8 +145,8 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
public static ref readonly LibHac.FsSrv.Sf.Path GetSfPath(ServiceCtx context, int index = 0) public static ref readonly LibHac.FsSrv.Sf.Path GetSfPath(ServiceCtx context, int index = 0)
{ {
ulong position = (ulong)context.Request.PtrBuff[index].Position; ulong position = context.Request.PtrBuff[index].Position;
ulong size = (ulong)context.Request.PtrBuff[index].Size; ulong size = context.Request.PtrBuff[index].Size;
ReadOnlySpan<byte> buffer = context.Memory.GetSpan(position, (int)size); ReadOnlySpan<byte> buffer = context.Memory.GetSpan(position, (int)size);
ReadOnlySpan<LibHac.FsSrv.Sf.Path> pathBuffer = MemoryMarshal.Cast<byte, LibHac.FsSrv.Sf.Path>(buffer); ReadOnlySpan<LibHac.FsSrv.Sf.Path> pathBuffer = MemoryMarshal.Cast<byte, LibHac.FsSrv.Sf.Path>(buffer);

View file

@ -1,6 +1,6 @@
using LibHac; using LibHac;
using LibHac.Common; using LibHac.Common;
using LibHac.FsSrv; using LibHac.Fs;
namespace Ryujinx.HLE.HOS.Services.Fs namespace Ryujinx.HLE.HOS.Services.Fs
{ {

View file

@ -1,8 +1,9 @@
using LibHac.Ns;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Arp; using Ryujinx.HLE.HOS.Services.Arp;
using System; using System;
using static LibHac.Ns.ApplicationControlProperty;
namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
{ {
class IParentalControlService : IpcService class IParentalControlService : IpcService
@ -52,8 +53,8 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
_titleId = titleId; _titleId = titleId;
// TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields. // TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields.
_ratingAge = Array.ConvertAll(context.Device.Application.ControlData.Value.RatingAge.ToArray(), Convert.ToInt32); _ratingAge = Array.ConvertAll(context.Device.Application.ControlData.Value.RatingAge.ItemsRo.ToArray(), Convert.ToInt32);
_parentalControlFlag = context.Device.Application.ControlData.Value.ParentalControl; _parentalControlFlag = context.Device.Application.ControlData.Value.ParentalControlFlag;
} }
} }
@ -224,7 +225,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
private ResultCode IsStereoVisionPermittedImpl() private ResultCode IsStereoVisionPermittedImpl()
{ {
/* /*
// TODO: Application Exemptions are readed from file "appExemptions.dat" in the service savedata. // TODO: Application Exemptions are read from file "appExemptions.dat" in the service savedata.
// Since we don't support the pctl savedata for now, this can be implemented later. // Since we don't support the pctl savedata for now, this can be implemented later.
if (appExemption) if (appExemption)

View file

@ -15,6 +15,8 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService
internal static ResultCode GetPlayStatistics(ServiceCtx context, bool byUserId = false) internal static ResultCode GetPlayStatistics(ServiceCtx context, bool byUserId = false)
{ {
ref readonly var controlProperty = ref context.Device.Application.ControlData.Value;
ulong inputPosition = context.Request.SendBuff[0].Position; ulong inputPosition = context.Request.SendBuff[0].Position;
ulong inputSize = context.Request.SendBuff[0].Size; ulong inputSize = context.Request.SendBuff[0].Size;
@ -31,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService
} }
} }
PlayLogQueryCapability queryCapability = (PlayLogQueryCapability)context.Device.Application.ControlData.Value.PlayLogQueryCapability; PlayLogQueryCapability queryCapability = (PlayLogQueryCapability)controlProperty.PlayLogQueryCapability;
List<ulong> titleIds = new List<ulong>(); List<ulong> titleIds = new List<ulong>();
@ -45,7 +47,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService
// Check if input title ids are in the whitelist. // Check if input title ids are in the whitelist.
foreach (ulong titleId in titleIds) foreach (ulong titleId in titleIds)
{ {
if (!context.Device.Application.ControlData.Value.PlayLogQueryableApplicationId.Contains(titleId)) if (!controlProperty.PlayLogQueryableApplicationId.ItemsRo.Contains(titleId))
{ {
return (ResultCode)Am.ResultCode.ObjectInvalid; return (ResultCode)Am.ResultCode.ObjectInvalid;
} }

View file

@ -1,4 +1,4 @@
using LibHac.Common; using LibHac.Common.FixedArrays;
using LibHac.Fs; using LibHac.Fs;
using LibHac.Loader; using LibHac.Loader;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
@ -27,7 +27,7 @@ namespace Ryujinx.HLE.Loaders.Executables
public uint BssSize { get; } public uint BssSize { get; }
public string Name; public string Name;
public Buffer32 BuildId; public Array32<byte> BuildId;
public NsoExecutable(IStorage inStorage, string name = null) public NsoExecutable(IStorage inStorage, string name = null)
{ {

View file

@ -19,7 +19,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Concentus" Version="1.1.7" /> <PackageReference Include="Concentus" Version="1.1.7" />
<PackageReference Include="LibHac" Version="0.15.0" /> <PackageReference Include="LibHac" Version="0.16.0" />
<PackageReference Include="MsgPack.Cli" Version="1.0.1" /> <PackageReference Include="MsgPack.Cli" Version="1.0.1" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" /> <PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />

View file

@ -558,10 +558,10 @@ namespace Ryujinx.Ui.App
{ {
_ = Enum.TryParse(_desiredTitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage); _ = Enum.TryParse(_desiredTitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage);
if (controlData.Titles.Length > (int)desiredTitleLanguage) if (controlData.Title.ItemsRo.Length > (int)desiredTitleLanguage)
{ {
titleName = controlData.Titles[(int)desiredTitleLanguage].Name.ToString(); titleName = controlData.Title[(int)desiredTitleLanguage].NameString.ToString();
publisher = controlData.Titles[(int)desiredTitleLanguage].Publisher.ToString(); publisher = controlData.Title[(int)desiredTitleLanguage].PublisherString.ToString();
} }
else else
{ {
@ -571,11 +571,11 @@ namespace Ryujinx.Ui.App
if (string.IsNullOrWhiteSpace(titleName)) if (string.IsNullOrWhiteSpace(titleName))
{ {
foreach (ApplicationControlTitle controlTitle in controlData.Titles) foreach (ref readonly var controlTitle in controlData.Title.ItemsRo)
{ {
if (!((U8Span)controlTitle.Name).IsEmpty()) if (!controlTitle.NameString.IsEmpty())
{ {
titleName = controlTitle.Name.ToString(); titleName = controlTitle.NameString.ToString();
break; break;
} }
@ -584,11 +584,11 @@ namespace Ryujinx.Ui.App
if (string.IsNullOrWhiteSpace(publisher)) if (string.IsNullOrWhiteSpace(publisher))
{ {
foreach (ApplicationControlTitle controlTitle in controlData.Titles) foreach (ref readonly var controlTitle in controlData.Title.ItemsRo)
{ {
if (!((U8Span)controlTitle.Publisher).IsEmpty()) if (!controlTitle.PublisherString.IsEmpty())
{ {
publisher = controlTitle.Publisher.ToString(); publisher = controlTitle.PublisherString.ToString();
break; break;
} }
@ -599,7 +599,7 @@ namespace Ryujinx.Ui.App
{ {
titleId = controlData.PresenceGroupId.ToString("x16"); titleId = controlData.PresenceGroupId.ToString("x16");
} }
else if (controlData.SaveDataOwnerId.Value != 0) else if (controlData.SaveDataOwnerId != 0)
{ {
titleId = controlData.SaveDataOwnerId.ToString(); titleId = controlData.SaveDataOwnerId.ToString();
} }
@ -612,7 +612,7 @@ namespace Ryujinx.Ui.App
titleId = "0000000000000000"; titleId = "0000000000000000";
} }
version = controlData.DisplayVersion.ToString(); version = controlData.DisplayVersionString.ToString();
} }
private bool IsUpdateApplied(string titleId, out IFileSystem updatedControlFs) private bool IsUpdateApplied(string titleId, out IFileSystem updatedControlFs)

View file

@ -6,7 +6,6 @@ using LibHac.Fs;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
using LibHac.Fs.Shim; using LibHac.Fs.Shim;
using LibHac.FsSystem; using LibHac.FsSystem;
using LibHac.Ncm;
using LibHac.Ns; using LibHac.Ns;
using LibHac.Tools.Fs; using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
@ -26,8 +25,6 @@ using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using static LibHac.Fs.ApplicationSaveDataManagement;
namespace Ryujinx.Ui.Widgets namespace Ryujinx.Ui.Widgets
{ {
public partial class GameTableContextMenu : Menu public partial class GameTableContextMenu : Menu
@ -81,7 +78,7 @@ namespace Ryujinx.Ui.Widgets
PopupAtPointer(null); PopupAtPointer(null);
} }
private bool TryFindSaveData(string titleName, ulong titleId, BlitStruct<ApplicationControlProperty> controlHolder, SaveDataFilter filter, out ulong saveDataId) private bool TryFindSaveData(string titleName, ulong titleId, BlitStruct<ApplicationControlProperty> controlHolder, in SaveDataFilter filter, out ulong saveDataId)
{ {
saveDataId = default; saveDataId = default;
@ -121,7 +118,7 @@ namespace Ryujinx.Ui.Widgets
Uid user = new Uid((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low); Uid user = new Uid((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low);
result = EnsureApplicationSaveData(_horizonClient.Fs, out _, new LibHac.Ncm.ApplicationId(titleId), ref control, ref user); result = _horizonClient.Fs.EnsureApplicationSaveData(out _, new LibHac.Ncm.ApplicationId(titleId), in control, in user);
if (result.IsFailure()) if (result.IsFailure())
{ {
@ -146,11 +143,9 @@ namespace Ryujinx.Ui.Widgets
return false; return false;
} }
private void OpenSaveDir(SaveDataFilter saveDataFilter) private void OpenSaveDir(in SaveDataFilter saveDataFilter)
{ {
saveDataFilter.SetProgramId(new ProgramId(_titleId)); if (!TryFindSaveData(_titleName, _titleId, _controlData, in saveDataFilter, out ulong saveDataId))
if (!TryFindSaveData(_titleName, _titleId, _controlData, saveDataFilter, out ulong saveDataId))
{ {
return; return;
} }
@ -439,26 +434,24 @@ namespace Ryujinx.Ui.Widgets
// //
private void OpenSaveUserDir_Clicked(object sender, EventArgs args) private void OpenSaveUserDir_Clicked(object sender, EventArgs args)
{ {
SaveDataFilter saveDataFilter = new SaveDataFilter(); var userId = new LibHac.Fs.UserId((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low);
saveDataFilter.SetUserId(new LibHac.Fs.UserId((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low)); var saveDataFilter = SaveDataFilter.Make(_titleId, saveType: default, userId, saveDataId: default, index: default);
OpenSaveDir(saveDataFilter); OpenSaveDir(in saveDataFilter);
} }
private void OpenSaveDeviceDir_Clicked(object sender, EventArgs args) private void OpenSaveDeviceDir_Clicked(object sender, EventArgs args)
{ {
SaveDataFilter saveDataFilter = new SaveDataFilter(); var saveDataFilter = SaveDataFilter.Make(_titleId, SaveDataType.Device, userId: default, saveDataId: default, index: default);
saveDataFilter.SetSaveDataType(SaveDataType.Device);
OpenSaveDir(saveDataFilter); OpenSaveDir(in saveDataFilter);
} }
private void OpenSaveBcatDir_Clicked(object sender, EventArgs args) private void OpenSaveBcatDir_Clicked(object sender, EventArgs args)
{ {
SaveDataFilter saveDataFilter = new SaveDataFilter(); var saveDataFilter = SaveDataFilter.Make(_titleId, SaveDataType.Bcat, userId: default, saveDataId: default, index: default);
saveDataFilter.SetSaveDataType(SaveDataType.Bcat);
OpenSaveDir(saveDataFilter); OpenSaveDir(in saveDataFilter);
} }
private void ManageTitleUpdates_Clicked(object sender, EventArgs args) private void ManageTitleUpdates_Clicked(object sender, EventArgs args)

View file

@ -105,7 +105,7 @@ namespace Ryujinx.Ui.Windows
controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref(), "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure(); controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref(), "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure(); nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
RadioButton radioButton = new RadioButton($"Version {controlData.DisplayVersion.ToString()} - {path}"); RadioButton radioButton = new RadioButton($"Version {controlData.DisplayVersionString.ToString()} - {path}");
radioButton.JoinGroup(_noUpdateRadioButton); radioButton.JoinGroup(_noUpdateRadioButton);
_availableUpdatesBox.Add(radioButton); _availableUpdatesBox.Add(radioButton);