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

View file

@ -158,7 +158,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2) && AOptimizations.UseSse2)
{ {
EmitSseOrSse2CallF(Context, nameof(Sse.CompareEqualScalar)); EmitScalarSseOrSse2CallF(Context, nameof(Sse.CompareEqualScalar));
} }
else else
{ {
@ -171,7 +171,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2) && AOptimizations.UseSse2)
{ {
EmitSseOrSse2CallF(Context, nameof(Sse.CompareEqual)); EmitVectorSseOrSse2CallF(Context, nameof(Sse.CompareEqual));
} }
else else
{ {
@ -184,7 +184,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2) && AOptimizations.UseSse2)
{ {
EmitSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanOrEqualScalar)); EmitScalarSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanOrEqualScalar));
} }
else else
{ {
@ -197,7 +197,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2) && AOptimizations.UseSse2)
{ {
EmitSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanOrEqual)); EmitVectorSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanOrEqual));
} }
else else
{ {
@ -210,7 +210,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2) && AOptimizations.UseSse2)
{ {
EmitSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanScalar)); EmitScalarSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThanScalar));
} }
else else
{ {
@ -223,7 +223,7 @@ namespace ChocolArm64.Instruction
if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse if (Context.CurrOp is AOpCodeSimdReg && AOptimizations.UseSse
&& AOptimizations.UseSse2) && AOptimizations.UseSse2)
{ {
EmitSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThan)); EmitVectorSseOrSse2CallF(Context, nameof(Sse.CompareGreaterThan));
} }
else 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; AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
@ -160,7 +170,18 @@ namespace ChocolArm64.Instruction
Context.EmitStvec(Op.Rd); 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); EmitVectorZeroUpper(Context, Op.Rd);
} }
@ -1238,6 +1259,15 @@ namespace ChocolArm64.Instruction
EmitVectorInsert(Context, Rd, 1, 3, 0); 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) public static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size)
{ {
ThrowIfInvalid(Index, Size); ThrowIfInvalid(Index, Size);

View file

@ -9,6 +9,18 @@ namespace ChocolArm64.Instruction
{ {
static class AVectorHelper 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) public static void EmitCall(AILEmitterCtx Context, string Name64, string Name128)
{ {
bool IsSimd64 = Context.CurrOp.RegisterSize == ARegisterSize.SIMD64; bool IsSimd64 = Context.CurrOp.RegisterSize == ARegisterSize.SIMD64;
@ -448,6 +460,17 @@ namespace ChocolArm64.Instruction
throw new PlatformNotSupportedException(); 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)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector128<sbyte> VectorSingleToSByte(Vector128<float> Vector) 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) private void VertexEndGl(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
{ {
LockCaches(); LockCaches();
@ -623,11 +631,6 @@ namespace Ryujinx.HLE.Gpu.Engines
if (Mode == 0) if (Mode == 0)
{ {
foreach (List<long> Uploaded in UploadedKeys)
{
Uploaded.Clear();
}
//Write mode. //Write mode.
Vmm.WriteInt32(Position, Seq); Vmm.WriteInt32(Position, Seq);
} }
@ -649,6 +652,8 @@ namespace Ryujinx.HLE.Gpu.Engines
} }
WriteRegister(NvGpuEngine3dReg.ConstBufferOffset, Offset); WriteRegister(NvGpuEngine3dReg.ConstBufferOffset, Offset);
UploadedKeys[(int)NvGpuBufferType.ConstBuffer].Clear();
} }
private void CbBind(NvGpuVmm Vmm, NvGpuPBEntry PBEntry) private void CbBind(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)

View file

@ -15,7 +15,7 @@ namespace Ryujinx.HLE.Gpu.Engines
private NvGpu Gpu; private NvGpu Gpu;
private ConcurrentQueue<(NvGpuVmm, NvGpuPBEntry)> BufferQueue; private ConcurrentQueue<(NvGpuVmm, NvGpuPBEntry[])> BufferQueue;
private NvGpuEngine[] SubChannels; private NvGpuEngine[] SubChannels;
@ -56,7 +56,7 @@ namespace Ryujinx.HLE.Gpu.Engines
{ {
this.Gpu = Gpu; this.Gpu = Gpu;
BufferQueue = new ConcurrentQueue<(NvGpuVmm, NvGpuPBEntry)>(); BufferQueue = new ConcurrentQueue<(NvGpuVmm, NvGpuPBEntry[])>();
SubChannels = new NvGpuEngine[8]; SubChannels = new NvGpuEngine[8];
@ -69,10 +69,7 @@ namespace Ryujinx.HLE.Gpu.Engines
public void PushBuffer(NvGpuVmm Vmm, NvGpuPBEntry[] Buffer) public void PushBuffer(NvGpuVmm Vmm, NvGpuPBEntry[] Buffer)
{ {
foreach (NvGpuPBEntry PBEntry in Buffer) BufferQueue.Enqueue((Vmm, Buffer));
{
BufferQueue.Enqueue((Vmm, PBEntry));
}
Event.Set(); Event.Set();
} }
@ -82,16 +79,27 @@ namespace Ryujinx.HLE.Gpu.Engines
while (Step()); while (Step());
} }
private (NvGpuVmm Vmm, NvGpuPBEntry[] Pb) Curr;
private int CurrPbEntryIndex;
public bool Step() 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) 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.Loaders.Npdm;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle.Handles; using Ryujinx.HLE.OsHle.Handles;
using Ryujinx.HLE.OsHle.SystemState;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.IO; using System.IO;

View file

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

View file

@ -11,6 +11,7 @@ using Ryujinx.HLE.OsHle.Exceptions;
using Ryujinx.HLE.OsHle.Handles; using Ryujinx.HLE.OsHle.Handles;
using Ryujinx.HLE.OsHle.Kernel; using Ryujinx.HLE.OsHle.Kernel;
using Ryujinx.HLE.OsHle.Services.Nv; using Ryujinx.HLE.OsHle.Services.Nv;
using Ryujinx.HLE.OsHle.SystemState;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; 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.Logging;
using Ryujinx.HLE.OsHle.Ipc; using Ryujinx.HLE.OsHle.Ipc;
using Ryujinx.HLE.OsHle.SystemState;
using System.Collections.Generic; using System.Collections.Generic;
using static Ryujinx.HLE.OsHle.ErrorCode;
namespace Ryujinx.HLE.OsHle.Services.Acc namespace Ryujinx.HLE.OsHle.Services.Acc
{ {
class IAccountServiceForApplication : IpcService class IAccountServiceForApplication : IpcService
@ -27,49 +31,80 @@ namespace Ryujinx.HLE.OsHle.Services.Acc
public long GetUserCount(ServiceCtx Context) public long GetUserCount(ServiceCtx Context)
{ {
Context.ResponseData.Write(0); Context.ResponseData.Write(Context.Ns.Os.SystemState.GetUserCount());
Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed.");
return 0; return 0;
} }
public long GetUserExistence(ServiceCtx Context) 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; return 0;
} }
public long ListAllUsers(ServiceCtx Context) public long ListAllUsers(ServiceCtx Context)
{ {
Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed."); return WriteUserList(Context, Context.Ns.Os.SystemState.GetAllUsers());
return 0;
} }
public long ListOpenUsers(ServiceCtx Context) 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; return 0;
} }
public long GetLastOpenedUser(ServiceCtx Context) public long GetLastOpenedUser(ServiceCtx Context)
{ {
Context.ResponseData.Write(1L); UserProfile LastOpened = Context.Ns.Os.SystemState.LastOpenUser;
Context.ResponseData.Write(0L);
Context.Ns.Log.PrintStub(LogClass.ServiceAcc, "Stubbed."); LastOpened.Uuid.Write(Context.ResponseData);
return 0; return 0;
} }
public long GetProfile(ServiceCtx Context) 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; return 0;
} }

View file

@ -1,6 +1,7 @@
using ChocolArm64.Memory; using ChocolArm64.Memory;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle.Ipc; using Ryujinx.HLE.OsHle.Ipc;
using Ryujinx.HLE.OsHle.SystemState;
using Ryujinx.HLE.OsHle.Utilities; using Ryujinx.HLE.OsHle.Utilities;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
@ -13,13 +14,17 @@ namespace Ryujinx.HLE.OsHle.Services.Acc
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands; public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IProfile() private UserProfile Profile;
public IProfile(UserProfile Profile)
{ {
m_Commands = new Dictionary<int, ServiceProcessRequest>() m_Commands = new Dictionary<int, ServiceProcessRequest>()
{ {
{ 0, Get }, { 0, Get },
{ 1, GetBase } { 1, GetBase }
}; };
this.Profile = Profile;
} }
public long Get(ServiceCtx Context) public long Get(ServiceCtx Context)
@ -32,20 +37,18 @@ namespace Ryujinx.HLE.OsHle.Services.Acc
Context.Memory.WriteInt32(Position, 0); Context.Memory.WriteInt32(Position, 0);
Context.Memory.WriteInt32(Position + 4, 1); Context.Memory.WriteInt32(Position + 4, 1);
Context.Memory.WriteByte(Position + 8, 1); Context.Memory.WriteInt64(Position + 8, 1);
return GetBase(Context); return GetBase(Context);
} }
public long GetBase(ServiceCtx 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(Profile.LastModifiedTimestamp);
Context.ResponseData.Write(ProfileBase.Timestamp);
int ByteCount = Encoding.UTF8.GetByteCount(ProfileBase.Username); byte[] Username = StringUtils.GetFixedLengthBytes(Profile.Name, 0x20, Encoding.UTF8);
byte[] Username = StringUtils.GetFixedLengthBytes(ProfileBase.Username, 0x20, Encoding.UTF8);
Context.ResponseData.Write(Username); 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 Ryujinx.HLE.OsHle.Ipc;
using System.Collections.Generic; using System.Collections.Generic;
using static Ryujinx.HLE.OsHle.SystemStateMgr;
using static Ryujinx.HLE.OsHle.ErrorCode; using static Ryujinx.HLE.OsHle.ErrorCode;
namespace Ryujinx.HLE.OsHle.Services.Am namespace Ryujinx.HLE.OsHle.Services.Am
@ -58,7 +57,9 @@ namespace Ryujinx.HLE.OsHle.Services.Am
public long GetOperationMode(ServiceCtx Context) 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); Context.ResponseData.Write((byte)Mode);
@ -67,7 +68,9 @@ namespace Ryujinx.HLE.OsHle.Services.Am
public long GetPerformanceMode(ServiceCtx Context) 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); Context.ResponseData.Write((int)Mode);

View file

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

View file

@ -1,4 +1,6 @@
using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle.Ipc; using Ryujinx.HLE.OsHle.Ipc;
using Ryujinx.HLE.OsHle.SystemState;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.OsHle.Services.Friend namespace Ryujinx.HLE.OsHle.Services.Friend
@ -13,8 +15,35 @@ namespace Ryujinx.HLE.OsHle.Services.Friend
{ {
m_Commands = new Dictionary<int, ServiceProcessRequest>() 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.Ipc;
using Ryujinx.HLE.OsHle.SystemState;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.OsHle.Services.Set namespace Ryujinx.HLE.OsHle.Services.Set

View file

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

View file

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

View file

@ -1,4 +1,4 @@
namespace Ryujinx.HLE.Settings namespace Ryujinx.HLE.OsHle.SystemState
{ {
public enum ColorSet 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 public enum SystemLanguage
{ {

View file

@ -1,7 +1,9 @@
using Ryujinx.HLE.Loaders.Npdm;
using System; 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 public class SystemStateMgr
{ {
@ -36,14 +38,27 @@ namespace Ryujinx.HLE.OsHle
internal long DesiredLanguageCode { get; private set; } internal long DesiredLanguageCode { get; private set; }
internal string ActiveAudioOutput { 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() public SystemStateMgr()
{ {
SetLanguage(SystemLanguage.AmericanEnglish); SetLanguage(SystemLanguage.AmericanEnglish);
SetAudioOutputAsBuiltInSpeaker(); SetAudioOutputAsBuiltInSpeaker();
Profiles = new ConcurrentDictionary<string, UserProfile>();
UserId DefaultUuid = new UserId("00000000000000000000000000000001");
AddUser(DefaultUuid, "Player");
OpenUser(DefaultUuid);
} }
public void SetLanguage(SystemLanguage Language) public void SetLanguage(SystemLanguage Language)
@ -66,6 +81,49 @@ namespace Ryujinx.HLE.OsHle
ActiveAudioOutput = AudioOutputs[2]; 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) internal static long GetLanguageCode(int Index)
{ {
if ((uint)Index >= LanguageCodes.Length) 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"; InputString = InputString + "\0";
int ByteCount = Encoding.GetByteCount(InputString); int BytesCount = Encoding.GetByteCount(InputString);
byte[] Output = new byte[Size]; 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 else
{ {
@ -35,15 +35,14 @@ namespace Ryujinx.HLE.OsHle.Utilities
public static byte[] HexToBytes(string HexString) 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; int BytesInHex = HexString.Length / 2;
byte[] Output = new byte[BytesInHex]; byte[] Output = new byte[BytesInHex];
for (int Index = 0; Index < BytesInHex; Index++) for (int Index = 0; Index < BytesInHex; Index++)
{ {
Output[Index] = byte.Parse(HexString.Substring(Index * 2, 2), Output[Index] = byte.Parse(HexString.Substring(Index * 2, 2), NumberStyles.HexNumber);
NumberStyles.HexNumber);
} }
return Output; 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.Input;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using Ryujinx.HLE.OsHle; using Ryujinx.HLE.OsHle;
using Ryujinx.HLE.Settings;
using System; using System;
namespace Ryujinx.HLE namespace Ryujinx.HLE
@ -22,8 +21,6 @@ namespace Ryujinx.HLE
public Horizon Os { get; private set; } public Horizon Os { get; private set; }
public SystemSettings Settings { get; private set; }
public PerformanceStatistics Statistics { get; private set; } public PerformanceStatistics Statistics { get; private set; }
public Hid Hid { get; private set; } public Hid Hid { get; private set; }
@ -54,8 +51,6 @@ namespace Ryujinx.HLE
Os = new Horizon(this); Os = new Horizon(this);
Settings = new SystemSettings();
Statistics = new PerformanceStatistics(); Statistics = new PerformanceStatistics();
Hid = new Hid(Log); Hid = new Hid(Log);
@ -67,12 +62,6 @@ namespace Ryujinx.HLE
Os.FontSharedMem.MemoryMapped += Font.ShMemMap; Os.FontSharedMem.MemoryMapped += Font.ShMemMap;
Os.FontSharedMem.MemoryUnmapped += Font.ShMemUnmap; Os.FontSharedMem.MemoryUnmapped += Font.ShMemUnmap;
Settings.User = new Profile()
{
Username = "Ryujinx",
UserId = "000123456789abcdef09876543210000"
};
} }
public void LoadCart(string ExeFsDir, string RomFsFile = null) 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.Logging;
using Ryujinx.HLE.Input; using Ryujinx.HLE.Input;
using Ryujinx.UI.Input;
using System; using System;
using System.Globalization; using System.Globalization;
using System.Collections.Generic; using System.Collections.Generic;
@ -8,8 +9,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using static Ryujinx.HLE.OsHle.SystemStateMgr;
namespace Ryujinx namespace Ryujinx
{ {
public static class Config public static class Config
@ -18,7 +17,7 @@ namespace Ryujinx
public static JoyConController[] JoyConControllers { get; private set; } public static JoyConController[] JoyConControllers { get; private set; }
public static bool GamePadEnable { 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); string IniFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
@ -30,13 +29,13 @@ namespace Ryujinx
GraphicsConfig.ShadersDumpPath = Parser.Value("Graphics_Shaders_Dump_Path"); GraphicsConfig.ShadersDumpPath = Parser.Value("Graphics_Shaders_Dump_Path");
Log.SetEnable(LogLevel.Debug, Convert.ToBoolean(Parser.Value("Logging_Enable_Debug"))); Device.Log.SetEnable(LogLevel.Debug, Convert.ToBoolean(Parser.Value("Logging_Enable_Debug")));
Log.SetEnable(LogLevel.Stub, Convert.ToBoolean(Parser.Value("Logging_Enable_Stub"))); Device.Log.SetEnable(LogLevel.Stub, Convert.ToBoolean(Parser.Value("Logging_Enable_Stub")));
Log.SetEnable(LogLevel.Info, Convert.ToBoolean(Parser.Value("Logging_Enable_Info"))); Device.Log.SetEnable(LogLevel.Info, Convert.ToBoolean(Parser.Value("Logging_Enable_Info")));
Log.SetEnable(LogLevel.Warning, Convert.ToBoolean(Parser.Value("Logging_Enable_Warn"))); Device.Log.SetEnable(LogLevel.Warning, Convert.ToBoolean(Parser.Value("Logging_Enable_Warn")));
Log.SetEnable(LogLevel.Error, Convert.ToBoolean(Parser.Value("Logging_Enable_Error"))); Device.Log.SetEnable(LogLevel.Error, Convert.ToBoolean(Parser.Value("Logging_Enable_Error")));
DockedMode = Convert.ToBoolean(Parser.Value("Docked_Mode")); Device.Os.SystemState.DockedMode = Convert.ToBoolean(Parser.Value("Docked_Mode"));
string[] FilteredLogClasses = Parser.Value("Logging_Filtered_Classes").Split(',', StringSplitOptions.RemoveEmptyEntries); string[] FilteredLogClasses = Parser.Value("Logging_Filtered_Classes").Split(',', StringSplitOptions.RemoveEmptyEntries);
@ -62,7 +61,7 @@ namespace Ryujinx
{ {
foreach (LogClass Class in Enum.GetValues(typeof(LogClass))) 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())) 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); Switch Ns = new Switch(Renderer, AudioOut);
Config.Read(Ns.Log); Config.Read(Ns);
Ns.Log.Updated += ConsoleLog.PrintLog; Ns.Log.Updated += ConsoleLog.PrintLog;