account: Adds AccountManager (#2184)

* account: Adds Account Manager

In a way to have Custom User Profiles merged in master faster, this PR adds a `AccountManager` class (based on `AccountUtils` class) and the following changes have been made:
- Adds a "default profile values" which were the old hardcoded ones.
- The image profile is moved to the Account service folder.
- The hardcoded UserId for the savedata is now using the `AccountManager` last opened one.
- The DeviceId in Mii service is changed to the right value (checked by REd sys:set call).

* Fix csproj

* Addresses gdkchan's comments

* Fix UserProfile fields

* Fix mii GetDeviceId()

* Update Ryujinx.HLE.csproj
This commit is contained in:
Ac_K 2021-04-13 03:16:43 +02:00 committed by GitHub
parent 001005b3d5
commit 7344dee475
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 89 additions and 81 deletions

View File

@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Applets
private byte[] BuildResponse() private byte[] BuildResponse()
{ {
UserProfile currentUser = _system.State.Account.LastOpenedUser; UserProfile currentUser = _system.AccountManager.LastOpenedUser;
using (MemoryStream stream = new MemoryStream()) using (MemoryStream stream = new MemoryStream())
using (BinaryWriter writer = new BinaryWriter(stream)) using (BinaryWriter writer = new BinaryWriter(stream))

View File

@ -648,7 +648,7 @@ namespace Ryujinx.HLE.HOS
{ {
Logger.Info?.Print(LogClass.Application, "Ensuring required savedata exists."); Logger.Info?.Print(LogClass.Application, "Ensuring required savedata exists.");
Uid user = _device.System.State.Account.LastOpenedUser.UserId.ToLibHacUid(); Uid user = _device.System.AccountManager.LastOpenedUser.UserId.ToLibHacUid();
ref ApplicationControlProperty control = ref ControlData.Value; ref ApplicationControlProperty control = ref ControlData.Value;

View File

@ -18,6 +18,7 @@ using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.HLE.HOS.Services; using Ryujinx.HLE.HOS.Services;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy; using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy;
using Ryujinx.HLE.HOS.Services.Apm; using Ryujinx.HLE.HOS.Services.Apm;
using Ryujinx.HLE.HOS.Services.Arp; using Ryujinx.HLE.HOS.Services.Arp;
@ -86,6 +87,7 @@ namespace Ryujinx.HLE.HOS
internal KSharedMemory IirsSharedMem { get; private set; } internal KSharedMemory IirsSharedMem { get; private set; }
internal SharedFontManager Font { get; private set; } internal SharedFontManager Font { get; private set; }
internal AccountManager AccountManager { get; private set; }
internal ContentManager ContentManager { get; private set; } internal ContentManager ContentManager { get; private set; }
internal CaptureManager CaptureManager { get; private set; } internal CaptureManager CaptureManager { get; private set; }
@ -110,7 +112,7 @@ namespace Ryujinx.HLE.HOS
internal LibHac.Horizon LibHacHorizonServer { get; private set; } internal LibHac.Horizon LibHacHorizonServer { get; private set; }
internal HorizonClient LibHacHorizonClient { get; private set; } internal HorizonClient LibHacHorizonClient { get; private set; }
public Horizon(Switch device, ContentManager contentManager, MemoryConfiguration memoryConfiguration) public Horizon(Switch device, ContentManager contentManager, AccountManager accountManager, MemoryConfiguration memoryConfiguration)
{ {
KernelContext = new KernelContext( KernelContext = new KernelContext(
device, device,
@ -165,6 +167,7 @@ namespace Ryujinx.HLE.HOS
DisplayResolutionChangeEvent = new KEvent(KernelContext); DisplayResolutionChangeEvent = new KEvent(KernelContext);
AccountManager = accountManager;
ContentManager = contentManager; ContentManager = contentManager;
CaptureManager = new CaptureManager(device); CaptureManager = new CaptureManager(device);

View File

@ -1,23 +1,31 @@
using System.Collections.Concurrent; using Ryujinx.Common;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace Ryujinx.HLE.HOS.Services.Account.Acc namespace Ryujinx.HLE.HOS.Services.Account.Acc
{ {
public class AccountUtils public class AccountManager
{ {
private ConcurrentDictionary<string, UserProfile> _profiles; private ConcurrentDictionary<string, UserProfile> _profiles;
internal UserProfile LastOpenedUser { get; private set; } public UserProfile LastOpenedUser { get; private set; }
public AccountUtils() public AccountManager()
{ {
_profiles = new ConcurrentDictionary<string, UserProfile>(); _profiles = new ConcurrentDictionary<string, UserProfile>();
UserId defaultUserId = new UserId("00000000000000010000000000000000");
byte[] defaultUserImage = EmbeddedResources.Read("Ryujinx.HLE/HOS/Services/Account/Acc/DefaultUserImage.jpg");
AddUser(defaultUserId, "Player", defaultUserImage);
OpenUser(defaultUserId);
} }
public void AddUser(UserId userId, string name) public void AddUser(UserId userId, string name, byte[] image)
{ {
UserProfile profile = new UserProfile(userId, name); UserProfile profile = new UserProfile(userId, name, image);
_profiles.AddOrUpdate(userId.ToString(), profile, (key, old) => profile); _profiles.AddOrUpdate(userId.ToString(), profile, (key, old) => profile);
} }

View File

@ -1,8 +1,6 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Cpu; using Ryujinx.Cpu;
using Ryujinx.HLE.Utilities; using Ryujinx.HLE.Utilities;
using System.IO;
using System.Reflection;
using System.Text; using System.Text;
namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
@ -10,12 +8,10 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
class ProfileServer class ProfileServer
{ {
private UserProfile _profile; private UserProfile _profile;
private Stream _profilePictureStream;
public ProfileServer(UserProfile profile) public ProfileServer(UserProfile profile)
{ {
_profile = profile; _profile = profile;
_profilePictureStream = Assembly.GetCallingAssembly().GetManifestResourceStream("Ryujinx.HLE.RyujinxProfileImage.jpg");
} }
public ResultCode Get(ServiceCtx context) public ResultCode Get(ServiceCtx context)
@ -54,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
public ResultCode GetImageSize(ServiceCtx context) public ResultCode GetImageSize(ServiceCtx context)
{ {
context.ResponseData.Write(_profilePictureStream.Length); context.ResponseData.Write(_profile.Image.Length);
return ResultCode.Success; return ResultCode.Success;
} }
@ -64,13 +60,14 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
long bufferPosition = context.Request.ReceiveBuff[0].Position; long bufferPosition = context.Request.ReceiveBuff[0].Position;
long bufferLen = context.Request.ReceiveBuff[0].Size; long bufferLen = context.Request.ReceiveBuff[0].Size;
byte[] profilePictureData = new byte[bufferLen]; if (_profile.Image.Length > bufferLen)
{
return ResultCode.InvalidBufferSize;
}
_profilePictureStream.Read(profilePictureData, 0, profilePictureData.Length); context.Memory.Write((ulong)bufferPosition, _profile.Image);
context.Memory.Write((ulong)bufferPosition, profilePictureData); context.ResponseData.Write(_profile.Image.Length);
context.ResponseData.Write(_profilePictureStream.Length);
return ResultCode.Success; return ResultCode.Success;
} }
@ -100,16 +97,16 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
context.Memory.Read((ulong)userDataPosition, userData); context.Memory.Read((ulong)userDataPosition, userData);
long profilePicturePosition = context.Request.SendBuff[0].Position; long profileImagePosition = context.Request.SendBuff[0].Position;
long profilePictureSize = context.Request.SendBuff[0].Size; long profileImageSize = context.Request.SendBuff[0].Size;
byte[] profilePictureData = new byte[profilePictureSize]; byte[] profileImageData = new byte[profileImageSize];
context.Memory.Read((ulong)profilePicturePosition, profilePictureData); context.Memory.Read((ulong)profileImagePosition, profileImageData);
// TODO: Read the nn::account::profile::ProfileBase and store everything in the savedata. // TODO: Read the nn::account::profile::ProfileBase and store everything in the savedata.
Logger.Stub?.PrintStub(LogClass.ServiceAcc, new { userDataSize, profilePictureSize }); Logger.Stub?.PrintStub(LogClass.ServiceAcc, new { userDataSize, profileImageSize });
return ResultCode.Success; return ResultCode.Success;
} }

View File

@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
public ResultCode GetUserCountImpl(ServiceCtx context) public ResultCode GetUserCountImpl(ServiceCtx context)
{ {
context.ResponseData.Write(context.Device.System.State.Account.GetUserCount()); context.ResponseData.Write(context.Device.System.AccountManager.GetUserCount());
return ResultCode.Success; return ResultCode.Success;
} }
@ -31,26 +31,26 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
return resultCode; return resultCode;
} }
context.ResponseData.Write(context.Device.System.State.Account.TryGetUser(userId, out _)); context.ResponseData.Write(context.Device.System.AccountManager.TryGetUser(userId, out _));
return ResultCode.Success; return ResultCode.Success;
} }
public ResultCode ListAllUsers(ServiceCtx context) public ResultCode ListAllUsers(ServiceCtx context)
{ {
return WriteUserList(context, context.Device.System.State.Account.GetAllUsers()); return WriteUserList(context, context.Device.System.AccountManager.GetAllUsers());
} }
public ResultCode ListOpenUsers(ServiceCtx context) public ResultCode ListOpenUsers(ServiceCtx context)
{ {
return WriteUserList(context, context.Device.System.State.Account.GetOpenedUsers()); return WriteUserList(context, context.Device.System.AccountManager.GetOpenedUsers());
} }
private ResultCode WriteUserList(ServiceCtx context, IEnumerable<UserProfile> profiles) private ResultCode WriteUserList(ServiceCtx context, IEnumerable<UserProfile> profiles)
{ {
if (context.Request.RecvListBuff.Count == 0) if (context.Request.RecvListBuff.Count == 0)
{ {
return ResultCode.InvalidInputBuffer; return ResultCode.InvalidBuffer;
} }
long outputPosition = context.Request.RecvListBuff[0].Position; long outputPosition = context.Request.RecvListBuff[0].Position;
@ -78,7 +78,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
public ResultCode GetLastOpenedUser(ServiceCtx context) public ResultCode GetLastOpenedUser(ServiceCtx context)
{ {
context.Device.System.State.Account.LastOpenedUser.UserId.Write(context.ResponseData); context.Device.System.AccountManager.LastOpenedUser.UserId.Write(context.ResponseData);
return ResultCode.Success; return ResultCode.Success;
} }
@ -94,7 +94,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
return resultCode; return resultCode;
} }
if (!context.Device.System.State.Account.TryGetUser(userId, out UserProfile userProfile)) if (!context.Device.System.AccountManager.TryGetUser(userId, out UserProfile userProfile))
{ {
Logger.Warning?.Print(LogClass.ServiceAcc, $"User 0x{userId} not found!"); Logger.Warning?.Print(LogClass.ServiceAcc, $"User 0x{userId} not found!");
@ -118,7 +118,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
public ResultCode TrySelectUserWithoutInteraction(ServiceCtx context) public ResultCode TrySelectUserWithoutInteraction(ServiceCtx context)
{ {
if (context.Device.System.State.Account.GetUserCount() != 1) if (context.Device.System.AccountManager.GetUserCount() != 1)
{ {
// Invalid UserId. // Invalid UserId.
UserId.Null.Write(context.ResponseData); UserId.Null.Write(context.ResponseData);
@ -137,7 +137,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
} }
// NOTE: As we returned an invalid UserId if there is more than one user earlier, now we can return only the first one. // NOTE: As we returned an invalid UserId if there is more than one user earlier, now we can return only the first one.
context.Device.System.State.Account.GetFirst().UserId.Write(context.ResponseData); context.Device.System.AccountManager.GetFirst().UserId.Write(context.ResponseData);
return ResultCode.Success; return ResultCode.Success;
} }
@ -153,7 +153,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
if (context.Request.SendBuff.Count == 0) if (context.Request.SendBuff.Count == 0)
{ {
return ResultCode.InvalidInputBuffer; return ResultCode.InvalidBuffer;
} }
long inputPosition = context.Request.SendBuff[0].Position; long inputPosition = context.Request.SendBuff[0].Position;
@ -161,7 +161,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
if (inputSize != 0x24000) if (inputSize != 0x24000)
{ {
return ResultCode.InvalidInputBufferSize; return ResultCode.InvalidBufferSize;
} }
byte[] thumbnailBuffer = new byte[inputSize]; byte[] thumbnailBuffer = new byte[inputSize];
@ -205,7 +205,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
{ {
// TODO: Determine how users are "qualified". We assume all users are "qualified" for now. // TODO: Determine how users are "qualified". We assume all users are "qualified" for now.
return WriteUserList(context, context.Device.System.State.Account.GetAllUsers()); return WriteUserList(context, context.Device.System.AccountManager.GetAllUsers());
} }
public ResultCode CheckUserId(ServiceCtx context, out UserId userId) public ResultCode CheckUserId(ServiceCtx context, out UserId userId)

View File

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -111,7 +111,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
{ {
UserId userId = context.RequestData.ReadStruct<UserId>(); UserId userId = context.RequestData.ReadStruct<UserId>();
if (!context.Device.System.State.Account.TryGetUser(userId, out UserProfile userProfile)) if (!context.Device.System.AccountManager.TryGetUser(userId, out UserProfile userProfile))
{ {
Logger.Warning?.Print(LogClass.ServiceAcc, $"User 0x{userId} not found!"); Logger.Warning?.Print(LogClass.ServiceAcc, $"User 0x{userId} not found!");

View File

@ -1,26 +1,29 @@
using Ryujinx.HLE.Utilities; using System;
using System;
namespace Ryujinx.HLE.HOS.Services.Account.Acc namespace Ryujinx.HLE.HOS.Services.Account.Acc
{ {
class UserProfile public class UserProfile
{ {
private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public UserId UserId { get; private set; } public UserId UserId { get; }
public string Name { get; private set; } public string Name { get; }
public byte[] Image { get; }
public long LastModifiedTimestamp { get; private set; } public long LastModifiedTimestamp { get; private set; }
public AccountState AccountState { get; set; } public AccountState AccountState { get; set; }
public AccountState OnlinePlayState { get; set; } public AccountState OnlinePlayState { get; set; }
public UserProfile(UserId userId, string name) public UserProfile(UserId userId, string name, byte[] image)
{ {
UserId = userId; UserId = userId;
Name = name; Name = name;
Image = image;
LastModifiedTimestamp = 0; LastModifiedTimestamp = 0;
AccountState = AccountState.Closed; AccountState = AccountState.Closed;

View File

@ -7,17 +7,17 @@ namespace Ryujinx.HLE.HOS.Services.Account
Success = 0, Success = 0,
NullArgument = (20 << ErrorCodeShift) | ModuleId, NullArgument = (20 << ErrorCodeShift) | ModuleId,
InvalidArgument = (22 << ErrorCodeShift) | ModuleId, InvalidArgument = (22 << ErrorCodeShift) | ModuleId,
NullInputBuffer = (30 << ErrorCodeShift) | ModuleId, NullInputBuffer = (30 << ErrorCodeShift) | ModuleId,
InvalidInputBufferSize = (31 << ErrorCodeShift) | ModuleId, InvalidBufferSize = (31 << ErrorCodeShift) | ModuleId,
InvalidInputBuffer = (32 << ErrorCodeShift) | ModuleId, InvalidBuffer = (32 << ErrorCodeShift) | ModuleId,
AsyncExecutionNotInitialized = (40 << ErrorCodeShift) | ModuleId, AsyncExecutionNotInitialized = (40 << ErrorCodeShift) | ModuleId,
Unknown41 = (41 << ErrorCodeShift) | ModuleId, Unknown41 = (41 << ErrorCodeShift) | ModuleId,
InternetRequestDenied = (59 << ErrorCodeShift) | ModuleId, InternetRequestDenied = (59 << ErrorCodeShift) | ModuleId,
UserNotFound = (100 << ErrorCodeShift) | ModuleId, UserNotFound = (100 << ErrorCodeShift) | ModuleId,
NullObject = (302 << ErrorCodeShift) | ModuleId, NullObject = (302 << ErrorCodeShift) | ModuleId,
Unknown341 = (341 << ErrorCodeShift) | ModuleId, Unknown341 = (341 << ErrorCodeShift) | ModuleId,
InvalidIdTokenCacheBufferSize = (451 << ErrorCodeShift) | ModuleId InvalidIdTokenCacheBufferSize = (451 << ErrorCodeShift) | ModuleId
} }
} }

View File

@ -58,7 +58,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
break; break;
case LaunchParameterKind.PreselectedUser: case LaunchParameterKind.PreselectedUser:
// Only the first 0x18 bytes of the Data seems to be actually used. // Only the first 0x18 bytes of the Data seems to be actually used.
storageData = StorageHelper.MakeLaunchParams(context.Device.System.State.Account.LastOpenedUser); storageData = StorageHelper.MakeLaunchParams(context.Device.System.AccountManager.LastOpenedUser);
break; break;
case LaunchParameterKind.Unknown: case LaunchParameterKind.Unknown:
throw new NotImplementedException("Unknown LaunchParameterKind."); throw new NotImplementedException("Unknown LaunchParameterKind.");

View File

@ -150,7 +150,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
return ResultCode.InvalidArgument; return ResultCode.InvalidArgument;
} }
if (context.Device.System.State.Account.TryGetUser(userId, out UserProfile profile)) if (context.Device.System.AccountManager.TryGetUser(userId, out UserProfile profile))
{ {
profile.OnlinePlayState = AccountState.Open; profile.OnlinePlayState = AccountState.Open;
} }
@ -171,7 +171,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
return ResultCode.InvalidArgument; return ResultCode.InvalidArgument;
} }
if (context.Device.System.State.Account.TryGetUser(userId, out UserProfile profile)) if (context.Device.System.AccountManager.TryGetUser(userId, out UserProfile profile))
{ {
profile.OnlinePlayState = AccountState.Closed; profile.OnlinePlayState = AccountState.Closed;
} }

View File

@ -1,5 +1,4 @@
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.Utilities;
using Ryujinx.HLE.Utilities;
using System; using System;
using System.Buffers.Binary; using System.Buffers.Binary;
@ -32,7 +31,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii
public static UInt128 GetDeviceId() public static UInt128 GetDeviceId()
{ {
// FIXME: call set:sys GetMiiAuthorId // FIXME: call set:sys GetMiiAuthorId
return SystemStateMgr.DefaultUserId.ToUInt128(); return new UInt128(0, 1);
} }
public static ReadOnlySpan<byte> Ver3FacelineColorTable => new byte[] { 0, 1, 2, 3, 4, 5 }; public static ReadOnlySpan<byte> Ver3FacelineColorTable => new byte[] { 0, 1, 2, 3, 4, 5 };

View File

@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService
if (byUserId) if (byUserId)
{ {
if (!context.Device.System.State.Account.TryGetUser(userId, out _)) if (!context.Device.System.AccountManager.TryGetUser(userId, out _))
{ {
return ResultCode.UserNotFound; return ResultCode.UserNotFound;
} }

View File

@ -1,12 +1,9 @@
using Ryujinx.HLE.HOS.Services.Account.Acc;
using System; using System;
namespace Ryujinx.HLE.HOS.SystemState namespace Ryujinx.HLE.HOS.SystemState
{ {
public class SystemStateMgr public class SystemStateMgr
{ {
public static readonly UserId DefaultUserId = new UserId("00000000000000010000000000000000");
internal static string[] LanguageCodes = new string[] internal static string[] LanguageCodes = new string[]
{ {
"ja", "ja",
@ -46,15 +43,8 @@ namespace Ryujinx.HLE.HOS.SystemState
public bool InstallContents { get; set; } public bool InstallContents { get; set; }
public AccountUtils Account { get; private set; }
public SystemStateMgr() public SystemStateMgr()
{ {
Account = new AccountUtils();
Account.AddUser(DefaultUserId, "Player");
Account.OpenUser(DefaultUserId);
// TODO: Let user specify. // TODO: Let user specify.
DesiredKeyboardLayout = (long)KeyboardLayout.Default; DesiredKeyboardLayout = (long)KeyboardLayout.Default;
} }

View File

@ -32,12 +32,12 @@
<ItemGroup> <ItemGroup>
<None Remove="Homebrew.npdm" /> <None Remove="Homebrew.npdm" />
<None Remove="RyujinxProfileImage.jpg" /> <None Remove="HOS\Services\Account\Acc\DefaultUserImage.jpg" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Homebrew.npdm" /> <EmbeddedResource Include="Homebrew.npdm" />
<EmbeddedResource Include="RyujinxProfileImage.jpg" /> <EmbeddedResource Include="HOS\Services\Account\Acc\DefaultUserImage.jpg" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -13,6 +13,7 @@ using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.FileSystem.Content;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.HLE.HOS.Services; using Ryujinx.HLE.HOS.Services;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.Services.Apm; using Ryujinx.HLE.HOS.Services.Apm;
using Ryujinx.HLE.HOS.Services.Hid; using Ryujinx.HLE.HOS.Services.Hid;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices;
@ -57,6 +58,7 @@ namespace Ryujinx.HLE
public Switch( public Switch(
VirtualFileSystem fileSystem, VirtualFileSystem fileSystem,
ContentManager contentManager, ContentManager contentManager,
AccountManager accountManager,
UserChannelPersistence userChannelPersistence, UserChannelPersistence userChannelPersistence,
IRenderer renderer, IRenderer renderer,
IHardwareDeviceDriver audioDeviceDriver, IHardwareDeviceDriver audioDeviceDriver,
@ -112,7 +114,7 @@ namespace Ryujinx.HLE
FileSystem = fileSystem; FileSystem = fileSystem;
System = new Horizon(this, contentManager, memoryConfiguration); System = new Horizon(this, contentManager, accountManager, memoryConfiguration);
System.InitializeServices(); System.InitializeServices();
Statistics = new PerformanceStatistics(); Statistics = new PerformanceStatistics();

View File

@ -3,7 +3,6 @@ using ARMeilleure.Translation.PTC;
using Gtk; using Gtk;
using LibHac.Common; using LibHac.Common;
using LibHac.Ns; using LibHac.Ns;
using Ryujinx.Audio;
using Ryujinx.Audio.Backends.Dummy; using Ryujinx.Audio.Backends.Dummy;
using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SoundIo; using Ryujinx.Audio.Backends.SoundIo;
@ -17,6 +16,7 @@ using Ryujinx.Graphics.OpenGL;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.FileSystem.Content;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.Modules; using Ryujinx.Modules;
using Ryujinx.Ui.App; using Ryujinx.Ui.App;
using Ryujinx.Ui.Applet; using Ryujinx.Ui.Applet;
@ -42,6 +42,7 @@ namespace Ryujinx.Ui
{ {
private readonly VirtualFileSystem _virtualFileSystem; private readonly VirtualFileSystem _virtualFileSystem;
private readonly ContentManager _contentManager; private readonly ContentManager _contentManager;
private readonly AccountManager _accountManager;
private UserChannelPersistence _userChannelPersistence; private UserChannelPersistence _userChannelPersistence;
@ -135,6 +136,7 @@ namespace Ryujinx.Ui
// Instanciate HLE objects. // Instanciate HLE objects.
_virtualFileSystem = VirtualFileSystem.CreateInstance(); _virtualFileSystem = VirtualFileSystem.CreateInstance();
_contentManager = new ContentManager(_virtualFileSystem); _contentManager = new ContentManager(_virtualFileSystem);
_accountManager = new AccountManager();
_userChannelPersistence = new UserChannelPersistence(); _userChannelPersistence = new UserChannelPersistence();
// Instanciate GUI objects. // Instanciate GUI objects.
@ -344,6 +346,7 @@ namespace Ryujinx.Ui
_emulationContext = new HLE.Switch( _emulationContext = new HLE.Switch(
_virtualFileSystem, _virtualFileSystem,
_contentManager, _contentManager,
_accountManager,
_userChannelPersistence, _userChannelPersistence,
renderer, renderer,
deviceDriver, deviceDriver,
@ -942,7 +945,7 @@ namespace Ryujinx.Ui
BlitStruct<ApplicationControlProperty> controlData = (BlitStruct<ApplicationControlProperty>)_tableStore.GetValue(treeIter, 10); BlitStruct<ApplicationControlProperty> controlData = (BlitStruct<ApplicationControlProperty>)_tableStore.GetValue(treeIter, 10);
_ = new GameTableContextMenu(this, _virtualFileSystem, titleFilePath, titleName, titleId, controlData); _ = new GameTableContextMenu(this, _virtualFileSystem, _accountManager, titleFilePath, titleName, titleId, controlData);
} }
private void Load_Application_File(object sender, EventArgs args) private void Load_Application_File(object sender, EventArgs args)

View File

@ -13,6 +13,7 @@ using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.Ui.Helper; using Ryujinx.Ui.Helper;
using Ryujinx.Ui.Windows; using Ryujinx.Ui.Windows;
using System; using System;
@ -31,6 +32,7 @@ namespace Ryujinx.Ui.Widgets
{ {
private readonly MainWindow _parent; private readonly MainWindow _parent;
private readonly VirtualFileSystem _virtualFileSystem; private readonly VirtualFileSystem _virtualFileSystem;
private readonly AccountManager _accountManager;
private readonly BlitStruct<ApplicationControlProperty> _controlData; private readonly BlitStruct<ApplicationControlProperty> _controlData;
private readonly string _titleFilePath; private readonly string _titleFilePath;
@ -41,13 +43,14 @@ namespace Ryujinx.Ui.Widgets
private MessageDialog _dialog; private MessageDialog _dialog;
private bool _cancel; private bool _cancel;
public GameTableContextMenu(MainWindow parent, VirtualFileSystem virtualFileSystem, string titleFilePath, string titleName, string titleId, BlitStruct<ApplicationControlProperty> controlData) public GameTableContextMenu(MainWindow parent, VirtualFileSystem virtualFileSystem, AccountManager accountManager, string titleFilePath, string titleName, string titleId, BlitStruct<ApplicationControlProperty> controlData)
{ {
_parent = parent; _parent = parent;
InitializeComponent(); InitializeComponent();
_virtualFileSystem = virtualFileSystem; _virtualFileSystem = virtualFileSystem;
_accountManager = accountManager;
_titleFilePath = titleFilePath; _titleFilePath = titleFilePath;
_titleName = titleName; _titleName = titleName;
_titleIdText = titleId; _titleIdText = titleId;
@ -429,7 +432,7 @@ namespace Ryujinx.Ui.Widgets
private void OpenSaveUserDir_Clicked(object sender, EventArgs args) private void OpenSaveUserDir_Clicked(object sender, EventArgs args)
{ {
SaveDataFilter saveDataFilter = new SaveDataFilter(); SaveDataFilter saveDataFilter = new SaveDataFilter();
saveDataFilter.SetUserId(new UserId(1, 0)); // TODO: Remove Hardcoded value. saveDataFilter.SetUserId(new LibHac.Fs.UserId((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low));
OpenSaveDir(saveDataFilter); OpenSaveDir(saveDataFilter);
} }