Merge branch 'master' into CoOp

This commit is contained in:
John Clemis 2018-08-15 02:49:14 -05:00 committed by GitHub
commit 097d590dde
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 411 additions and 167 deletions

View file

@ -305,7 +305,7 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.UseSse && AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.AddScalar));
EmitScalarSseOrSse2CallF(Context, nameof(Sse.AddScalar));
}
else
{
@ -317,7 +317,7 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.UseSse && AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.Add));
EmitVectorSseOrSse2CallF(Context, nameof(Sse.Add));
}
else
{
@ -375,7 +375,7 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.UseSse && AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.DivideScalar));
EmitScalarSseOrSse2CallF(Context, nameof(Sse.DivideScalar));
}
else
{
@ -387,7 +387,7 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.UseSse && AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.Divide));
EmitVectorSseOrSse2CallF(Context, nameof(Sse.Divide));
}
else
{
@ -526,7 +526,7 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.UseSse && AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.MultiplyScalar));
EmitScalarSseOrSse2CallF(Context, nameof(Sse.MultiplyScalar));
}
else
{
@ -543,7 +543,7 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.UseSse && AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.Multiply));
EmitVectorSseOrSse2CallF(Context, nameof(Sse.Multiply));
}
else
{
@ -910,7 +910,7 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.UseSse && AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.SubtractScalar));
EmitScalarSseOrSse2CallF(Context, nameof(Sse.SubtractScalar));
}
else
{
@ -922,7 +922,7 @@ namespace ChocolArm64.Instruction
{
if (AOptimizations.UseSse && AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.Subtract));
EmitVectorSseOrSse2CallF(Context, nameof(Sse.Subtract));
}
else
{

View file

@ -158,7 +158,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.CompareEqualScalar));
EmitScalarSseOrSse2CallF(Context, nameof(Sse.CompareEqualScalar));
}
else
{
@ -171,7 +171,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.CompareEqual));
EmitVectorSseOrSse2CallF(Context, nameof(Sse.CompareEqual));
}
else
{
@ -184,7 +184,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanOrEqualScalar));
EmitScalarSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanOrEqualScalar));
}
else
{
@ -197,7 +197,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanOrEqual));
EmitVectorSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanOrEqual));
}
else
{
@ -210,7 +210,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanScalar));
EmitScalarSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanScalar));
}
else
{
@ -223,7 +223,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2)
{
EmitSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThan));
EmitVectorSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThan));
}
else
{

View file

@ -110,7 +110,17 @@ namespace ChocolArm64.Instruction
}
}
public static void EmitSseOrSse2CallF(AILEmitterCtx Context, string Name)
public static void EmitScalarSseOrSse2CallF(AILEmitterCtx Context, string Name)
{
EmitSseOrSse2CallF(Context, Name, true);
}
public static void EmitVectorSseOrSse2CallF(AILEmitterCtx Context, string Name)
{
EmitSseOrSse2CallF(Context, Name, false);
}
public static void EmitSseOrSse2CallF(AILEmitterCtx Context, string Name, bool Scalar)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
@ -160,7 +170,18 @@ namespace ChocolArm64.Instruction
Context.EmitStvec(Op.Rd);
if (Op.RegisterSize == ARegisterSize.SIMD64)
if (Scalar)
{
if (SizeF == 0)
{
EmitVectorZero32_128(Context, Op.Rd);
}
else /* if (SizeF == 1) */
{
EmitVectorZeroUpper(Context, Op.Rd);
}
}
else if (Op.RegisterSize == ARegisterSize.SIMD64)
{
EmitVectorZeroUpper(Context, Op.Rd);
}
@ -1238,6 +1259,15 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(Context, Rd, 1, 3, 0);
}
public static void EmitVectorZero32_128(AILEmitterCtx Context, int Reg)
{
Context.EmitLdvec(Reg);
AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorZero32_128));
Context.EmitStvec(Reg);
}
public static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size)
{
ThrowIfInvalid(Index, Size);

View file

@ -9,6 +9,18 @@ namespace ChocolArm64.Instruction
{
static class AVectorHelper
{
private static readonly Vector128<float> Zero32_128Mask;
static AVectorHelper()
{
if (!Sse2.IsSupported)
{
throw new PlatformNotSupportedException();
}
Zero32_128Mask = Sse.StaticCast<uint, float>(Sse2.SetVector128(0, 0, 0, 0xffffffff));
}
public static void EmitCall(AILEmitterCtx Context, string Name64, string Name128)
{
bool IsSimd64 = Context.CurrOp.RegisterSize == ARegisterSize.SIMD64;
@ -448,6 +460,17 @@ namespace ChocolArm64.Instruction
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<float> VectorZero32_128(Vector128<float> Vector)
{
if (Sse.IsSupported)
{
return Sse.And(Vector, Zero32_128Mask);
}
throw new PlatformNotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<sbyte> VectorSingleToSByte(Vector128<float> Vector)
{

View file

@ -80,6 +80,14 @@ namespace Ryujinx.HLE.Gpu.Engines
}
}
public void ResetCache()
{
foreach (List<long> Uploaded in UploadedKeys)
{
Uploaded.Clear();
}
}
private void VertexEndGl(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
{
LockCaches();
@ -623,11 +631,6 @@ namespace Ryujinx.HLE.Gpu.Engines
if (Mode == 0)
{
foreach (List<long> Uploaded in UploadedKeys)
{
Uploaded.Clear();
}
//Write mode.
Vmm.WriteInt32(Position, Seq);
}
@ -649,6 +652,8 @@ namespace Ryujinx.HLE.Gpu.Engines
}
WriteRegister(NvGpuEngine3dReg.ConstBufferOffset, Offset);
UploadedKeys[(int)NvGpuBufferType.ConstBuffer].Clear();
}
private void CbBind(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)

View file

@ -15,7 +15,7 @@ namespace Ryujinx.HLE.Gpu.Engines
private NvGpu Gpu;
private ConcurrentQueue<(NvGpuVmm, NvGpuPBEntry)> BufferQueue;
private ConcurrentQueue<(NvGpuVmm, NvGpuPBEntry[])> BufferQueue;
private NvGpuEngine[] SubChannels;
@ -56,7 +56,7 @@ namespace Ryujinx.HLE.Gpu.Engines
{
this.Gpu = Gpu;
BufferQueue = new ConcurrentQueue<(NvGpuVmm, NvGpuPBEntry)>();
BufferQueue = new ConcurrentQueue<(NvGpuVmm, NvGpuPBEntry[])>();
SubChannels = new NvGpuEngine[8];
@ -69,10 +69,7 @@ namespace Ryujinx.HLE.Gpu.Engines
public void PushBuffer(NvGpuVmm Vmm, NvGpuPBEntry[] Buffer)
{
foreach (NvGpuPBEntry PBEntry in Buffer)
{
BufferQueue.Enqueue((Vmm, PBEntry));
}
BufferQueue.Enqueue((Vmm, Buffer));
Event.Set();
}
@ -82,16 +79,27 @@ namespace Ryujinx.HLE.Gpu.Engines
while (Step());
}
private (NvGpuVmm Vmm, NvGpuPBEntry[] Pb) Curr;
private int CurrPbEntryIndex;
public bool Step()
{
if (BufferQueue.TryDequeue(out (NvGpuVmm Vmm, NvGpuPBEntry PBEntry) Tuple))
while (Curr.Pb == null || Curr.Pb.Length <= CurrPbEntryIndex)
{
CallMethod(Tuple.Vmm, Tuple.PBEntry);
if (!BufferQueue.TryDequeue(out Curr))
{
return false;
}
return true;
Gpu.Engine3d.ResetCache();
CurrPbEntryIndex = 0;
}
return false;
CallMethod(Curr.Vmm, Curr.Pb[CurrPbEntryIndex++]);
return true;
}
private void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)

View file

@ -2,6 +2,7 @@ using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.HLE.Loaders.Npdm;
using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle.Handles;
using Ryujinx.HLE.OsHle.SystemState;
using System;
using System.Collections.Concurrent;
using System.IO;

View file

@ -242,6 +242,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
Process.Scheduler.Suspend(CurrThread);
IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
long Result = IpcHandler.IpcCall(Ns, Process, Memory, Session, Cmd, CmdPtr);
Thread.Yield();

View file

@ -11,6 +11,7 @@ using Ryujinx.HLE.OsHle.Exceptions;
using Ryujinx.HLE.OsHle.Handles;
using Ryujinx.HLE.OsHle.Kernel;
using Ryujinx.HLE.OsHle.Services.Nv;
using Ryujinx.HLE.OsHle.SystemState;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

View file

@ -1,8 +0,0 @@
namespace Ryujinx.HLE.OsHle
{
public struct Profile
{
public string Username;
public string UserId;
}
}

View file

@ -0,0 +1,7 @@
namespace Ryujinx.HLE.OsHle.Services.Acc
{
static class AccErr
{
public const int UserNotFound = 100;
}
}

View file

@ -1,7 +1,11 @@
using ChocolArm64.Memory;
using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle.Ipc;
using Ryujinx.HLE.OsHle.SystemState;
using System.Collections.Generic;
using static Ryujinx.HLE.OsHle.ErrorCode;
namespace Ryujinx.HLE.OsHle.Services.Acc
{
class IAccountServiceForApplication : IpcService
@ -27,49 +31,80 @@ namespace Ryujinx.HLE.OsHle.Services.Acc
public long GetUserCount(ServiceCtx Context)
{
Context.ResponseData.Write(0);
Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed.");
Context.ResponseData.Write(Context.Ns.Os.SystemState.GetUserCount());
return 0;
}
public long GetUserExistence(ServiceCtx Context)
{
Context.ResponseData.Write(1);
UserId Uuid = new UserId(
Context.RequestData.ReadInt64(),
Context.RequestData.ReadInt64());
Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed.");
Context.ResponseData.Write(Context.Ns.Os.SystemState.TryGetUser(Uuid, out _) ? 1 : 0);
return 0;
}
public long ListAllUsers(ServiceCtx Context)
{
Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed.");
return 0;
return WriteUserList(Context, Context.Ns.Os.SystemState.GetAllUsers());
}
public long ListOpenUsers(ServiceCtx Context)
{
Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed.");
return WriteUserList(Context, Context.Ns.Os.SystemState.GetOpenUsers());
}
private long WriteUserList(ServiceCtx Context, IEnumerable<UserProfile> Profiles)
{
long OutputPosition = Context.Request.RecvListBuff[0].Position;
long OutputSize = Context.Request.RecvListBuff[0].Size;
long Offset = 0;
foreach (UserProfile Profile in Profiles)
{
if ((ulong)Offset + 16 > (ulong)OutputSize)
{
break;
}
byte[] Uuid = Profile.Uuid.Bytes;
for (int Index = Uuid.Length - 1; Index >= 0; Index--)
{
Context.Memory.WriteByte(OutputPosition + Offset++, Uuid[Index]);
}
}
return 0;
}
public long GetLastOpenedUser(ServiceCtx Context)
{
Context.ResponseData.Write(1L);
Context.ResponseData.Write(0L);
UserProfile LastOpened = Context.Ns.Os.SystemState.LastOpenUser;
Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed.");
LastOpened.Uuid.Write(Context.ResponseData);
return 0;
}
public long GetProfile(ServiceCtx Context)
{
MakeObject(Context, new IProfile());
UserId Uuid = new UserId(
Context.RequestData.ReadInt64(),
Context.RequestData.ReadInt64());
if (!Context.Ns.Os.SystemState.TryGetUser(Uuid, out UserProfile Profile))
{
Context.Ns.Log.PrintWarning(LogClass.ServiceAcc, $"User 0x{Uuid} not found!");
return MakeError(ErrorModule.Account, AccErr.UserNotFound);
}
MakeObject(Context, new IProfile(Profile));
return 0;
}

View file

@ -1,6 +1,7 @@
using ChocolArm64.Memory;
using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle.Ipc;
using Ryujinx.HLE.OsHle.SystemState;
using Ryujinx.HLE.OsHle.Utilities;
using System.Collections.Generic;
using System.Text;
@ -13,13 +14,17 @@ namespace Ryujinx.HLE.OsHle.Services.Acc
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IProfile()
private UserProfile Profile;
public IProfile(UserProfile Profile)
{
m_Commands = new Dictionary<int, ServiceProcessRequest>()
{
{ 0, Get },
{ 1, GetBase }
};
this.Profile = Profile;
}
public long Get(ServiceCtx Context)
@ -32,20 +37,18 @@ namespace Ryujinx.HLE.OsHle.Services.Acc
Context.Memory.WriteInt32(Position, 0);
Context.Memory.WriteInt32(Position + 4, 1);
Context.Memory.WriteByte(Position + 8, 1);
Context.Memory.WriteInt64(Position + 8, 1);
return GetBase(Context);
}
public long GetBase(ServiceCtx Context)
{
ProfileBase ProfileBase = new ProfileBase(Context.Ns.Settings.User);
Profile.Uuid.Write(Context.ResponseData);
Context.ResponseData.Write(ProfileBase.UserId.ToBytes());
Context.ResponseData.Write(ProfileBase.Timestamp);
Context.ResponseData.Write(Profile.LastModifiedTimestamp);
int ByteCount = Encoding.UTF8.GetByteCount(ProfileBase.Username);
byte[] Username = StringUtils.GetFixedLengthBytes(ProfileBase.Username, 0x20, Encoding.UTF8);
byte[] Username = StringUtils.GetFixedLengthBytes(Profile.Name, 0x20, Encoding.UTF8);
Context.ResponseData.Write(Username);

View file

@ -1,52 +0,0 @@
using Ryujinx.HLE.OsHle.Utilities;
using System;
using System.Linq;
namespace Ryujinx.HLE.OsHle.Services.Acc
{
struct ProfileBase
{
public UserId UserId;
public long Timestamp;
public string Username;
public ProfileBase(Profile User)
{
UserId = new UserId(User.UserId);
Username = User.Username;
Timestamp = ((DateTimeOffset)DateTime.Today).ToUnixTimeSeconds();
}
}
struct UserId
{
private readonly ulong LowBytes;
private readonly ulong HighBytes;
public UserId(string UserIdHex)
{
if (UserIdHex == null || UserIdHex.Length != 32 || !UserIdHex.All("0123456789abcdefABCDEF".Contains))
{
throw new ArgumentException("UserId is not a valid Hex string", "UserIdHex");
}
byte[] HexBytes = StringUtils.HexToBytes(UserIdHex);
LowBytes = BitConverter.ToUInt64(HexBytes, 8);
Array.Resize(ref HexBytes, 8);
HighBytes = BitConverter.ToUInt64(HexBytes, 0);
}
public byte[] ToBytes()
{
return BitConverter.GetBytes(HighBytes).Concat(BitConverter.GetBytes(LowBytes)).ToArray();
}
public override string ToString()
{
return BitConverter.ToString(ToBytes()).ToLower().Replace("-", string.Empty);
}
}
}

View file

@ -3,7 +3,6 @@ using Ryujinx.HLE.OsHle.Handles;
using Ryujinx.HLE.OsHle.Ipc;
using System.Collections.Generic;
using static Ryujinx.HLE.OsHle.SystemStateMgr;
using static Ryujinx.HLE.OsHle.ErrorCode;
namespace Ryujinx.HLE.OsHle.Services.Am
@ -58,7 +57,9 @@ namespace Ryujinx.HLE.OsHle.Services.Am
public long GetOperationMode(ServiceCtx Context)
{
OperationMode Mode = DockedMode ? OperationMode.Docked : OperationMode.Handheld;
OperationMode Mode = Context.Ns.Os.SystemState.DockedMode
? OperationMode.Docked
: OperationMode.Handheld;
Context.ResponseData.Write((byte)Mode);
@ -67,7 +68,9 @@ namespace Ryujinx.HLE.OsHle.Services.Am
public long GetPerformanceMode(ServiceCtx Context)
{
Apm.PerformanceMode Mode = DockedMode ? Apm.PerformanceMode.Docked : Apm.PerformanceMode.Handheld;
Apm.PerformanceMode Mode = Context.Ns.Os.SystemState.DockedMode
? Apm.PerformanceMode.Docked
: Apm.PerformanceMode.Handheld;
Context.ResponseData.Write((int)Mode);

View file

@ -1,6 +1,7 @@
using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle.Handles;
using Ryujinx.HLE.OsHle.Ipc;
using Ryujinx.HLE.OsHle.SystemState;
using System.Collections.Generic;
using System.Text;

View file

@ -1,4 +1,6 @@
using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle.Ipc;
using Ryujinx.HLE.OsHle.SystemState;
using System.Collections.Generic;
namespace Ryujinx.HLE.OsHle.Services.Friend
@ -13,8 +15,35 @@ namespace Ryujinx.HLE.OsHle.Services.Friend
{
m_Commands = new Dictionary<int, ServiceProcessRequest>()
{
//...
{ 10601, DeclareCloseOnlinePlaySession },
{ 10610, UpdateUserPresence }
};
}
public long DeclareCloseOnlinePlaySession(ServiceCtx Context)
{
UserId Uuid = new UserId(
Context.RequestData.ReadInt64(),
Context.RequestData.ReadInt64());
if (Context.Ns.Os.SystemState.TryGetUser(Uuid, out UserProfile Profile))
{
Profile.OnlinePlayState = OpenCloseState.Closed;
}
return 0;
}
public long UpdateUserPresence(ServiceCtx Context)
{
UserId Uuid = new UserId(
Context.RequestData.ReadInt64(),
Context.RequestData.ReadInt64());
//TODO.
Context.Ns.Log.PrintStub(LogClass.ServiceFriend, "Stubbed.");
return 0;
}
}
}

View file

@ -1,4 +1,5 @@
using Ryujinx.HLE.OsHle.Ipc;
using Ryujinx.HLE.OsHle.SystemState;
using System.Collections.Generic;
namespace Ryujinx.HLE.OsHle.Services.Set

View file

@ -1,5 +1,5 @@
using Ryujinx.HLE.OsHle.Ipc;
using Ryujinx.HLE.Settings;
using Ryujinx.HLE.OsHle.SystemState;
using System;
using System.Collections.Generic;
using System.IO;
@ -75,7 +75,7 @@ namespace Ryujinx.HLE.OsHle.Services.Set
public static long GetColorSetId(ServiceCtx Context)
{
Context.ResponseData.Write((int)Context.Ns.Settings.ThemeColor);
Context.ResponseData.Write((int)Context.Ns.Os.SystemState.ThemeColor);
return 0;
}
@ -84,7 +84,8 @@ namespace Ryujinx.HLE.OsHle.Services.Set
{
int ColorSetId = Context.RequestData.ReadInt32();
Context.Ns.Settings.ThemeColor = (ColorSet)ColorSetId;
Context.Ns.Os.SystemState.ThemeColor = (ColorSet)ColorSetId;
return 0;
}
@ -121,6 +122,7 @@ namespace Ryujinx.HLE.OsHle.Services.Set
SettingBuffer = Encoding.ASCII.GetBytes(StringValue + "\0");
}
}
if (NxSetting is int IntValue)
{
SettingBuffer = BitConverter.GetBytes(IntValue);

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.OsHle.Services.Am;
using System;
using System.Collections.Concurrent;
namespace Ryujinx.HLE.OsHle
namespace Ryujinx.HLE.OsHle.SystemState
{
class AppletStateMgr : IDisposable
{

View file

@ -1,4 +1,4 @@
namespace Ryujinx.HLE.Settings
namespace Ryujinx.HLE.OsHle.SystemState
{
public enum ColorSet
{

View file

@ -0,0 +1,8 @@
namespace Ryujinx.HLE.OsHle.SystemState
{
public enum OpenCloseState
{
Closed,
Open
}
}

View file

@ -1,4 +1,4 @@
namespace Ryujinx.HLE.OsHle
namespace Ryujinx.HLE.OsHle.SystemState
{
public enum SystemLanguage
{

View file

@ -1,7 +1,9 @@
using Ryujinx.HLE.Loaders.Npdm;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.HLE.OsHle
namespace Ryujinx.HLE.OsHle.SystemState
{
public class SystemStateMgr
{
@ -36,14 +38,27 @@ namespace Ryujinx.HLE.OsHle
internal long DesiredLanguageCode { get; private set; }
internal string ActiveAudioOutput { get; private set; }
public static bool DockedMode { get; set; }
public bool DockedMode { get; set; }
public ColorSet ThemeColor { get; set; }
private ConcurrentDictionary<string, UserProfile> Profiles;
internal UserProfile LastOpenUser { get; private set; }
public SystemStateMgr()
{
SetLanguage(SystemLanguage.AmericanEnglish);
SetAudioOutputAsBuiltInSpeaker();
Profiles = new ConcurrentDictionary<string, UserProfile>();
UserId DefaultUuid = new UserId("00000000000000000000000000000001");
AddUser(DefaultUuid, "Player");
OpenUser(DefaultUuid);
}
public void SetLanguage(SystemLanguage Language)
@ -66,6 +81,49 @@ namespace Ryujinx.HLE.OsHle
ActiveAudioOutput = AudioOutputs[2];
}
public void AddUser(UserId Uuid, string Name)
{
UserProfile Profile = new UserProfile(Uuid, Name);
Profiles.AddOrUpdate(Uuid.UserIdHex, Profile, (Key, Old) => Profile);
}
public void OpenUser(UserId Uuid)
{
if (Profiles.TryGetValue(Uuid.UserIdHex, out UserProfile Profile))
{
(LastOpenUser = Profile).AccountState = OpenCloseState.Open;
}
}
public void CloseUser(UserId Uuid)
{
if (Profiles.TryGetValue(Uuid.UserIdHex, out UserProfile Profile))
{
Profile.AccountState = OpenCloseState.Closed;
}
}
public int GetUserCount()
{
return Profiles.Count;
}
internal bool TryGetUser(UserId Uuid, out UserProfile Profile)
{
return Profiles.TryGetValue(Uuid.UserIdHex, out Profile);
}
internal IEnumerable<UserProfile> GetAllUsers()
{
return Profiles.Values;
}
internal IEnumerable<UserProfile> GetOpenUsers()
{
return Profiles.Values.Where(x => x.AccountState == OpenCloseState.Open);
}
internal static long GetLanguageCode(int Index)
{
if ((uint)Index >= LanguageCodes.Length)

View file

@ -0,0 +1,76 @@
using Ryujinx.HLE.OsHle.Utilities;
using System;
using System.IO;
using System.Linq;
namespace Ryujinx.HLE.OsHle.SystemState
{
public struct UserId
{
public string UserIdHex { get; private set; }
public byte[] Bytes { get; private set; }
public UserId(long Low, long High)
{
if ((Low | High) == 0)
{
throw new ArgumentException("Zero is not a valid user id!");
}
byte[] Bytes = new byte[16];
int Index = Bytes.Length;
void WriteBytes(long Value)
{
for (int Byte = 0; Byte < 8; Byte++)
{
Bytes[--Index] = (byte)(Value >> Byte * 8);
}
}
WriteBytes(Low);
WriteBytes(High);
UserIdHex = string.Empty;
foreach (byte Byte in Bytes)
{
UserIdHex += Byte.ToString("X2");
}
this.Bytes = Bytes;
}
public UserId(string UserIdHex)
{
if (UserIdHex == null || UserIdHex.Length != 32 || !UserIdHex.All("0123456789abcdefABCDEF".Contains))
{
throw new ArgumentException("Invalid user id!", nameof(UserIdHex));
}
if (UserIdHex == "00000000000000000000000000000000")
{
throw new ArgumentException("Zero is not a valid user id!", nameof(UserIdHex));
}
this.UserIdHex = UserIdHex.ToUpper();
Bytes = StringUtils.HexToBytes(UserIdHex);
}
internal void Write(BinaryWriter Writer)
{
for (int Index = Bytes.Length - 1; Index >= 0; Index--)
{
Writer.Write(Bytes[Index]);
}
}
public override string ToString()
{
return UserIdHex;
}
}
}

View file

@ -0,0 +1,36 @@
using System;
namespace Ryujinx.HLE.OsHle.SystemState
{
class UserProfile
{
private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public UserId Uuid { get; private set; }
public string Name { get; private set; }
public long LastModifiedTimestamp { get; private set; }
public OpenCloseState AccountState { get; set; }
public OpenCloseState OnlinePlayState { get; set; }
public UserProfile(UserId Uuid, string Name)
{
this.Uuid = Uuid;
this.Name = Name;
LastModifiedTimestamp = 0;
AccountState = OpenCloseState.Closed;
OnlinePlayState = OpenCloseState.Closed;
UpdateTimestamp();
}
private void UpdateTimestamp()
{
LastModifiedTimestamp = (long)(DateTime.Now - Epoch).TotalSeconds;
}
}
}

View file

@ -11,13 +11,13 @@ namespace Ryujinx.HLE.OsHle.Utilities
{
InputString = InputString + "\0";
int ByteCount = Encoding.GetByteCount(InputString);
int BytesCount = Encoding.GetByteCount(InputString);
byte[] Output = new byte[Size];
if (ByteCount < Size)
if (BytesCount < Size)
{
Encoding.GetBytes(InputString, 0, InputString.Length, Output, Size - ByteCount);
Encoding.GetBytes(InputString, 0, InputString.Length, Output, 0);
}
else
{
@ -35,15 +35,14 @@ namespace Ryujinx.HLE.OsHle.Utilities
public static byte[] HexToBytes(string HexString)
{
//Ignore last charactor if HexLength % 2 != 0
//Ignore last charactor if HexLength % 2 != 0.
int BytesInHex = HexString.Length / 2;
byte[] Output = new byte[BytesInHex];
for (int Index = 0; Index < BytesInHex; Index++)
{
Output[Index] = byte.Parse(HexString.Substring(Index * 2, 2),
NumberStyles.HexNumber);
Output[Index] = byte.Parse(HexString.Substring(Index * 2, 2), NumberStyles.HexNumber);
}
return Output;

View file

@ -1,11 +0,0 @@
using System.Collections.Generic;
using Ryujinx.HLE.OsHle;
namespace Ryujinx.HLE.Settings
{
public class SystemSettings
{
public Profile User { get; set; }
public ColorSet ThemeColor { get; set; }
}
}

View file

@ -5,7 +5,6 @@ using Ryujinx.HLE.Gpu;
using Ryujinx.HLE.Input;
using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle;
using Ryujinx.HLE.Settings;
using System;
namespace Ryujinx.HLE
@ -22,8 +21,6 @@ namespace Ryujinx.HLE
public Horizon Os { get; private set; }
public SystemSettings Settings { get; private set; }
public PerformanceStatistics Statistics { get; private set; }
public Hid Hid { get; private set; }
@ -54,8 +51,6 @@ namespace Ryujinx.HLE
Os = new Horizon(this);
Settings = new SystemSettings();
Statistics = new PerformanceStatistics();
Hid = new Hid(Log);
@ -67,12 +62,6 @@ namespace Ryujinx.HLE
Os.FontSharedMem.MemoryMapped += Font.ShMemMap;
Os.FontSharedMem.MemoryUnmapped += Font.ShMemUnmap;
Settings.User = new Profile()
{
Username = "Ryujinx",
UserId = "000123456789abcdef09876543210000"
};
}
public void LoadCart(string ExeFsDir, string RomFsFile = null)

View file

@ -1,6 +1,7 @@
using Ryujinx.UI.Input;
using Ryujinx.HLE;
using Ryujinx.HLE.Logging;
using Ryujinx.HLE.Input;
using Ryujinx.UI.Input;
using System;
using System.Globalization;
using System.Collections.Generic;
@ -8,8 +9,6 @@ using System.IO;
using System.Linq;
using System.Reflection;
using static Ryujinx.HLE.OsHle.SystemStateMgr;
namespace Ryujinx
{
public static class Config
@ -18,7 +17,7 @@ namespace Ryujinx
public static JoyConController[] JoyConControllers { get; private set; }
public static bool GamePadEnable { get; private set; }
public static void Read(Logger Log)
public static void Read(Switch Device)
{
string IniFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
@ -30,13 +29,13 @@ namespace Ryujinx
GraphicsConfig.ShadersDumpPath = Parser.Value("Graphics_Shaders_Dump_Path");
Log.SetEnable(LogLevel.Debug, Convert.ToBoolean(Parser.Value("Logging_Enable_Debug")));
Log.SetEnable(LogLevel.Stub, Convert.ToBoolean(Parser.Value("Logging_Enable_Stub")));
Log.SetEnable(LogLevel.Info, Convert.ToBoolean(Parser.Value("Logging_Enable_Info")));
Log.SetEnable(LogLevel.Warning, Convert.ToBoolean(Parser.Value("Logging_Enable_Warn")));
Log.SetEnable(LogLevel.Error, Convert.ToBoolean(Parser.Value("Logging_Enable_Error")));
DockedMode = Convert.ToBoolean(Parser.Value("Docked_Mode"));
Device.Log.SetEnable(LogLevel.Debug, Convert.ToBoolean(Parser.Value("Logging_Enable_Debug")));
Device.Log.SetEnable(LogLevel.Stub, Convert.ToBoolean(Parser.Value("Logging_Enable_Stub")));
Device.Log.SetEnable(LogLevel.Info, Convert.ToBoolean(Parser.Value("Logging_Enable_Info")));
Device.Log.SetEnable(LogLevel.Warning, Convert.ToBoolean(Parser.Value("Logging_Enable_Warn")));
Device.Log.SetEnable(LogLevel.Error, Convert.ToBoolean(Parser.Value("Logging_Enable_Error")));
Device.Os.SystemState.DockedMode = Convert.ToBoolean(Parser.Value("Docked_Mode"));
string[] FilteredLogClasses = Parser.Value("Logging_Filtered_Classes").Split(',', StringSplitOptions.RemoveEmptyEntries);
@ -62,7 +61,7 @@ namespace Ryujinx
{
foreach (LogClass Class in Enum.GetValues(typeof(LogClass)))
{
Log.SetEnable(Class, false);
Device.Log.SetEnable(Class, false);
}
}
@ -74,7 +73,7 @@ namespace Ryujinx
{
if (Class.ToString().ToLower().Contains(LogClass.Trim().ToLower()))
{
Log.SetEnable(Class, true);
Device.Log.SetEnable(Class, true);
}
}
}

View file

@ -20,7 +20,7 @@ namespace Ryujinx
Switch Ns = new Switch(Renderer, AudioOut);
Config.Read(Ns.Log);
Config.Read(Ns);
Ns.Log.Updated += ConsoleLog.PrintLog;