forked from Mirror/Ryujinx
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:
parent
001005b3d5
commit
7344dee475
19 changed files with 89 additions and 81 deletions
|
@ -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))
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
@ -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!");
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -10,8 +10,8 @@ namespace Ryujinx.HLE.HOS.Services.Account
|
||||||
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,
|
||||||
|
|
|
@ -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.");
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue