aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/SvcSystem.cs')
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcSystem.cs138
1 files changed, 120 insertions, 18 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
index 60ccf7f7..8bcea550 100644
--- a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
@@ -22,20 +22,73 @@ namespace Ryujinx.HLE.HOS.Kernel
Device.System.ExitProcess(Process.ProcessId);
}
- private void SvcClearEvent(AThreadState ThreadState)
+ private void SignalEvent64(AThreadState ThreadState)
{
- int Handle = (int)ThreadState.X0;
+ ThreadState.X0 = (ulong)SignalEvent((int)ThreadState.X0);
+ }
- //TODO: Implement events.
+ private KernelResult SignalEvent(int Handle)
+ {
+ KWritableEvent WritableEvent = Process.HandleTable.GetObject<KWritableEvent>(Handle);
- ThreadState.X0 = 0;
+ KernelResult Result;
+
+ if (WritableEvent != null)
+ {
+ WritableEvent.Signal();
+
+ Result = KernelResult.Success;
+ }
+ else
+ {
+ Result = KernelResult.InvalidHandle;
+ }
+
+ if (Result != KernelResult.Success)
+ {
+ Device.Log.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
+ }
+
+ return Result;
+ }
+
+ private void ClearEvent64(AThreadState ThreadState)
+ {
+ ThreadState.X0 = (ulong)ClearEvent((int)ThreadState.X0);
+ }
+
+ private KernelResult ClearEvent(int Handle)
+ {
+ KernelResult Result;
+
+ KWritableEvent WritableEvent = Process.HandleTable.GetObject<KWritableEvent>(Handle);
+
+ if (WritableEvent == null)
+ {
+ KReadableEvent ReadableEvent = Process.HandleTable.GetObject<KReadableEvent>(Handle);
+
+ Result = ReadableEvent?.Clear() ?? KernelResult.InvalidHandle;
+ }
+ else
+ {
+ Result = WritableEvent.Clear();
+ }
+
+ if (Result != KernelResult.Success)
+ {
+ Device.Log.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
+ }
+
+ return Result;
}
private void SvcCloseHandle(AThreadState ThreadState)
{
int Handle = (int)ThreadState.X0;
- object Obj = Process.HandleTable.CloseHandle(Handle);
+ object Obj = Process.HandleTable.GetObject<object>(Handle);
+
+ Process.HandleTable.CloseHandle(Handle);
if (Obj == null)
{
@@ -60,24 +113,37 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = 0;
}
- private void SvcResetSignal(AThreadState ThreadState)
+ private void ResetSignal64(AThreadState ThreadState)
{
- int Handle = (int)ThreadState.X0;
+ ThreadState.X0 = (ulong)ResetSignal((int)ThreadState.X0);
+ }
- KEvent Event = Process.HandleTable.GetData<KEvent>(Handle);
+ private KernelResult ResetSignal(int Handle)
+ {
+ KReadableEvent ReadableEvent = Process.HandleTable.GetObject<KReadableEvent>(Handle);
- if (Event != null)
- {
- Event.Reset();
+ KernelResult Result;
- ThreadState.X0 = 0;
+ //TODO: KProcess support.
+ if (ReadableEvent != null)
+ {
+ Result = ReadableEvent.ClearIfSignaled();
}
else
{
- Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid event handle 0x{Handle:x8}!");
+ Result = KernelResult.InvalidHandle;
+ }
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+ if (Result == KernelResult.InvalidState)
+ {
+ Device.Log.PrintDebug(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
+ }
+ else if (Result != KernelResult.Success)
+ {
+ Device.Log.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
}
+
+ return Result;
}
private void SvcGetSystemTick(AThreadState ThreadState)
@@ -96,10 +162,13 @@ namespace Ryujinx.HLE.HOS.Kernel
//actually exists, return error codes otherwise.
KSession Session = new KSession(ServiceFactory.MakeService(System, Name), Name);
- ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session);
+ if (Process.HandleTable.GenerateHandle(Session, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
ThreadState.X0 = 0;
- ThreadState.X1 = Handle;
+ ThreadState.X1 = (uint)Handle;
}
private void SvcSendSyncRequest(AThreadState ThreadState)
@@ -122,7 +191,7 @@ namespace Ryujinx.HLE.HOS.Kernel
byte[] MessageData = Memory.ReadBytes(MessagePtr, Size);
- KSession Session = Process.HandleTable.GetData<KSession>(Handle);
+ KSession Session = Process.HandleTable.GetObject<KSession>(Handle);
if (Session != null)
{
@@ -206,7 +275,8 @@ namespace Ryujinx.HLE.HOS.Kernel
if (InfoType == 18 ||
InfoType == 19 ||
InfoType == 20 ||
- InfoType == 21)
+ InfoType == 21 ||
+ InfoType == 22)
{
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
@@ -287,5 +357,37 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = 0;
}
+
+ private void CreateEvent64(AThreadState State)
+ {
+ KernelResult Result = CreateEvent(out int WEventHandle, out int REventHandle);
+
+ State.X0 = (ulong)Result;
+ State.X1 = (ulong)WEventHandle;
+ State.X2 = (ulong)REventHandle;
+ }
+
+ private KernelResult CreateEvent(out int WEventHandle, out int REventHandle)
+ {
+ KEvent Event = new KEvent(System);
+
+ KernelResult Result = Process.HandleTable.GenerateHandle(Event.WritableEvent, out WEventHandle);
+
+ if (Result == KernelResult.Success)
+ {
+ Result = Process.HandleTable.GenerateHandle(Event.ReadableEvent, out REventHandle);
+
+ if (Result != KernelResult.Success)
+ {
+ Process.HandleTable.CloseHandle(WEventHandle);
+ }
+ }
+ else
+ {
+ REventHandle = 0;
+ }
+
+ return Result;
+ }
}
}