aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-03-19 15:58:46 -0300
committerGitHub <noreply@github.com>2018-03-19 15:58:46 -0300
commit4314a8f3e5b76bbf2143f701c06e9354de712027 (patch)
treeacded3e24125e54bc791f322f0be869f1d379c19
parent4940cf0ea58c77c8666d76abdfc35c6380efed4c (diff)
[WIP] Add support for events (#60)
* Add support for events, move concept of domains to IpcService * Support waiting for KThread, remove some test code, other tweaks * Use move handle on NIFM since I can't test that now, it's better to leave it how it was
-rw-r--r--Ryujinx.Audio/IAalOutput.cs6
-rw-r--r--Ryujinx.Audio/OpenAL/OpenALAudioOut.cs75
-rw-r--r--Ryujinx.Audio/ReleaseCallback.cs4
-rw-r--r--Ryujinx.Core/OsHle/AppletStateMgr.cs62
-rw-r--r--Ryujinx.Core/OsHle/CondVar.cs8
-rw-r--r--Ryujinx.Core/OsHle/FileDesc.cs12
-rw-r--r--Ryujinx.Core/OsHle/GlobalStateTable.cs62
-rw-r--r--Ryujinx.Core/OsHle/Handles/HDomain.cs48
-rw-r--r--Ryujinx.Core/OsHle/Handles/HEvent.cs7
-rw-r--r--Ryujinx.Core/OsHle/Handles/HSession.cs29
-rw-r--r--Ryujinx.Core/OsHle/Handles/HSessionObj.cs30
-rw-r--r--Ryujinx.Core/OsHle/Handles/KEvent.cs4
-rw-r--r--Ryujinx.Core/OsHle/Handles/KProcessHandleTable.cs39
-rw-r--r--Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs26
-rw-r--r--Ryujinx.Core/OsHle/Handles/KSession.cs28
-rw-r--r--Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs28
-rw-r--r--Ryujinx.Core/OsHle/Handles/KThread.cs (renamed from Ryujinx.Core/OsHle/Handles/HThread.cs)4
-rw-r--r--Ryujinx.Core/OsHle/Horizon.cs19
-rw-r--r--Ryujinx.Core/OsHle/IdDictionary.cs37
-rw-r--r--Ryujinx.Core/OsHle/Ipc/IpcDomCmd.cs8
-rw-r--r--Ryujinx.Core/OsHle/Ipc/IpcHandler.cs117
-rw-r--r--Ryujinx.Core/OsHle/Ipc/IpcLog.cs3
-rw-r--r--Ryujinx.Core/OsHle/Ipc/IpcMagic.cs8
-rw-r--r--Ryujinx.Core/OsHle/Ipc/IpcMessage.cs48
-rw-r--r--Ryujinx.Core/OsHle/KernelErr.cs1
-rw-r--r--Ryujinx.Core/OsHle/Mutex.cs10
-rw-r--r--Ryujinx.Core/OsHle/Process.cs47
-rw-r--r--Ryujinx.Core/OsHle/ServiceCtx.cs4
-rw-r--r--Ryujinx.Core/OsHle/ServiceMgr.cs128
-rw-r--r--Ryujinx.Core/OsHle/Services/Acc/IManagerForApplication.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Acc/IProfile.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Acc/ServiceAcc.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/AmErr.cs7
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/FocusState.cs8
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/IApplicationProxy.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/IAudioController.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/ICommonStateGetter.cs39
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/IDebugFunctions.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/IDisplayController.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/ILibraryAppletCreator.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/ISelfController.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/IStorage.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/IWindowController.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/MessageInfo.cs9
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/OperationMode.cs8
-rw-r--r--Ryujinx.Core/OsHle/Services/Am/ServiceAppletOE.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Apm/ISession.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Apm/ServiceApm.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs17
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs27
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs18
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Friend/IFriendService.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Friend/ServiceFriend.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/FspSrv/IDirectory.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs5
-rw-r--r--Ryujinx.Core/OsHle/Services/FspSrv/IStorage.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/FspSrv/ServiceFspSrv.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/IpcService.cs151
-rw-r--r--Ryujinx.Core/OsHle/Services/Lm/ILogger.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs8
-rw-r--r--Ryujinx.Core/OsHle/Services/Nifm/IGeneralService.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Nifm/IRequest.cs29
-rw-r--r--Ryujinx.Core/OsHle/Services/Nifm/ServiceNifm.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs63
-rw-r--r--Ryujinx.Core/OsHle/Services/ObjHelper.cs24
-rw-r--r--Ryujinx.Core/OsHle/Services/Pctl/IParentalControlService.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Pctl/ServicePctl.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceFactory.cs119
-rw-r--r--Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Sfdnsres/ServiceSfdnsres.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs12
-rw-r--r--Ryujinx.Core/OsHle/Services/Ssl/ServiceSsl.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Time/ISteadyClock.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Time/ISystemClock.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Time/ServiceTime.cs6
-rw-r--r--Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs8
-rw-r--r--Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs17
-rw-r--r--Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Vi/ISystemDisplayService.cs4
-rw-r--r--Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs22
-rw-r--r--Ryujinx.Core/OsHle/Services/Vi/ServiceVi.cs6
-rw-r--r--Ryujinx.Core/OsHle/Svc/SvcSystem.cs151
-rw-r--r--Ryujinx.Core/OsHle/Svc/SvcThread.cs18
-rw-r--r--Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs6
-rw-r--r--Ryujinx.Core/Switch.cs10
-rw-r--r--Ryujinx.Graphics/Gpu/NsGpuPGraph.cs59
-rw-r--r--Ryujinx.Graphics/Gpu/NsGpuRegister.cs1
-rw-r--r--Ryujinx/Ui/GLScreen.cs2
101 files changed, 1119 insertions, 835 deletions
diff --git a/Ryujinx.Audio/IAalOutput.cs b/Ryujinx.Audio/IAalOutput.cs
index 5ffeebdd..f9978ee4 100644
--- a/Ryujinx.Audio/IAalOutput.cs
+++ b/Ryujinx.Audio/IAalOutput.cs
@@ -2,7 +2,11 @@ namespace Ryujinx.Audio
{
public interface IAalOutput
{
- int OpenTrack(int SampleRate, int Channels, out AudioFormat Format);
+ int OpenTrack(
+ int SampleRate,
+ int Channels,
+ ReleaseCallback Callback,
+ out AudioFormat Format);
void CloseTrack(int Track);
diff --git a/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs b/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs
index 48dcd199..f574b46f 100644
--- a/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs
+++ b/Ryujinx.Audio/OpenAL/OpenALAudioOut.cs
@@ -3,6 +3,7 @@ using OpenTK.Audio.OpenAL;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Threading;
namespace Ryujinx.Audio.OpenAL
{
@@ -22,20 +23,27 @@ namespace Ryujinx.Audio.OpenAL
public ALFormat Format { get; private set; }
+ private ReleaseCallback Callback;
+
public PlaybackState State { get; set; }
+ private bool ShouldCallReleaseCallback;
+
private ConcurrentDictionary<long, int> Buffers;
private Queue<long> QueuedTagsQueue;
private Queue<long> ReleasedTagsQueue;
+ private int LastReleasedCount;
+
private bool Disposed;
- public Track(int SampleRate, ALFormat Format)
+ public Track(int SampleRate, ALFormat Format, ReleaseCallback Callback)
{
this.SampleRate = SampleRate;
this.Format = Format;
+ this.Callback = Callback;
State = PlaybackState.Stopped;
@@ -109,11 +117,42 @@ namespace Ryujinx.Audio.OpenAL
AL.GetSource(SourceId, ALGetSourcei.BuffersProcessed, out int ReleasedCount);
+ CheckReleaseChanges(ReleasedCount);
+
if (ReleasedCount > 0)
{
AL.SourceUnqueueBuffers(SourceId, ReleasedCount);
}
}
+
+ public void CallReleaseCallbackIfNeeded()
+ {
+ CheckReleaseChanges();
+
+ if (ShouldCallReleaseCallback)
+ {
+ ShouldCallReleaseCallback = false;
+
+ Callback();
+ }
+ }
+
+ private void CheckReleaseChanges()
+ {
+ AL.GetSource(SourceId, ALGetSourcei.BuffersProcessed, out int ReleasedCount);
+
+ CheckReleaseChanges(ReleasedCount);
+ }
+
+ private void CheckReleaseChanges(int NewReleasedCount)
+ {
+ if (LastReleasedCount != NewReleasedCount)
+ {
+ LastReleasedCount = NewReleasedCount;
+
+ ShouldCallReleaseCallback = true;
+ }
+ }
private void SyncQueuedTags()
{
@@ -156,18 +195,46 @@ namespace Ryujinx.Audio.OpenAL
private ConcurrentDictionary<int, Track> Tracks;
+ private Thread AudioPollerThread;
+
+ private bool KeepPolling;
+
public OpenALAudioOut()
{
Context = new AudioContext();
Tracks = new ConcurrentDictionary<int, Track>();
+
+ KeepPolling = true;
+
+ AudioPollerThread = new Thread(AudioPollerWork);
+
+ AudioPollerThread.Start();
+ }
+
+ private void AudioPollerWork()
+ {
+ do
+ {
+ foreach (Track Td in Tracks.Values)
+ {
+ Td.CallReleaseCallbackIfNeeded();
+ }
+
+ Thread.Yield();
+ }
+ while (KeepPolling);
}
- public int OpenTrack(int SampleRate, int Channels, out AudioFormat Format)
+ public int OpenTrack(
+ int SampleRate,
+ int Channels,
+ ReleaseCallback Callback,
+ out AudioFormat Format)
{
Format = AudioFormat.PcmInt16;
- Track Td = new Track(SampleRate, GetALFormat(Channels, Format));
+ Track Td = new Track(SampleRate, GetALFormat(Channels, Format), Callback);
for (int Id = 0; Id < MaxTracks; Id++)
{
@@ -292,5 +359,7 @@ namespace Ryujinx.Audio.OpenAL
return PlaybackState.Stopped;
}
+
+
}
} \ No newline at end of file
diff --git a/Ryujinx.Audio/ReleaseCallback.cs b/Ryujinx.Audio/ReleaseCallback.cs
new file mode 100644
index 00000000..f534e02c
--- /dev/null
+++ b/Ryujinx.Audio/ReleaseCallback.cs
@@ -0,0 +1,4 @@
+namespace Ryujinx.Audio
+{
+ public delegate void ReleaseCallback();
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/AppletStateMgr.cs b/Ryujinx.Core/OsHle/AppletStateMgr.cs
new file mode 100644
index 00000000..cd168b77
--- /dev/null
+++ b/Ryujinx.Core/OsHle/AppletStateMgr.cs
@@ -0,0 +1,62 @@
+using Ryujinx.Core.OsHle.IpcServices.Am;
+using Ryujinx.Core.OsHle.Handles;
+using System;
+using System.Collections.Concurrent;
+
+namespace Ryujinx.Core.OsHle
+{
+ class AppletStateMgr : IDisposable
+ {
+ private ConcurrentQueue<MessageInfo> Messages;
+
+ public FocusState FocusState { get; private set; }
+
+ public KEvent MessageEvent { get; private set; }
+
+ public AppletStateMgr()
+ {
+ Messages = new ConcurrentQueue<MessageInfo>();
+
+ MessageEvent = new KEvent();
+ }
+
+ public void SetFocus(bool IsFocused)
+ {
+ FocusState = IsFocused
+ ? FocusState.InFocus
+ : FocusState.OutOfFocus;
+
+ EnqueueMessage(MessageInfo.FocusStateChanged);
+ }
+
+ public void EnqueueMessage(MessageInfo Message)
+ {
+ Messages.Enqueue(Message);
+
+ MessageEvent.Handle.Set();
+ }
+
+ public bool TryDequeueMessage(out MessageInfo Message)
+ {
+ if (Messages.Count < 2)
+ {
+ MessageEvent.Handle.Reset();
+ }
+
+ return Messages.TryDequeue(out Message);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool Disposing)
+ {
+ if (Disposing)
+ {
+ MessageEvent.Dispose();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/CondVar.cs b/Ryujinx.Core/OsHle/CondVar.cs
index f5fe3d29..f1b846d0 100644
--- a/Ryujinx.Core/OsHle/CondVar.cs
+++ b/Ryujinx.Core/OsHle/CondVar.cs
@@ -13,7 +13,7 @@ namespace Ryujinx.Core.OsHle
private bool OwnsCondVarValue;
- private List<HThread> WaitingThreads;
+ private List<KThread> WaitingThreads;
public CondVar(Process Process, long CondVarAddress, long Timeout)
{
@@ -21,10 +21,10 @@ namespace Ryujinx.Core.OsHle
this.CondVarAddress = CondVarAddress;
this.Timeout = Timeout;
- WaitingThreads = new List<HThread>();
+ WaitingThreads = new List<KThread>();
}
- public bool WaitForSignal(HThread Thread)
+ public bool WaitForSignal(KThread Thread)
{
int Count = Process.Memory.ReadInt32(CondVarAddress);
@@ -66,7 +66,7 @@ namespace Ryujinx.Core.OsHle
return true;
}
- public void SetSignal(HThread Thread, int Count)
+ public void SetSignal(KThread Thread, int Count)
{
lock (WaitingThreads)
{
diff --git a/Ryujinx.Core/OsHle/FileDesc.cs b/Ryujinx.Core/OsHle/FileDesc.cs
deleted file mode 100644
index 4be83bb0..00000000
--- a/Ryujinx.Core/OsHle/FileDesc.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Ryujinx.Core.OsHle
-{
- class FileDesc
- {
- public string Name { get; private set; }
-
- public FileDesc(string Name)
- {
- this.Name = Name;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/GlobalStateTable.cs b/Ryujinx.Core/OsHle/GlobalStateTable.cs
new file mode 100644
index 00000000..ffc9f262
--- /dev/null
+++ b/Ryujinx.Core/OsHle/GlobalStateTable.cs
@@ -0,0 +1,62 @@
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+
+namespace Ryujinx.Core.OsHle
+{
+ class GlobalStateTable
+ {
+ private ConcurrentDictionary<Process, IdDictionary> DictByProcess;
+
+ public GlobalStateTable()
+ {
+ DictByProcess = new ConcurrentDictionary<Process, IdDictionary>();
+ }
+
+ public int Add(Process Process, object Obj)
+ {
+ IdDictionary Dict = DictByProcess.GetOrAdd(Process, (Key) => new IdDictionary());
+
+ return Dict.Add(Obj);
+ }
+
+ public object GetData(Process Process, int Id)
+ {
+ if (DictByProcess.TryGetValue(Process, out IdDictionary Dict))
+ {
+ return Dict.GetData(Id);
+ }
+
+ return null;
+ }
+
+ public T GetData<T>(Process Process, int Id)
+ {
+ if (DictByProcess.TryGetValue(Process, out IdDictionary Dict))
+ {
+ return Dict.GetData<T>(Id);
+ }
+
+ return default(T);
+ }
+
+ public object Delete(Process Process, int Id)
+ {
+ if (DictByProcess.TryGetValue(Process, out IdDictionary Dict))
+ {
+ return Dict.Delete(Id);
+ }
+
+ return null;
+ }
+
+ public ICollection<object> DeleteProcess(Process Process)
+ {
+ if (DictByProcess.TryRemove(Process, out IdDictionary Dict))
+ {
+ return Dict.Clear();
+ }
+
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/HDomain.cs b/Ryujinx.Core/OsHle/Handles/HDomain.cs
deleted file mode 100644
index 26c60455..00000000
--- a/Ryujinx.Core/OsHle/Handles/HDomain.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System;
-
-namespace Ryujinx.Core.OsHle.Handles
-{
- class HDomain : HSession, IDisposable
- {
- private IdDictionary Objects;
-
- public HDomain(HSession Session) : base(Session)
- {
- Objects = new IdDictionary();
- }
-
- public int Add(object Obj)
- {
- return Objects.Add(Obj);
- }
-
- public bool Delete(int Id)
- {
- return Objects.Delete(Id);
- }
-
- public object GetObject(int Id)
- {
- return Objects.GetData(Id);
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool Disposing)
- {
- if (Disposing)
- {
- foreach (object Obj in Objects)
- {
- if (Obj != this && Obj is IDisposable DisposableObj)
- {
- DisposableObj.Dispose();
- }
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/HEvent.cs b/Ryujinx.Core/OsHle/Handles/HEvent.cs
deleted file mode 100644
index 4e881ca2..00000000
--- a/Ryujinx.Core/OsHle/Handles/HEvent.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Ryujinx.Core.OsHle.Handles
-{
- class HEvent
- {
-
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/HSession.cs b/Ryujinx.Core/OsHle/Handles/HSession.cs
deleted file mode 100644
index f30e91f9..00000000
--- a/Ryujinx.Core/OsHle/Handles/HSession.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using Ryujinx.Core.OsHle.IpcServices;
-
-namespace Ryujinx.Core.OsHle.Handles
-{
- class HSession
- {
- public IIpcService Service { get; private set; }
-
- public bool IsInitialized { get; private set; }
-
- public int State { get; set; }
-
- public HSession(IIpcService Service)
- {
- this.Service = Service;
- }
-
- public HSession(HSession Session)
- {
- Service = Session.Service;
- IsInitialized = Session.IsInitialized;
- }
-
- public void Initialize()
- {
- IsInitialized = true;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/HSessionObj.cs b/Ryujinx.Core/OsHle/Handles/HSessionObj.cs
deleted file mode 100644
index ed0530f7..00000000
--- a/Ryujinx.Core/OsHle/Handles/HSessionObj.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System;
-
-namespace Ryujinx.Core.OsHle.Handles
-{
- class HSessionObj : HSession, IDisposable
- {
- public object Obj { get; private set; }
-
- public HSessionObj(HSession Session, object Obj) : base(Session)
- {
- this.Obj = Obj;
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool Disposing)
- {
- if (Disposing && Obj != null)
- {
- if (Obj is IDisposable DisposableObj)
- {
- DisposableObj.Dispose();
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/KEvent.cs b/Ryujinx.Core/OsHle/Handles/KEvent.cs
new file mode 100644
index 00000000..96ff01f7
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Handles/KEvent.cs
@@ -0,0 +1,4 @@
+namespace Ryujinx.Core.OsHle.Handles
+{
+ class KEvent : KSynchronizationObject { }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/KProcessHandleTable.cs b/Ryujinx.Core/OsHle/Handles/KProcessHandleTable.cs
index 1156e035..2c809883 100644
--- a/Ryujinx.Core/OsHle/Handles/KProcessHandleTable.cs
+++ b/Ryujinx.Core/OsHle/Handles/KProcessHandleTable.cs
@@ -1,8 +1,8 @@
-using System;
+using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.Handles
{
- class KProcessHandleTable : IDisposable
+ class KProcessHandleTable
{
private IdDictionary Handles;
@@ -21,43 +21,14 @@ namespace Ryujinx.Core.OsHle.Handles
return Handles.GetData<T>(Handle);
}
- public bool ReplaceData(int Id, object Data)
+ public object CloseHandle(int Handle)
{
- return Handles.ReplaceData(Id, Data);
- }
-
- public bool CloseHandle(int Handle)
- {
- object Data = Handles.GetData(Handle);
-
- if (Data is HTransferMem TMem)
- {
- TMem.Memory.Manager.Reprotect(
- TMem.Position,
- TMem.Size,
- TMem.Perm);
- }
-
return Handles.Delete(Handle);
}
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool Disposing)
+ public ICollection<object> Clear()
{
- if (Disposing)
- {
- foreach (object Obj in Handles)
- {
- if (Obj is IDisposable DisposableObj)
- {
- DisposableObj.Dispose();
- }
- }
- }
+ return Handles.Clear();
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
index b1116078..95754298 100644
--- a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
+++ b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
@@ -5,15 +5,15 @@ using System.Threading;
namespace Ryujinx.Core.OsHle.Handles
{
- public class KProcessScheduler : IDisposable
+ class KProcessScheduler : IDisposable
{
private class SchedulerThread : IDisposable
{
- public HThread Thread { get; private set; }
+ public KThread Thread { get; private set; }
public AutoResetEvent WaitEvent { get; private set; }
- public SchedulerThread(HThread Thread)
+ public SchedulerThread(KThread Thread)
{
this.Thread = Thread;
@@ -95,7 +95,7 @@ namespace Ryujinx.Core.OsHle.Handles
}
}
- private ConcurrentDictionary<HThread, SchedulerThread> AllThreads;
+ private ConcurrentDictionary<KThread, SchedulerThread> AllThreads;
private ThreadQueue[] WaitingToRun;
@@ -105,7 +105,7 @@ namespace Ryujinx.Core.OsHle.Handles
public KProcessScheduler()
{
- AllThreads = new ConcurrentDictionary<HThread, SchedulerThread>();
+ AllThreads = new ConcurrentDictionary<KThread, SchedulerThread>();
WaitingToRun = new ThreadQueue[4];
@@ -119,7 +119,7 @@ namespace Ryujinx.Core.OsHle.Handles
SchedLock = new object();
}
- public void StartThread(HThread Thread)
+ public void StartThread(KThread Thread)
{
lock (SchedLock)
{
@@ -164,7 +164,7 @@ namespace Ryujinx.Core.OsHle.Handles
}
}
- public void Resume(HThread CurrThread)
+ public void Resume(KThread CurrThread)
{
SchedulerThread SchedThread;
@@ -183,7 +183,7 @@ namespace Ryujinx.Core.OsHle.Handles
TryResumingExecution(SchedThread);
}
- public bool WaitForSignal(HThread Thread, int Timeout = -1)
+ public bool WaitForSignal(KThread Thread, int Timeout = -1)
{
SchedulerThread SchedThread;
@@ -230,7 +230,7 @@ namespace Ryujinx.Core.OsHle.Handles
private void TryResumingExecution(SchedulerThread SchedThread)
{
- HThread Thread = SchedThread.Thread;
+ KThread Thread = SchedThread.Thread;
lock (SchedLock)
{
@@ -249,7 +249,7 @@ namespace Ryujinx.Core.OsHle.Handles
Logging.Debug($"{GetDbgThreadInfo(Thread)} resuming execution...");
}
- public void Yield(HThread Thread)
+ public void Yield(KThread Thread)
{
SchedulerThread SchedThread;
@@ -295,11 +295,11 @@ namespace Ryujinx.Core.OsHle.Handles
}
}
- public void Signal(params HThread[] Threads)
+ public void Signal(params KThread[] Threads)
{
lock (SchedLock)
{
- foreach (HThread Thread in Threads)
+ foreach (KThread Thread in Threads)
{
if (AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
{
@@ -314,7 +314,7 @@ namespace Ryujinx.Core.OsHle.Handles
}
}
- private string GetDbgThreadInfo(HThread Thread)
+ private string GetDbgThreadInfo(KThread Thread)
{
return $"Thread {Thread.ThreadId} (core {Thread.ProcessorId}) prio {Thread.Priority}";
}
diff --git a/Ryujinx.Core/OsHle/Handles/KSession.cs b/Ryujinx.Core/OsHle/Handles/KSession.cs
new file mode 100644
index 00000000..6934e522
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Handles/KSession.cs
@@ -0,0 +1,28 @@
+using Ryujinx.Core.OsHle.IpcServices;
+using System;
+
+namespace Ryujinx.Core.OsHle.Handles
+{
+ class KSession : IDisposable
+ {
+ public IpcService Service { get; private set; }
+
+ public KSession(IpcService Service)
+ {
+ this.Service = Service;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool Disposing)
+ {
+ if (Disposing && Service is IDisposable DisposableService)
+ {
+ DisposableService.Dispose();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs b/Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs
new file mode 100644
index 00000000..015b814a
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Threading;
+
+namespace Ryujinx.Core.OsHle.Handles
+{
+ class KSynchronizationObject : IDisposable
+ {
+ public ManualResetEvent Handle { get; private set; }
+
+ public KSynchronizationObject()
+ {
+ Handle = new ManualResetEvent(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool Disposing)
+ {
+ if (Disposing)
+ {
+ Handle.Dispose();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Handles/HThread.cs b/Ryujinx.Core/OsHle/Handles/KThread.cs
index c631cedc..aa1b27be 100644
--- a/Ryujinx.Core/OsHle/Handles/HThread.cs
+++ b/Ryujinx.Core/OsHle/Handles/KThread.cs
@@ -2,7 +2,7 @@ using ChocolArm64;
namespace Ryujinx.Core.OsHle.Handles
{
- public class HThread
+ class KThread : KSynchronizationObject
{
public AThread Thread { get; private set; }
@@ -11,7 +11,7 @@ namespace Ryujinx.Core.OsHle.Handles
public int ThreadId => Thread.ThreadId;
- public HThread(AThread Thread, int ProcessorId, int Priority)
+ public KThread(AThread Thread, int ProcessorId, int Priority)
{
this.Thread = Thread;
this.ProcessorId = ProcessorId;
diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs
index c3f8cd8b..240c08db 100644
--- a/Ryujinx.Core/OsHle/Horizon.cs
+++ b/Ryujinx.Core/OsHle/Horizon.cs
@@ -16,8 +16,10 @@ namespace Ryujinx.Core.OsHle
private ConcurrentDictionary<int, Process> Processes;
- internal HSharedMem HidSharedMem;
- internal HSharedMem FontSharedMem;
+ internal HSharedMem HidSharedMem { get; private set; }
+ internal HSharedMem FontSharedMem { get; private set; }
+
+ internal KEvent VsyncEvent { get; private set; }
private Switch Ns;
@@ -32,6 +34,8 @@ namespace Ryujinx.Core.OsHle
HidSharedMem = new HSharedMem();
FontSharedMem = new HSharedMem();
+
+ VsyncEvent = new KEvent();
}
public void LoadCart(string ExeFsDir, string RomFsFile = null)
@@ -91,6 +95,8 @@ namespace Ryujinx.Core.OsHle
MainProcess.Run(IsNro);
}
+ public void SignalVsync() => VsyncEvent.Handle.Set();
+
private Process MakeProcess()
{
Process Process;
@@ -109,9 +115,16 @@ namespace Ryujinx.Core.OsHle
Processes.TryAdd(ProcessId, Process);
}
+ InitializeProcess(Process);
+
return Process;
}
+ private void InitializeProcess(Process Process)
+ {
+ Process.AppletState.SetFocus(true);
+ }
+
internal void ExitProcess(int ProcessId)
{
if (Processes.TryGetValue(ProcessId, out Process Process) && Process.NeedsHbAbi)
@@ -171,6 +184,8 @@ namespace Ryujinx.Core.OsHle
Process.StopAllThreadsAsync();
Process.Dispose();
}
+
+ VsyncEvent.Dispose();
}
}
}
diff --git a/Ryujinx.Core/OsHle/IdDictionary.cs b/Ryujinx.Core/OsHle/IdDictionary.cs
index 0b909246..0746ae81 100644
--- a/Ryujinx.Core/OsHle/IdDictionary.cs
+++ b/Ryujinx.Core/OsHle/IdDictionary.cs
@@ -1,11 +1,10 @@
using System;
-using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace Ryujinx.Core.OsHle
{
- class IdDictionary : IEnumerable<object>
+ class IdDictionary
{
private ConcurrentDictionary<int, object> Objs;
@@ -39,18 +38,6 @@ namespace Ryujinx.Core.OsHle
throw new InvalidOperationException();
}
- public bool ReplaceData(int Id, object Data)
- {
- if (Objs.ContainsKey(Id))
- {
- Objs[Id] = Data;
-
- return true;
- }
-
- return false;
- }
-
public object GetData(int Id)
{
if (Objs.TryGetValue(Id, out object Data))
@@ -71,31 +58,25 @@ namespace Ryujinx.Core.OsHle
return default(T);
}
- public bool Delete(int Id)
+ public object Delete(int Id)
{
if (Objs.TryRemove(Id, out object Obj))
{
- if (Obj is IDisposable DisposableObj)
- {
- DisposableObj.Dispose();
- }
-
FreeIdHint = Id;
- return true;
+ return Obj;
}
- return false;
+ return null;
}
- IEnumerator<object> IEnumerable<object>.GetEnumerator()
+ public ICollection<object> Clear()
{
- return Objs.Values.GetEnumerator();
- }
+ ICollection<object> Values = Objs.Values;
- IEnumerator IEnumerable.GetEnumerator()
- {
- return Objs.Values.GetEnumerator();
+ Objs.Clear();
+
+ return Values;
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Ipc/IpcDomCmd.cs b/Ryujinx.Core/OsHle/Ipc/IpcDomCmd.cs
deleted file mode 100644
index 1ef0c408..00000000
--- a/Ryujinx.Core/OsHle/Ipc/IpcDomCmd.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Ryujinx.Core.OsHle.Ipc
-{
- enum IpcDomCmd
- {
- SendMsg = 1,
- DeleteObj = 2
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs
index f2179a96..35a2535b 100644
--- a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs
+++ b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs
@@ -1,6 +1,5 @@
using ChocolArm64.Memory;
using Ryujinx.Core.OsHle.Handles;
-using Ryujinx.Core.OsHle.IpcServices;
using System;
using System.IO;
@@ -8,20 +7,15 @@ namespace Ryujinx.Core.OsHle.Ipc
{
static class IpcHandler
{
- private const long SfciMagic = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'I' << 24;
- private const long SfcoMagic = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'O' << 24;
-
public static void IpcCall(
Switch Ns,
Process Process,
AMemory Memory,
- HSession Session,
+ KSession Session,
IpcMessage Request,
- int ThreadId,
- long CmdPtr,
- int HndId)
+ long CmdPtr)
{
- IpcMessage Response = new IpcMessage(Request.IsDomain && Request.Type == IpcMessageType.Request);
+ IpcMessage Response = new IpcMessage();
using (MemoryStream Raw = new MemoryStream(Request.RawData))
{
@@ -29,94 +23,25 @@ namespace Ryujinx.Core.OsHle.Ipc
if (Request.Type == IpcMessageType.Request)
{
- string ServiceName = Session.Service.GetType().Name;
-
- ServiceProcessRequest ProcReq = null;
-
- bool IgnoreNullPR = false;
-
- string DbgServiceName = string.Empty;
-
- if (Session is HDomain Dom)
- {
- if (Request.DomCmd == IpcDomCmd.SendMsg)
- {
- long Magic = ReqReader.ReadInt64();
- int CmdId = (int)ReqReader.ReadInt64();
-
- object Obj = Dom.GetObject(Request.DomObjId);
-
- if (Obj is HDomain)
- {
- Session.Service.Commands.TryGetValue(CmdId, out ProcReq);
-
- DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}";
- }
- else if (Obj != null)
- {
- ((IIpcService)Obj).Commands.TryGetValue(CmdId, out ProcReq);
-
- DbgServiceName = $"{Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}";
- }
- }
- else if (Request.DomCmd == IpcDomCmd.DeleteObj)
- {
- Dom.Delete(Request.DomObjId);
-
- Response = FillResponse(Response, 0);
-
- IgnoreNullPR = true;
- }
- }
- else
- {
- long Magic = ReqReader.ReadInt64();
- int CmdId = (int)ReqReader.ReadInt64();
-
- if (Session is HSessionObj)
- {
- object Obj = ((HSessionObj)Session).Obj;
+ Response.Type = IpcMessageType.Response;
- ((IIpcService)Obj).Commands.TryGetValue(CmdId, out ProcReq);
-
- DbgServiceName = $"{Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}";
- }
- else
- {
- Session.Service.Commands.TryGetValue(CmdId, out ProcReq);
-
- DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}";
- }
- }
-
- DbgServiceName = $"Tid {ThreadId} {ServiceName} {DbgServiceName}";
-
- Logging.Debug($"IpcMessage: {DbgServiceName}");
-
- if (ProcReq != null)
+ using (MemoryStream ResMS = new MemoryStream())
{
- using (MemoryStream ResMS = new MemoryStream())
- {
- BinaryWriter ResWriter = new BinaryWriter(ResMS);
+ BinaryWriter ResWriter = new BinaryWriter(ResMS);
- ServiceCtx Context = new ServiceCtx(
- Ns,
- Process,
- Memory,
- Session,
- Request,
- Response,
- ReqReader,
- ResWriter);
+ ServiceCtx Context = new ServiceCtx(
+ Ns,
+ Process,
+ Memory,
+ Session,
+ Request,
+ Response,
+ ReqReader,
+ ResWriter);
- long Result = ProcReq(Context);
+ Session.Service.CallMethod(Context);
- Response = FillResponse(Response, Result, ResMS.ToArray());
- }
- }
- else if (!IgnoreNullPR)
- {
- throw new NotImplementedException(DbgServiceName);
+ Response.RawData = ResMS.ToArray();
}
}
else if (Request.Type == IpcMessageType.Control)
@@ -128,11 +53,7 @@ namespace Ryujinx.Core.OsHle.Ipc
{
case 0:
{
- HDomain Dom = new HDomain(Session);
-
- Process.HandleTable.ReplaceData(HndId, Dom);
-
- Request = FillResponse(Response, 0, Dom.Add(Dom));
+ Request = FillResponse(Response, 0, Session.Service.ConvertToDomain());
break;
}
@@ -198,7 +119,7 @@ namespace Ryujinx.Core.OsHle.Ipc
{
BinaryWriter Writer = new BinaryWriter(MS);
- Writer.Write(SfcoMagic);
+ Writer.Write(IpcMagic.Sfco);
Writer.Write(Result);
if (Data != null)
diff --git a/Ryujinx.Core/OsHle/Ipc/IpcLog.cs b/Ryujinx.Core/OsHle/Ipc/IpcLog.cs
index dfec7ccf..01915d91 100644
--- a/Ryujinx.Core/OsHle/Ipc/IpcLog.cs
+++ b/Ryujinx.Core/OsHle/Ipc/IpcLog.cs
@@ -125,8 +125,7 @@ namespace Ryujinx.Core.OsHle.Ipc
Reader.ReadInt64(); //Padding
- IpcMessage += Environment.NewLine + $" Domain:" + Environment.NewLine +
- $" DomCmd: {Enum.GetName(typeof(IpcDomCmd), DomCmd)}" + Environment.NewLine +
+ IpcMessage += Environment.NewLine + $" Domain:" + Environment.NewLine + Environment.NewLine +
$" DomObjId: {DomObjId.ToString()}" + Environment.NewLine;
}
diff --git a/Ryujinx.Core/OsHle/Ipc/IpcMagic.cs b/Ryujinx.Core/OsHle/Ipc/IpcMagic.cs
new file mode 100644
index 00000000..e3b8c74e
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Ipc/IpcMagic.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Core.OsHle.Ipc
+{
+ abstract class IpcMagic
+ {
+ public const long Sfci = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'I' << 24;
+ public const long Sfco = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'O' << 24;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs
index ebb3dbca..a9924246 100644
--- a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs
+++ b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs
@@ -17,10 +17,6 @@ namespace Ryujinx.Core.OsHle.Ipc
public List<int> ResponseObjIds { get; private set; }
- public bool IsDomain { get; private set; }
- public IpcDomCmd DomCmd { get; private set; }
- public int DomObjId { get; private set; }
-
public byte[] RawData { get; set; }
public IpcMessage()
@@ -34,27 +30,18 @@ namespace Ryujinx.Core.OsHle.Ipc
ResponseObjIds = new List<int>();
}
- public IpcMessage(bool Domain) : this()
+ public IpcMessage(byte[] Data, long CmdPtr) : this()
{
- IsDomain = Domain;
- }
-
- public IpcMessage(byte[] Data, long CmdPtr, bool Domain) : this()
- {
- Logging.Ipc(Data, CmdPtr, Domain);
-
using (MemoryStream MS = new MemoryStream(Data))
{
BinaryReader Reader = new BinaryReader(MS);
- Initialize(Reader, CmdPtr, Domain);
+ Initialize(Reader, CmdPtr);
}
}
- private void Initialize(BinaryReader Reader, long CmdPtr, bool Domain)
+ private void Initialize(BinaryReader Reader, long CmdPtr)
{
- IsDomain = Domain;
-
int Word0 = Reader.ReadInt32();
int Word1 = Reader.ReadInt32();
@@ -110,19 +97,6 @@ namespace Ryujinx.Core.OsHle.Ipc
RecvListCount = 0;
}
- if (Domain && Type == IpcMessageType.Request)
- {
- int DomWord0 = Reader.ReadInt32();
-
- DomCmd = (IpcDomCmd)(DomWord0 & 0xff);
-
- RawDataSize = (DomWord0 >> 16) & 0xffff;
-
- DomObjId = Reader.ReadInt32();
-
- Reader.ReadInt64(); //Padding
- }
-
RawData = Reader.ReadBytes(RawDataSize);
Reader.BaseStream.Seek(RecvListPos, SeekOrigin.Begin);
@@ -165,9 +139,7 @@ namespace Ryujinx.Core.OsHle.Ipc
//This is the weirdest padding I've seen so far...
int Pad1 = 0x10 - Pad0;
- DataLength = (DataLength + Pad0 + Pad1 + (IsDomain ? 0x10 : 0)) / 4;
-
- DataLength += ResponseObjIds.Count;
+ DataLength = (DataLength + Pad0 + Pad1) / 4;
Word1 = DataLength & 0x3ff;
@@ -182,23 +154,11 @@ namespace Ryujinx.Core.OsHle.Ipc
MS.Seek(Pad0, SeekOrigin.Current);
- if (IsDomain)
- {
- Writer.Write(ResponseObjIds.Count);
- Writer.Write(0);
- Writer.Write(0L);
- }
-
if (RawData != null)
{
Writer.Write(RawData);
}
- foreach (int Id in ResponseObjIds)
- {
- Writer.Write(Id);
- }
-
Writer.Write(new byte[Pad1]);
return MS.ToArray();
diff --git a/Ryujinx.Core/OsHle/KernelErr.cs b/Ryujinx.Core/OsHle/KernelErr.cs
index 19983af1..e476f631 100644
--- a/Ryujinx.Core/OsHle/KernelErr.cs
+++ b/Ryujinx.Core/OsHle/KernelErr.cs
@@ -6,6 +6,5 @@ namespace Ryujinx.Core.OsHle
public const int InvalidHandle = 114;
public const int Timeout = 117;
public const int InvalidInfo = 120;
- public const int InvalidIpcReq = 123;
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Mutex.cs b/Ryujinx.Core/OsHle/Mutex.cs
index c619e121..7a0e8b6c 100644
--- a/Ryujinx.Core/OsHle/Mutex.cs
+++ b/Ryujinx.Core/OsHle/Mutex.cs
@@ -16,7 +16,7 @@ namespace Ryujinx.Core.OsHle
private object EnterWaitLock;
- private ConcurrentQueue<HThread> WaitingThreads;
+ private ConcurrentQueue<KThread> WaitingThreads;
public Mutex(Process Process, long MutexAddress, int OwnerThreadHandle)
{
@@ -27,10 +27,10 @@ namespace Ryujinx.Core.OsHle
EnterWaitLock = new object();
- WaitingThreads = new ConcurrentQueue<HThread>();
+ WaitingThreads = new ConcurrentQueue<KThread>();
}
- public void WaitForLock(HThread RequestingThread, int RequestingThreadHandle)
+ public void WaitForLock(KThread RequestingThread, int RequestingThreadHandle)
{
AcquireMutexValue();
@@ -83,11 +83,11 @@ namespace Ryujinx.Core.OsHle
ReleaseMutexValue();
- HThread[] UnlockedThreads = new HThread[WaitingThreads.Count];
+ KThread[] UnlockedThreads = new KThread[WaitingThreads.Count];
int Index = 0;
- while (WaitingThreads.TryDequeue(out HThread Thread))
+ while (WaitingThreads.TryDequeue(out KThread Thread))
{
UnlockedThreads[Index++] = Thread;
}
diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs
index 239b1980..1846e576 100644
--- a/Ryujinx.Core/OsHle/Process.cs
+++ b/Ryujinx.Core/OsHle/Process.cs
@@ -5,6 +5,7 @@ using Ryujinx.Core.Loaders;
using Ryujinx.Core.Loaders.Executables;
using Ryujinx.Core.OsHle.Exceptions;
using Ryujinx.Core.OsHle.Handles;
+using Ryujinx.Core.OsHle.IpcServices.NvServices;
using Ryujinx.Core.OsHle.Svc;
using System;
using System.Collections.Concurrent;
@@ -31,21 +32,21 @@ namespace Ryujinx.Core.OsHle
public AMemory Memory { get; private set; }
- public ServiceMgr Services { get; private set; }
-
public KProcessScheduler Scheduler { get; private set; }
public KProcessHandleTable HandleTable { get; private set; }
+ public AppletStateMgr AppletState { get; private set; }
+
private SvcHandler SvcHandler;
private ConcurrentDictionary<int, AThread> TlsSlots;
- private ConcurrentDictionary<long, HThread> ThreadsByTpidr;
+ private ConcurrentDictionary<long, KThread> ThreadsByTpidr;
private List<Executable> Executables;
- private HThread MainThread;
+ private KThread MainThread;
private long ImageBase;
@@ -60,17 +61,17 @@ namespace Ryujinx.Core.OsHle
Memory = new AMemory();
- Services = new ServiceMgr();
-
HandleTable = new KProcessHandleTable();
- Scheduler = new KProcessScheduler();
+ Scheduler = new KProcessScheduler();
+
+ AppletState = new AppletStateMgr();
SvcHandler = new SvcHandler(Ns, this);
TlsSlots = new ConcurrentDictionary<int, AThread>();
- ThreadsByTpidr = new ConcurrentDictionary<long, HThread>();
+ ThreadsByTpidr = new ConcurrentDictionary<long, KThread>();
Executables = new List<Executable>();
@@ -132,7 +133,7 @@ namespace Ryujinx.Core.OsHle
return false;
}
- MainThread = HandleTable.GetData<HThread>(Handle);
+ MainThread = HandleTable.GetData<KThread>(Handle);
if (NeedsHbAbi)
{
@@ -186,7 +187,7 @@ namespace Ryujinx.Core.OsHle
AThread Thread = new AThread(GetTranslator(), Memory, EntryPoint);
- HThread ThreadHnd = new HThread(Thread, ProcessorId, Priority);
+ KThread ThreadHnd = new KThread(Thread, ProcessorId, Priority);
int Handle = HandleTable.OpenHandle(ThreadHnd);
@@ -311,9 +312,9 @@ namespace Ryujinx.Core.OsHle
return (int)((Position - MemoryRegions.TlsPagesAddress) / TlsSize);
}
- public HThread GetThread(long Tpidr)
+ public KThread GetThread(long Tpidr)
{
- if (!ThreadsByTpidr.TryGetValue(Tpidr, out HThread Thread))
+ if (!ThreadsByTpidr.TryGetValue(Tpidr, out KThread Thread))
{
Logging.Error($"Thread with TPIDR 0x{Tpidr:x16} not found!");
}
@@ -344,11 +345,27 @@ namespace Ryujinx.Core.OsHle
}
Disposed = true;
-
- Services.Dispose();
- HandleTable.Dispose();
+
+ foreach (object Obj in HandleTable.Clear())
+ {
+ if (Obj is KSession Session)
+ {
+ Session.Dispose();
+ }
+ }
+
+ ServiceNvDrv.Fds.DeleteProcess(this);
+
+ ServiceNvDrv.NvMaps.DeleteProcess(this);
+
+ ServiceNvDrv.NvMapsById.DeleteProcess(this);
+
Scheduler.Dispose();
+
+ AppletState.Dispose();
+
SvcHandler.Dispose();
+
Memory.Dispose();
Logging.Info($"Process {ProcessId} exiting...");
diff --git a/Ryujinx.Core/OsHle/ServiceCtx.cs b/Ryujinx.Core/OsHle/ServiceCtx.cs
index 60c378d5..7716507f 100644
--- a/Ryujinx.Core/OsHle/ServiceCtx.cs
+++ b/Ryujinx.Core/OsHle/ServiceCtx.cs
@@ -10,7 +10,7 @@ namespace Ryujinx.Core.OsHle
public Switch Ns { get; private set; }
public Process Process { get; private set; }
public AMemory Memory { get; private set; }
- public HSession Session { get; private set; }
+ public KSession Session { get; private set; }
public IpcMessage Request { get; private set; }
public IpcMessage Response { get; private set; }
public BinaryReader RequestData { get; private set; }
@@ -20,7 +20,7 @@ namespace Ryujinx.Core.OsHle
Switch Ns,
Process Process,
AMemory Memory,
- HSession Session,
+ KSession Session,
IpcMessage Request,
IpcMessage Response,
BinaryReader RequestData,
diff --git a/Ryujinx.Core/OsHle/ServiceMgr.cs b/Ryujinx.Core/OsHle/ServiceMgr.cs
deleted file mode 100644
index 39f62368..00000000
--- a/Ryujinx.Core/OsHle/ServiceMgr.cs
+++ /dev/null
@@ -1,128 +0,0 @@
-using Ryujinx.Core.OsHle.IpcServices;
-using Ryujinx.Core.OsHle.IpcServices.Acc;
-using Ryujinx.Core.OsHle.IpcServices.Am;
-using Ryujinx.Core.OsHle.IpcServices.Apm;
-using Ryujinx.Core.OsHle.IpcServices.Aud;
-using Ryujinx.Core.OsHle.IpcServices.Bsd;
-using Ryujinx.Core.OsHle.IpcServices.Friend;
-using Ryujinx.Core.OsHle.IpcServices.FspSrv;
-using Ryujinx.Core.OsHle.IpcServices.Hid;
-using Ryujinx.Core.OsHle.IpcServices.Lm;
-using Ryujinx.Core.OsHle.IpcServices.Nifm;
-using Ryujinx.Core.OsHle.IpcServices.Ns;
-using Ryujinx.Core.OsHle.IpcServices.NvServices;
-using Ryujinx.Core.OsHle.IpcServices.Pctl;
-using Ryujinx.Core.OsHle.IpcServices.Pl;
-using Ryujinx.Core.OsHle.IpcServices.Set;
-using Ryujinx.Core.OsHle.IpcServices.Sfdnsres;
-using Ryujinx.Core.OsHle.IpcServices.Sm;
-using Ryujinx.Core.OsHle.IpcServices.Ssl;
-using Ryujinx.Core.OsHle.IpcServices.Time;
-using Ryujinx.Core.OsHle.IpcServices.Vi;
-using System;
-using System.Collections.Generic;
-
-namespace Ryujinx.Core.OsHle
-{
- class ServiceMgr : IDisposable
- {
- private Dictionary<string, IIpcService> Services;
-
- public ServiceMgr()
- {
- Services = new Dictionary<string, IIpcService>();
- }
-
- public IIpcService GetService(string Name)
- {
- lock (Services)
- {
- string LookUpName;
-
- //Same service with different privileges.
- if (Name.EndsWith(":a") ||
- Name.EndsWith(":m") ||
- Name.EndsWith(":s") ||
- Name.EndsWith(":su") ||
- Name.EndsWith(":u") ||
- Name.EndsWith(":u0") ||
- Name.EndsWith(":u1"))
- {
- LookUpName = Name.Substring(0, Name.IndexOf(':'));
- }
- else
- {
- LookUpName = Name;
- }
-
- if (!Services.TryGetValue(LookUpName, out IIpcService Service))
- {
- switch (Name)
- {
- case "acc:u0": Service = new ServiceAcc(); break;
- case "aoc:u": Service = new ServiceNs(); break;
- case "apm": Service = new ServiceApm(); break;
- case "apm:p": Service = new ServiceApm(); break;
- case "appletOE": Service = new ServiceAppletOE(); break;
- case "audout:u": Service = new ServiceAudOut(); break;
- case "audren:u": Service = new ServiceAudRen(); break;
- case "bsd:s": Service = new ServiceBsd(); break;
- case "bsd:u": Service = new ServiceBsd(); break;
- case "friend:a": Service = new ServiceFriend(); break;
- case "fsp-srv": Service = new ServiceFspSrv(); break;
- case "hid": Service = new ServiceHid(); break;
- case "lm": Service = new ServiceLm(); break;
- case "nifm:u": Service = new ServiceNifm(); break;
- case "nvdrv": Service = new ServiceNvDrv(); break;
- case "nvdrv:a": Service = new ServiceNvDrv(); break;
- case "pctl:a": Service = new ServicePctl(); break;
- case "pl:u": Service = new ServicePl(); break;
- case "set": Service = new ServiceSet(); break;
- case "set:sys": Service = new ServiceSetSys(); break;
- case "sfdnsres": Service = new ServiceSfdnsres(); break;
- case "sm:": Service = new ServiceSm(); break;
- case "ssl": Service = new ServiceSsl(); break;
- case "time:s": Service = new ServiceTime(); break;
- case "time:u": Service = new ServiceTime(); break;
- case "vi:m": Service = new ServiceVi(); break;
- case "vi:s": Service = new ServiceVi(); break;
- case "vi:u": Service = new ServiceVi(); break;
- }
-
- if (Service == null)
- {
- throw new NotImplementedException(Name);
- }
-
- Services.Add(LookUpName, Service);
- }
-
- return Service;
- }
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool Disposing)
- {
- if (Disposing)
- {
- lock (Services)
- {
- foreach (IIpcService Service in Services.Values)
- {
- if (Service is IDisposable DisposableSrv)
- {
- DisposableSrv.Dispose();
- }
- }
-
- Services.Clear();
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Acc/IManagerForApplication.cs b/Ryujinx.Core/OsHle/Services/Acc/IManagerForApplication.cs
index ab491eac..9e309142 100644
--- a/Ryujinx.Core/OsHle/Services/Acc/IManagerForApplication.cs
+++ b/Ryujinx.Core/OsHle/Services/Acc/IManagerForApplication.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Acc
{
- class IManagerForApplication : IIpcService
+ class IManagerForApplication : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IManagerForApplication()
{
diff --git a/Ryujinx.Core/OsHle/Services/Acc/IProfile.cs b/Ryujinx.Core/OsHle/Services/Acc/IProfile.cs
index 77fe2b48..bdeadfe8 100644
--- a/Ryujinx.Core/OsHle/Services/Acc/IProfile.cs
+++ b/Ryujinx.Core/OsHle/Services/Acc/IProfile.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Acc
{
- class IProfile : IIpcService
+ class IProfile : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IProfile()
{
diff --git a/Ryujinx.Core/OsHle/Services/Acc/ServiceAcc.cs b/Ryujinx.Core/OsHle/Services/Acc/ServiceAcc.cs
index 8844bb5d..8b0a99d9 100644
--- a/Ryujinx.Core/OsHle/Services/Acc/ServiceAcc.cs
+++ b/Ryujinx.Core/OsHle/Services/Acc/ServiceAcc.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Acc
{
- class ServiceAcc : IIpcService
+ class ServiceAcc : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceAcc()
{
diff --git a/Ryujinx.Core/OsHle/Services/Am/AmErr.cs b/Ryujinx.Core/OsHle/Services/Am/AmErr.cs
new file mode 100644
index 00000000..be165874
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/Am/AmErr.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.Core.OsHle.IpcServices.Am
+{
+ static class AmErr
+ {
+ public const int NoMessages = 3;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Am/FocusState.cs b/Ryujinx.Core/OsHle/Services/Am/FocusState.cs
new file mode 100644
index 00000000..08dffe3b
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/Am/FocusState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Core.OsHle.IpcServices.Am
+{
+ enum FocusState
+ {
+ InFocus = 1,
+ OutOfFocus = 2
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs b/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs
index c989cdd4..685a7482 100644
--- a/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs
@@ -2,15 +2,13 @@ using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
using System.IO;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class IApplicationFunctions : IIpcService
+ class IApplicationFunctions : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IApplicationFunctions()
{
diff --git a/Ryujinx.Core/OsHle/Services/Am/IApplicationProxy.cs b/Ryujinx.Core/OsHle/Services/Am/IApplicationProxy.cs
index 5417d7f0..81bb2711 100644
--- a/Ryujinx.Core/OsHle/Services/Am/IApplicationProxy.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/IApplicationProxy.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class IApplicationProxy : IIpcService
+ class IApplicationProxy : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IApplicationProxy()
{
diff --git a/Ryujinx.Core/OsHle/Services/Am/IAudioController.cs b/Ryujinx.Core/OsHle/Services/Am/IAudioController.cs
index 1212f1e2..aa927d60 100644
--- a/Ryujinx.Core/OsHle/Services/Am/IAudioController.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/IAudioController.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class IAudioController : IIpcService
+ class IAudioController : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IAudioController()
{
diff --git a/Ryujinx.Core/OsHle/Services/Am/ICommonStateGetter.cs b/Ryujinx.Core/OsHle/Services/Am/ICommonStateGetter.cs
index 2999bbba..ec1fc774 100644
--- a/Ryujinx.Core/OsHle/Services/Am/ICommonStateGetter.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/ICommonStateGetter.cs
@@ -1,13 +1,16 @@
+using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
+using static Ryujinx.Core.OsHle.ErrorCode;
+
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class ICommonStateGetter : IIpcService
+ class ICommonStateGetter : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ICommonStateGetter()
{
@@ -17,37 +20,31 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am
{ 1, ReceiveMessage },
{ 5, GetOperationMode },
{ 6, GetPerformanceMode },
- { 9, GetCurrentFocusState },
+ { 9, GetCurrentFocusState }
};
}
- private enum FocusState
+ public long GetEventHandle(ServiceCtx Context)
{
- InFocus = 1,
- OutOfFocus = 2
- }
+ KEvent Event = Context.Process.AppletState.MessageEvent;
- private enum OperationMode
- {
- Handheld = 0,
- Docked = 1
- }
+ int Handle = Context.Process.HandleTable.OpenHandle(Event);
- public long GetEventHandle(ServiceCtx Context)
- {
- Context.ResponseData.Write(0L);
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
return 0;
}
public long ReceiveMessage(ServiceCtx Context)
{
- //Program expects 0xF at 0x17ae70 on puyo sdk,
- //otherwise runs on a infinite loop until it reads said value.
- //What it means is still unknown.
- Context.ResponseData.Write(0xfL);
+ if (!Context.Process.AppletState.TryDequeueMessage(out MessageInfo Message))
+ {
+ return MakeError(ErrorModule.Am, AmErr.NoMessages);
+ }
- return 0; //0x680;
+ Context.ResponseData.Write((int)Message);
+
+ return 0;
}
public long GetOperationMode(ServiceCtx Context)
@@ -66,7 +63,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am
public long GetCurrentFocusState(ServiceCtx Context)
{
- Context.ResponseData.Write((byte)FocusState.InFocus);
+ Context.ResponseData.Write((byte)Context.Process.AppletState.FocusState);
return 0;
}
diff --git a/Ryujinx.Core/OsHle/Services/Am/IDebugFunctions.cs b/Ryujinx.Core/OsHle/Services/Am/IDebugFunctions.cs
index 944e58d8..445b57e2 100644
--- a/Ryujinx.Core/OsHle/Services/Am/IDebugFunctions.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/IDebugFunctions.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class IDebugFunctions : IIpcService
+ class IDebugFunctions : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IDebugFunctions()
{
diff --git a/Ryujinx.Core/OsHle/Services/Am/IDisplayController.cs b/Ryujinx.Core/OsHle/Services/Am/IDisplayController.cs
index 979e842a..59956242 100644
--- a/Ryujinx.Core/OsHle/Services/Am/IDisplayController.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/IDisplayController.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class IDisplayController : IIpcService
+ class IDisplayController : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IDisplayController()
{
diff --git a/Ryujinx.Core/OsHle/Services/Am/ILibraryAppletCreator.cs b/Ryujinx.Core/OsHle/Services/Am/ILibraryAppletCreator.cs
index 9f5b5e69..02da3156 100644
--- a/Ryujinx.Core/OsHle/Services/Am/ILibraryAppletCreator.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/ILibraryAppletCreator.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class ILibraryAppletCreator : IIpcService
+ class ILibraryAppletCreator : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ILibraryAppletCreator()
{
diff --git a/Ryujinx.Core/OsHle/Services/Am/ISelfController.cs b/Ryujinx.Core/OsHle/Services/Am/ISelfController.cs
index 403e4072..c5865009 100644
--- a/Ryujinx.Core/OsHle/Services/Am/ISelfController.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/ISelfController.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class ISelfController : IIpcService
+ class ISelfController : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ISelfController()
{
diff --git a/Ryujinx.Core/OsHle/Services/Am/IStorage.cs b/Ryujinx.Core/OsHle/Services/Am/IStorage.cs
index 375b960b..8f99ea7d 100644
--- a/Ryujinx.Core/OsHle/Services/Am/IStorage.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/IStorage.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class IStorage : IIpcService
+ class IStorage : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public byte[] Data { get; private set; }
diff --git a/Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs b/Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs
index 6d83e6f9..096183ed 100644
--- a/Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs
@@ -5,11 +5,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class IStorageAccessor : IIpcService
+ class IStorageAccessor : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private IStorage Storage;
diff --git a/Ryujinx.Core/OsHle/Services/Am/IWindowController.cs b/Ryujinx.Core/OsHle/Services/Am/IWindowController.cs
index ddc73bce..a830f263 100644
--- a/Ryujinx.Core/OsHle/Services/Am/IWindowController.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/IWindowController.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class IWindowController : IIpcService
+ class IWindowController : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IWindowController()
{
diff --git a/Ryujinx.Core/OsHle/Services/Am/MessageInfo.cs b/Ryujinx.Core/OsHle/Services/Am/MessageInfo.cs
new file mode 100644
index 00000000..4c91e54a
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/Am/MessageInfo.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.Core.OsHle.IpcServices.Am
+{
+ enum MessageInfo
+ {
+ FocusStateChanged = 0xf,
+ OperationModeChanged = 0x1e,
+ PerformanceModeChanged = 0x1f
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Am/OperationMode.cs b/Ryujinx.Core/OsHle/Services/Am/OperationMode.cs
new file mode 100644
index 00000000..7103742f
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/Am/OperationMode.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Core.OsHle.IpcServices.Am
+{
+ enum OperationMode
+ {
+ Handheld = 0,
+ Docked = 1
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Am/ServiceAppletOE.cs b/Ryujinx.Core/OsHle/Services/Am/ServiceAppletOE.cs
index b60c93dd..255f74e6 100644
--- a/Ryujinx.Core/OsHle/Services/Am/ServiceAppletOE.cs
+++ b/Ryujinx.Core/OsHle/Services/Am/ServiceAppletOE.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Am
{
- class ServiceAppletOE : IIpcService
+ class ServiceAppletOE : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceAppletOE()
{
diff --git a/Ryujinx.Core/OsHle/Services/Apm/ISession.cs b/Ryujinx.Core/OsHle/Services/Apm/ISession.cs
index 500f7596..dd06e2c9 100644
--- a/Ryujinx.Core/OsHle/Services/Apm/ISession.cs
+++ b/Ryujinx.Core/OsHle/Services/Apm/ISession.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Apm
{
- class ISession : IIpcService
+ class ISession : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ISession()
{
diff --git a/Ryujinx.Core/OsHle/Services/Apm/ServiceApm.cs b/Ryujinx.Core/OsHle/Services/Apm/ServiceApm.cs
index d6c0400a..d7526216 100644
--- a/Ryujinx.Core/OsHle/Services/Apm/ServiceApm.cs
+++ b/Ryujinx.Core/OsHle/Services/Apm/ServiceApm.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Apm
{
- class ServiceApm : IIpcService
+ class ServiceApm : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceApm()
{
diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs
index 863c9a27..b8aa0a6e 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioDevice.cs
@@ -5,11 +5,11 @@ using System.Text;
namespace Ryujinx.Core.OsHle.IpcServices.Aud
{
- class IAudioDevice : IIpcService
+ class IAudioDevice : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IAudioDevice()
{
diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs
index 8cd013f8..9549eb57 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs
@@ -7,17 +7,19 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Aud
{
- class IAudioOut : IIpcService, IDisposable
+ class IAudioOut : IpcService, IDisposable
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private IAalOutput AudioOut;
+ private KEvent ReleaseEvent;
+
private int Track;
- public IAudioOut(IAalOutput AudioOut, int Track)
+ public IAudioOut(IAalOutput AudioOut, KEvent ReleaseEvent, int Track)
{
m_Commands = new Dictionary<int, ServiceProcessRequest>()
{
@@ -32,8 +34,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
{ 8, GetReleasedAudioOutBufferEx }
};
- this.AudioOut = AudioOut;
- this.Track = Track;
+ this.AudioOut = AudioOut;
+ this.ReleaseEvent = ReleaseEvent;
+ this.Track = Track;
}
public long GetAudioOutState(ServiceCtx Context)
@@ -77,7 +80,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
public long RegisterBufferEvent(ServiceCtx Context)
{
- int Handle = Context.Process.HandleTable.OpenHandle(new HEvent());
+ int Handle = Context.Process.HandleTable.OpenHandle(ReleaseEvent);
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@@ -143,6 +146,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
if (Disposing)
{
AudioOut.CloseTrack(Track);
+
+ ReleaseEvent.Dispose();
}
}
}
diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs
index 4d29371f..68fe0f4c 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs
@@ -1,14 +1,17 @@
using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Ipc;
+using System;
using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Aud
{
- class IAudioRenderer : IIpcService
+ class IAudioRenderer : IpcService, IDisposable
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ private KEvent UpdateEvent;
public IAudioRenderer()
{
@@ -19,6 +22,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
{ 6, StopAudioRenderer },
{ 7, QuerySystemEvent }
};
+
+ UpdateEvent = new KEvent();
}
public long RequestUpdateAudioRenderer(ServiceCtx Context)
@@ -41,6 +46,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
Context.Memory.WriteInt32(Position + Offset, 5);
}
+ //TODO: We shouldn't be signaling this here.
+ UpdateEvent.Handle.Set();
+
return 0;
}
@@ -56,11 +64,24 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
public long QuerySystemEvent(ServiceCtx Context)
{
- int Handle = Context.Process.HandleTable.OpenHandle(new HEvent());
+ int Handle = Context.Process.HandleTable.OpenHandle(UpdateEvent);
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
return 0;
}
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool Disposing)
+ {
+ if (Disposing)
+ {
+ UpdateEvent.Dispose();
+ }
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs
index 19f23d1c..5064398c 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs
@@ -1,18 +1,17 @@
using ChocolArm64.Memory;
using Ryujinx.Audio;
+using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
using System.Text;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Aud
{
- class ServiceAudOut : IIpcService
+ class ServiceAudOut : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceAudOut()
{
@@ -73,9 +72,16 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
Channels = 2;
}
- int Track = AudioOut.OpenTrack(SampleRate, Channels, out AudioFormat Format);
+ KEvent ReleaseEvent = new KEvent();
+
+ ReleaseCallback Callback = () =>
+ {
+ ReleaseEvent.Handle.Set();
+ };
+
+ int Track = AudioOut.OpenTrack(SampleRate, Channels, Callback, out AudioFormat Format);
- MakeObject(Context, new IAudioOut(AudioOut, Track));
+ MakeObject(Context, new IAudioOut(AudioOut, ReleaseEvent, Track));
Context.ResponseData.Write(SampleRate);
Context.ResponseData.Write(Channels);
diff --git a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs
index c3a0a8b4..8c7d9525 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Aud
{
- class ServiceAudRen : IIpcService
+ class ServiceAudRen : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceAudRen()
{
diff --git a/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs b/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs
index 680e8405..825b3b27 100644
--- a/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs
+++ b/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs
@@ -51,11 +51,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd
public Socket Handle;
}
- class ServiceBsd : IIpcService
+ class ServiceBsd : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private List<SocketBsd> Sockets = new List<SocketBsd>();
diff --git a/Ryujinx.Core/OsHle/Services/Friend/IFriendService.cs b/Ryujinx.Core/OsHle/Services/Friend/IFriendService.cs
index e3e03da8..f5497f38 100644
--- a/Ryujinx.Core/OsHle/Services/Friend/IFriendService.cs
+++ b/Ryujinx.Core/OsHle/Services/Friend/IFriendService.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Friend
{
- class IFriendService : IIpcService
+ class IFriendService : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IFriendService()
{
diff --git a/Ryujinx.Core/OsHle/Services/Friend/ServiceFriend.cs b/Ryujinx.Core/OsHle/Services/Friend/ServiceFriend.cs
index 674877f6..43baf8bb 100644
--- a/Ryujinx.Core/OsHle/Services/Friend/ServiceFriend.cs
+++ b/Ryujinx.Core/OsHle/Services/Friend/ServiceFriend.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Friend
{
- class ServiceFriend : IIpcService
+ class ServiceFriend : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceFriend()
{
diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/IDirectory.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IDirectory.cs
index 54dbec74..6563c6aa 100644
--- a/Ryujinx.Core/OsHle/Services/FspSrv/IDirectory.cs
+++ b/Ryujinx.Core/OsHle/Services/FspSrv/IDirectory.cs
@@ -7,13 +7,13 @@ using System.Text;
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
{
- class IDirectory : IIpcService, IDisposable
+ class IDirectory : IpcService, IDisposable
{
private const int DirectoryEntrySize = 0x310;
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private List<string> DirectoryEntries;
diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs
index b9973061..7d01b22f 100644
--- a/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs
+++ b/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs
@@ -6,11 +6,11 @@ using System.IO;
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
{
- class IFile : IIpcService, IDisposable
+ class IFile : IpcService, IDisposable
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private Stream BaseStream;
diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs
index 62bcb8e8..d5c2766e 100644
--- a/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs
+++ b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs
@@ -5,15 +5,14 @@ using System.IO;
using System.Text;
using static Ryujinx.Core.OsHle.ErrorCode;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
{
- class IFileSystem : IIpcService
+ class IFileSystem : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private HashSet<string> OpenPaths;
diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/IStorage.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IStorage.cs
index 297461a0..d0f40333 100644
--- a/Ryujinx.Core/OsHle/Services/FspSrv/IStorage.cs
+++ b/Ryujinx.Core/OsHle/Services/FspSrv/IStorage.cs
@@ -5,11 +5,11 @@ using System.IO;
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
{
- class IStorage : IIpcService
+ class IStorage : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private Stream BaseStream;
diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/ServiceFspSrv.cs b/Ryujinx.Core/OsHle/Services/FspSrv/ServiceFspSrv.cs
index 991f4027..c6f23005 100644
--- a/Ryujinx.Core/OsHle/Services/FspSrv/ServiceFspSrv.cs
+++ b/Ryujinx.Core/OsHle/Services/FspSrv/ServiceFspSrv.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
{
- class ServiceFspSrv : IIpcService
+ class ServiceFspSrv : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceFspSrv()
{
diff --git a/Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs b/Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs
index f6596f42..ff829172 100644
--- a/Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs
+++ b/Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Hid
{
- class IActiveApplicationDeviceList : IIpcService
+ class IActiveApplicationDeviceList : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IActiveApplicationDeviceList()
{
diff --git a/Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs b/Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs
index ef437c02..2b7e934e 100644
--- a/Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs
+++ b/Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs
@@ -4,11 +4,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Hid
{
- class IAppletResource : IIpcService
+ class IAppletResource : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private HSharedMem HidSharedMem;
diff --git a/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs
index 6735c6ad..f15cbcfc 100644
--- a/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs
+++ b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs
@@ -2,15 +2,13 @@ using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
using Ryujinx.Core.Input;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Hid
{
- class ServiceHid : IIpcService
+ class ServiceHid : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceHid()
{
diff --git a/Ryujinx.Core/OsHle/Services/IpcService.cs b/Ryujinx.Core/OsHle/Services/IpcService.cs
new file mode 100644
index 00000000..9dca8114
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/IpcService.cs
@@ -0,0 +1,151 @@
+using Ryujinx.Core.OsHle.Ipc;
+using Ryujinx.Core.OsHle.Handles;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Ryujinx.Core.OsHle.IpcServices
+{
+ abstract class IpcService : IIpcService
+ {
+ public abstract IReadOnlyDictionary<int, ServiceProcessRequest> Commands { get; }
+
+ private IdDictionary DomainObjects;
+
+ private int SelfId;
+
+ private bool IsDomain;
+
+ public IpcService()
+ {
+ DomainObjects = new IdDictionary();
+
+ SelfId = -1;
+ }
+
+ public int ConvertToDomain()
+ {
+ if (SelfId == -1)
+ {
+ SelfId = DomainObjects.Add(this);
+ }
+
+ IsDomain = true;
+
+ return SelfId;
+ }
+
+ public void ConvertToSession()
+ {
+ IsDomain = false;
+ }
+
+ public void CallMethod(ServiceCtx Context)
+ {
+ IIpcService Service = this;
+
+ if (IsDomain)
+ {
+ int DomainWord0 = Context.RequestData.ReadInt32();
+ int DomainObjId = Context.RequestData.ReadInt32();
+
+ long Padding = Context.RequestData.ReadInt64();
+
+ int DomainCmd = DomainWord0 & 0xff;
+
+ if (DomainCmd == 1)
+ {
+ Service = GetObject(DomainObjId);
+
+ Context.ResponseData.Write(0L);
+ Context.ResponseData.Write(0L);
+ }
+ else if (DomainCmd == 2)
+ {
+ Delete(DomainObjId);
+
+ Context.ResponseData.Write(0L);
+
+ return;
+ }
+ else
+ {
+ throw new NotImplementedException($"Domain command: {DomainCmd}");
+ }
+ }
+
+ long SfciMagic = Context.RequestData.ReadInt64();
+ int CommandId = (int)Context.RequestData.ReadInt64();
+
+ if (Service.Commands.TryGetValue(CommandId, out ServiceProcessRequest ProcessRequest))
+ {
+ Context.ResponseData.BaseStream.Seek(IsDomain ? 0x20 : 0x10, SeekOrigin.Begin);
+
+ Logging.Trace($"{Service.GetType().Name}: {ProcessRequest.Method.Name}");
+
+ long Result = ProcessRequest(Context);
+
+ if (IsDomain)
+ {
+ foreach (int Id in Context.Response.ResponseObjIds)
+ {
+ Context.ResponseData.Write(Id);
+ }
+
+ Context.ResponseData.BaseStream.Seek(0, SeekOrigin.Begin);
+
+ Context.ResponseData.Write(Context.Response.ResponseObjIds.Count);
+ }
+
+ Context.ResponseData.BaseStream.Seek(IsDomain ? 0x10 : 0, SeekOrigin.Begin);
+
+ Context.ResponseData.Write(IpcMagic.Sfco);
+ Context.ResponseData.Write(Result);
+ }
+ else
+ {
+ throw new NotImplementedException($"{Service.GetType().Name}: {CommandId}");
+ }
+ }
+
+ protected static void MakeObject(ServiceCtx Context, IpcService Obj)
+ {
+ IpcService Service = Context.Session.Service;
+
+ if (Service.IsDomain)
+ {
+ Context.Response.ResponseObjIds.Add(Service.Add(Obj));
+ }
+ else
+ {
+ KSession Session = new KSession(Obj);
+
+ int Handle = Context.Process.HandleTable.OpenHandle(Session);
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
+ }
+ }
+
+ private int Add(IIpcService Obj)
+ {
+ return DomainObjects.Add(Obj);
+ }
+
+ private bool Delete(int Id)
+ {
+ object Obj = DomainObjects.Delete(Id);
+
+ if (Obj is IDisposable DisposableObj)
+ {
+ DisposableObj.Dispose();
+ }
+
+ return Obj != null;
+ }
+
+ private IIpcService GetObject(int Id)
+ {
+ return DomainObjects.GetData<IIpcService>(Id);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs b/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
index 8ef9f3c6..c3f5b035 100644
--- a/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
+++ b/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
@@ -7,11 +7,11 @@ using System.Text;
namespace Ryujinx.Core.OsHle.IpcServices.Lm
{
- class ILogger : IIpcService
+ class ILogger : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ILogger()
{
diff --git a/Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs b/Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs
index ca3fe35e..e23ff565 100644
--- a/Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs
+++ b/Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Lm
{
- class ServiceLm : IIpcService
+ class ServiceLm : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceLm()
{
@@ -21,8 +19,6 @@ namespace Ryujinx.Core.OsHle.IpcServices.Lm
public long Initialize(ServiceCtx Context)
{
- Context.Session.Initialize();
-
MakeObject(Context, new ILogger());
return 0;
diff --git a/Ryujinx.Core/OsHle/Services/Nifm/IGeneralService.cs b/Ryujinx.Core/OsHle/Services/Nifm/IGeneralService.cs
index c31ee36b..abd1cc20 100644
--- a/Ryujinx.Core/OsHle/Services/Nifm/IGeneralService.cs
+++ b/Ryujinx.Core/OsHle/Services/Nifm/IGeneralService.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Nifm
{
- class IGeneralService : IIpcService
+ class IGeneralService : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IGeneralService()
{
diff --git a/Ryujinx.Core/OsHle/Services/Nifm/IRequest.cs b/Ryujinx.Core/OsHle/Services/Nifm/IRequest.cs
index 6110e5fb..1e1f13e6 100644
--- a/Ryujinx.Core/OsHle/Services/Nifm/IRequest.cs
+++ b/Ryujinx.Core/OsHle/Services/Nifm/IRequest.cs
@@ -1,13 +1,17 @@
+using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Ipc;
+using System;
using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Nifm
{
- class IRequest : IIpcService
+ class IRequest : IpcService, IDisposable
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ private KEvent Event;
public IRequest()
{
@@ -17,9 +21,10 @@ namespace Ryujinx.Core.OsHle.IpcServices.Nifm
{ 1, GetResult },
{ 2, GetSystemEventReadableHandles }
};
+
+ Event = new KEvent();
}
- // -> i32
public long GetRequestState(ServiceCtx Context)
{
Context.ResponseData.Write(0);
@@ -39,11 +44,25 @@ namespace Ryujinx.Core.OsHle.IpcServices.Nifm
//GetSystemEventReadableHandles() -> (KObject, KObject)
public long GetSystemEventReadableHandles(ServiceCtx Context)
{
- Context.Response.HandleDesc = IpcHandleDesc.MakeMove(0xbadcafe);
+ //FIXME: Is this supposed to return 2 events?
+ int Handle = Context.Process.HandleTable.OpenHandle(Event);
- //Todo: Stub
+ Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
return 0;
}
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool Disposing)
+ {
+ if (Disposing)
+ {
+ Event.Dispose();
+ }
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Nifm/ServiceNifm.cs b/Ryujinx.Core/OsHle/Services/Nifm/ServiceNifm.cs
index 7e183389..b3602e9c 100644
--- a/Ryujinx.Core/OsHle/Services/Nifm/ServiceNifm.cs
+++ b/Ryujinx.Core/OsHle/Services/Nifm/ServiceNifm.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Nifm
{
- class ServiceNifm : IIpcService
+ class ServiceNifm : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceNifm()
{
diff --git a/Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs b/Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs
index 720baa6e..acdb92cf 100644
--- a/Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs
+++ b/Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Ns
{
- class ServiceNs : IIpcService
+ class ServiceNs : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceNs()
{
diff --git a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs
index 67ad4491..ef223772 100644
--- a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs
+++ b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs
@@ -1,4 +1,5 @@
using ChocolArm64.Memory;
+using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Ipc;
using Ryujinx.Core.OsHle.Utilities;
using Ryujinx.Graphics.Gpu;
@@ -7,20 +8,22 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.NvServices
{
- class ServiceNvDrv : IIpcService
+ class ServiceNvDrv : IpcService, IDisposable
{
private delegate long ServiceProcessIoctl(ServiceCtx Context);
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private Dictionary<(string, int), ServiceProcessIoctl> IoctlCmds;
- private IdDictionary Fds;
+ public static GlobalStateTable Fds { get; private set; }
- private IdDictionary NvMaps;
- private IdDictionary NvMapsById;
+ public static GlobalStateTable NvMaps { get; private set; }
+ public static GlobalStateTable NvMapsById { get; private set; }
+
+ private KEvent Event;
public ServiceNvDrv()
{
@@ -64,10 +67,15 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
{ ("/dev/nvmap", 0x010e), NvMapIocGetId },
};
- Fds = new IdDictionary();
+ Event = new KEvent();
+ }
- NvMaps = new IdDictionary();
- NvMapsById = new IdDictionary();
+ static ServiceNvDrv()
+ {
+ Fds = new GlobalStateTable();
+
+ NvMaps = new GlobalStateTable();
+ NvMapsById = new GlobalStateTable();
}
public long Open(ServiceCtx Context)
@@ -76,7 +84,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
string Name = AMemoryHelper.ReadAsciiString(Context.Memory, NamePtr);
- int Fd = Fds.Add(new NvFd(Name));
+ int Fd = Fds.Add(Context.Process, new NvFd(Name));
Context.ResponseData.Write(Fd);
Context.ResponseData.Write(0);
@@ -89,7 +97,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
int Fd = Context.RequestData.ReadInt32();
int Cmd = Context.RequestData.ReadInt32() & 0xffff;
- NvFd FdData = Fds.GetData<NvFd>(Fd);
+ NvFd FdData = Fds.GetData<NvFd>(Context.Process, Fd);
long Position = Context.Request.GetSendBuffPtr();
@@ -109,7 +117,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
{
int Fd = Context.RequestData.ReadInt32();
- Fds.Delete(Fd);
+ Fds.Delete(Context.Process, Fd);
Context.ResponseData.Write(0);
@@ -131,7 +139,10 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
int Fd = Context.RequestData.ReadInt32();
int EventId = Context.RequestData.ReadInt32();
- Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(0xcafe);
+ //TODO: Use Fd/EventId, different channels have different events.
+ int Handle = Context.Process.HandleTable.OpenHandle(Event);
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
Context.ResponseData.Write(0);
@@ -203,7 +214,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
return 0;
}
- NvMap Map = NvMaps.GetData<NvMap>(Handle);
+ NvMap Map = NvMaps.GetData<NvMap>(Context.Process, Handle);
if (Map == null)
{
@@ -550,9 +561,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
NvMap Map = new NvMap() { Size = Size };
- Map.Handle = NvMaps.Add(Map);
+ Map.Handle = NvMaps.Add(Context.Process, Map);
- Map.Id = NvMapsById.Add(Map);
+ Map.Id = NvMapsById.Add(Context.Process, Map);
Context.Memory.WriteInt32(Position + 4, Map.Handle);
@@ -567,7 +578,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
int Id = Context.Memory.ReadInt32(Position);
- NvMap Map = NvMapsById.GetData<NvMap>(Id);
+ NvMap Map = NvMapsById.GetData<NvMap>(Context.Process, Id);
if (Map == null)
{
@@ -594,7 +605,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
byte Kind = (byte)Reader.ReadInt64();
long Addr = Reader.ReadInt64();
- NvMap Map = NvMaps.GetData<NvMap>(Handle);
+ NvMap Map = NvMaps.GetData<NvMap>(Context.Process, Handle);
if (Map == null)
{
@@ -620,7 +631,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
int Handle = Reader.ReadInt32();
int Padding = Reader.ReadInt32();
- NvMap Map = NvMaps.GetData<NvMap>(Handle);
+ NvMap Map = NvMaps.GetData<NvMap>(Context.Process, Handle);
if (Map == null)
{
@@ -645,7 +656,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
int Handle = Reader.ReadInt32();
int Param = Reader.ReadInt32();
- NvMap Map = NvMaps.GetData<NvMap>(Handle);
+ NvMap Map = NvMaps.GetData<NvMap>(Context.Process, Handle);
if (Map == null)
{
@@ -675,7 +686,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
int Handle = Context.Memory.ReadInt32(Position + 4);
- NvMap Map = NvMaps.GetData<NvMap>(Handle);
+ NvMap Map = NvMaps.GetData<NvMap>(Context.Process, Handle);
if (Map == null)
{
@@ -689,9 +700,17 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
return 0;
}
- public NvMap GetNvMap(int Handle)
+ public void Dispose()
{
- return NvMaps.GetData<NvMap>(Handle);
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool Disposing)
+ {
+ if (Disposing)
+ {
+ Event.Dispose();
+ }
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ObjHelper.cs b/Ryujinx.Core/OsHle/Services/ObjHelper.cs
deleted file mode 100644
index 89d986ae..00000000
--- a/Ryujinx.Core/OsHle/Services/ObjHelper.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using Ryujinx.Core.OsHle.Handles;
-using Ryujinx.Core.OsHle.Ipc;
-
-namespace Ryujinx.Core.OsHle.IpcServices
-{
- static class ObjHelper
- {
- public static void MakeObject(ServiceCtx Context, object Obj)
- {
- if (Context.Session is HDomain Dom)
- {
- Context.Response.ResponseObjIds.Add(Dom.Add(Obj));
- }
- else
- {
- HSessionObj HndData = new HSessionObj(Context.Session, Obj);
-
- int VHandle = Context.Process.HandleTable.OpenHandle(HndData);
-
- Context.Response.HandleDesc = IpcHandleDesc.MakeMove(VHandle);
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Pctl/IParentalControlService.cs b/Ryujinx.Core/OsHle/Services/Pctl/IParentalControlService.cs
index 4eb92d31..45216864 100644
--- a/Ryujinx.Core/OsHle/Services/Pctl/IParentalControlService.cs
+++ b/Ryujinx.Core/OsHle/Services/Pctl/IParentalControlService.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Pctl
{
- class IParentalControlService : IIpcService
+ class IParentalControlService : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IParentalControlService()
{
diff --git a/Ryujinx.Core/OsHle/Services/Pctl/ServicePctl.cs b/Ryujinx.Core/OsHle/Services/Pctl/ServicePctl.cs
index 2d5e22a4..b648d184 100644
--- a/Ryujinx.Core/OsHle/Services/Pctl/ServicePctl.cs
+++ b/Ryujinx.Core/OsHle/Services/Pctl/ServicePctl.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Pctl
{
- class ServicePctl : IIpcService
+ class ServicePctl : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServicePctl()
{
diff --git a/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs b/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs
index 9a617799..55637eac 100644
--- a/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs
+++ b/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Pl
{
- class ServicePl : IIpcService
+ class ServicePl : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServicePl()
{
diff --git a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs
new file mode 100644
index 00000000..9f43cdf0
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs
@@ -0,0 +1,119 @@
+using Ryujinx.Core.OsHle.IpcServices.Acc;
+using Ryujinx.Core.OsHle.IpcServices.Am;
+using Ryujinx.Core.OsHle.IpcServices.Apm;
+using Ryujinx.Core.OsHle.IpcServices.Aud;
+using Ryujinx.Core.OsHle.IpcServices.Bsd;
+using Ryujinx.Core.OsHle.IpcServices.Friend;
+using Ryujinx.Core.OsHle.IpcServices.FspSrv;
+using Ryujinx.Core.OsHle.IpcServices.Hid;
+using Ryujinx.Core.OsHle.IpcServices.Lm;
+using Ryujinx.Core.OsHle.IpcServices.Nifm;
+using Ryujinx.Core.OsHle.IpcServices.Ns;
+using Ryujinx.Core.OsHle.IpcServices.NvServices;
+using Ryujinx.Core.OsHle.IpcServices.Pctl;
+using Ryujinx.Core.OsHle.IpcServices.Pl;
+using Ryujinx.Core.OsHle.IpcServices.Set;
+using Ryujinx.Core.OsHle.IpcServices.Sfdnsres;
+using Ryujinx.Core.OsHle.IpcServices.Sm;
+using Ryujinx.Core.OsHle.IpcServices.Ssl;
+using Ryujinx.Core.OsHle.IpcServices.Time;
+using Ryujinx.Core.OsHle.IpcServices.Vi;
+using System;
+
+namespace Ryujinx.Core.OsHle.IpcServices
+{
+ static class ServiceFactory
+ {
+ public static IpcService MakeService(string Name)
+ {
+ switch (Name)
+ {
+ case "acc:u0":
+ return new ServiceAcc();
+
+ case "aoc:u":
+ return new ServiceNs();
+
+ case "apm":
+ return new ServiceApm();
+
+ case "apm:p":
+ return new ServiceApm();
+
+ case "appletOE":
+ return new ServiceAppletOE();
+
+ case "audout:u":
+ return new ServiceAudOut();
+
+ case "audren:u":
+ return new ServiceAudRen();
+
+ case "bsd:s":
+ return new ServiceBsd();
+
+ case "bsd:u":
+ return new ServiceBsd();
+
+ case "friend:a":
+ return new ServiceFriend();
+
+ case "fsp-srv":
+ return new ServiceFspSrv();
+
+ case "hid":
+ return new ServiceHid();
+
+ case "lm":
+ return new ServiceLm();
+
+ case "nifm:u":
+ return new ServiceNifm();
+
+ case "nvdrv":
+ return new ServiceNvDrv();
+
+ case "nvdrv:a":
+ return new ServiceNvDrv();
+
+ case "pctl:a":
+ return new ServicePctl();
+
+ case "pl:u":
+ return new ServicePl();
+
+ case "set":
+ return new ServiceSet();
+
+ case "set:sys":
+ return new ServiceSetSys();
+
+ case "sfdnsres":
+ return new ServiceSfdnsres();
+
+ case "sm:":
+ return new ServiceSm();
+
+ case "ssl":
+ return new ServiceSsl();
+
+ case "time:s":
+ return new ServiceTime();
+
+ case "time:u":
+ return new ServiceTime();
+
+ case "vi:m":
+ return new ServiceVi();
+
+ case "vi:s":
+ return new ServiceVi();
+
+ case "vi:u":
+ return new ServiceVi();
+ }
+
+ throw new NotImplementedException(Name);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs b/Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs
index c60e1712..55824357 100644
--- a/Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs
+++ b/Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs
@@ -5,11 +5,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Set
{
- class ServiceSet : IIpcService
+ class ServiceSet : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceSet()
{
diff --git a/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs b/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs
index dee6573d..1d6afc4f 100644
--- a/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs
+++ b/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Set
{
- class ServiceSetSys : IIpcService
+ class ServiceSetSys : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceSetSys()
{
diff --git a/Ryujinx.Core/OsHle/Services/Sfdnsres/ServiceSfdnsres.cs b/Ryujinx.Core/OsHle/Services/Sfdnsres/ServiceSfdnsres.cs
index f110ae73..1f68558e 100644
--- a/Ryujinx.Core/OsHle/Services/Sfdnsres/ServiceSfdnsres.cs
+++ b/Ryujinx.Core/OsHle/Services/Sfdnsres/ServiceSfdnsres.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Sfdnsres
{
- class ServiceSfdnsres : IIpcService
+ class ServiceSfdnsres : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceSfdnsres()
{
diff --git a/Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs b/Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs
index cb745e37..770227d5 100644
--- a/Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs
+++ b/Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs
@@ -4,11 +4,13 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Sm
{
- class ServiceSm : IIpcService
+ class ServiceSm : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ private bool IsInitialized;
public ServiceSm()
{
@@ -23,7 +25,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Sm
public long Initialize(ServiceCtx Context)
{
- Context.Session.Initialize();
+ IsInitialized = true;
return 0;
}
@@ -31,7 +33,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Sm
public long GetService(ServiceCtx Context)
{
//Only for kernel version > 3.0.0.
- if (!Context.Session.IsInitialized)
+ if (!IsInitialized)
{
//return SmNotInitialized;
}
@@ -55,7 +57,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Sm
return 0;
}
- HSession Session = new HSession(Context.Process.Services.GetService(Name));
+ KSession Session = new KSession(ServiceFactory.MakeService(Name));
int Handle = Context.Process.HandleTable.OpenHandle(Session);
diff --git a/Ryujinx.Core/OsHle/Services/Ssl/ServiceSsl.cs b/Ryujinx.Core/OsHle/Services/Ssl/ServiceSsl.cs
index 23934b14..b9513a86 100644
--- a/Ryujinx.Core/OsHle/Services/Ssl/ServiceSsl.cs
+++ b/Ryujinx.Core/OsHle/Services/Ssl/ServiceSsl.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Ssl
{
- class ServiceSsl : IIpcService
+ class ServiceSsl : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceSsl()
{
diff --git a/Ryujinx.Core/OsHle/Services/Time/ISteadyClock.cs b/Ryujinx.Core/OsHle/Services/Time/ISteadyClock.cs
index d20e4378..91d78664 100644
--- a/Ryujinx.Core/OsHle/Services/Time/ISteadyClock.cs
+++ b/Ryujinx.Core/OsHle/Services/Time/ISteadyClock.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Time
{
- class ISteadyClock : IIpcService
+ class ISteadyClock : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ISteadyClock()
{
diff --git a/Ryujinx.Core/OsHle/Services/Time/ISystemClock.cs b/Ryujinx.Core/OsHle/Services/Time/ISystemClock.cs
index 4d4493da..f7f710c8 100644
--- a/Ryujinx.Core/OsHle/Services/Time/ISystemClock.cs
+++ b/Ryujinx.Core/OsHle/Services/Time/ISystemClock.cs
@@ -4,11 +4,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Time
{
- class ISystemClock : IIpcService
+ class ISystemClock : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
diff --git a/Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs b/Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs
index d220824c..63329ada 100644
--- a/Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs
+++ b/Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs
@@ -4,11 +4,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Time
{
- class ITimeZoneService : IIpcService
+ class ITimeZoneService : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
diff --git a/Ryujinx.Core/OsHle/Services/Time/ServiceTime.cs b/Ryujinx.Core/OsHle/Services/Time/ServiceTime.cs
index 43f28bb8..1f947939 100644
--- a/Ryujinx.Core/OsHle/Services/Time/ServiceTime.cs
+++ b/Ryujinx.Core/OsHle/Services/Time/ServiceTime.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Time
{
- class ServiceTime : IIpcService
+ class ServiceTime : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceTime()
{
diff --git a/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs
index 0ff1f909..62db23b4 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs
@@ -1,19 +1,17 @@
using ChocolArm64.Memory;
-using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
using System.IO;
using static Ryujinx.Core.OsHle.IpcServices.Android.Parcel;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
namespace Ryujinx.Core.OsHle.IpcServices.Vi
{
- class IApplicationDisplayService : IIpcService
+ class IApplicationDisplayService : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
private IdDictionary Displays;
@@ -145,7 +143,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
{
string Name = GetDisplayName(Context);
- int Handle = Context.Process.HandleTable.OpenHandle(new HEvent());
+ int Handle = Context.Process.HandleTable.OpenHandle(Context.Ns.Os.VsyncEvent);
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs
index beccbe7d..4c342006 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs
@@ -1,4 +1,5 @@
using ChocolArm64.Memory;
+using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Ipc;
using Ryujinx.Core.OsHle.IpcServices.Android;
using Ryujinx.Graphics.Gal;
@@ -7,11 +8,13 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Vi
{
- class IHOSBinderDriver : IIpcService, IDisposable
+ class IHOSBinderDriver : IpcService, IDisposable
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ private KEvent ReleaseEvent;
private NvFlinger Flinger;
@@ -24,7 +27,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
{ 2, GetNativeHandle }
};
- Flinger = new NvFlinger(Renderer);
+ ReleaseEvent = new KEvent();
+
+ Flinger = new NvFlinger(Renderer, ReleaseEvent);
}
public long TransactParcel(ServiceCtx Context)
@@ -56,7 +61,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
int Id = Context.RequestData.ReadInt32();
uint Unk = Context.RequestData.ReadUInt32();
- Context.Response.HandleDesc = IpcHandleDesc.MakeMove(0xbadcafe);
+ int Handle = Context.Process.HandleTable.OpenHandle(ReleaseEvent);
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
return 0;
}
@@ -70,6 +77,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
{
if (Disposing)
{
+ ReleaseEvent.Dispose();
+
Flinger.Dispose();
}
}
diff --git a/Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs
index 69dbff47..6c7f36ff 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Vi
{
- class IManagerDisplayService : IIpcService
+ class IManagerDisplayService : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public IManagerDisplayService()
{
diff --git a/Ryujinx.Core/OsHle/Services/Vi/ISystemDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/ISystemDisplayService.cs
index d87fcbf6..814ed7d1 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/ISystemDisplayService.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/ISystemDisplayService.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Ryujinx.Core.OsHle.IpcServices.Vi
{
- class ISystemDisplayService : IIpcService
+ class ISystemDisplayService : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ISystemDisplayService()
{
diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
index 5309dcab..3a7a2ee6 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
@@ -1,4 +1,5 @@
using ChocolArm64.Memory;
+using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.IpcServices.NvServices;
using Ryujinx.Graphics.Gal;
using System;
@@ -17,6 +18,10 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
private Dictionary<(string, int), ServiceProcessParcel> Commands;
+ private KEvent ReleaseEvent;
+
+ private IGalRenderer Renderer;
+
private const int BufferQueueCount = 0x40;
private const int BufferQueueMask = BufferQueueCount - 1;
@@ -55,8 +60,6 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
public GbpBuffer Data;
}
- private IGalRenderer Renderer;
-
private BufferEntry[] BufferQueue;
private ManualResetEvent WaitBufferFree;
@@ -69,7 +72,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
private bool KeepRunning;
- public NvFlinger(IGalRenderer Renderer)
+ public NvFlinger(IGalRenderer Renderer, KEvent ReleaseEvent)
{
Commands = new Dictionary<(string, int), ServiceProcessParcel>()
{
@@ -83,8 +86,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
{ ("android.gui.IGraphicBufferProducer", 0xb), GbpDisconnect },
{ ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer }
};
-
- this.Renderer = Renderer;
+
+ this.Renderer = Renderer;
+ this.ReleaseEvent = ReleaseEvent;
BufferQueue = new BufferEntry[0x40];
@@ -293,6 +297,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
BufferQueue[Slot].State = BufferState.Free;
+ ReleaseEvent.Handle.Set();
+
WaitBufferFree.Set();
return;
@@ -377,6 +383,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
Interlocked.Decrement(ref RenderQueueCount);
+ ReleaseEvent.Handle.Set();
+
lock (WaitBufferFree)
{
WaitBufferFree.Set();
@@ -397,9 +405,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
NvMapHandle = BitConverter.ToInt32(RawValue, 0);
}
- ServiceNvDrv NvDrv = (ServiceNvDrv)Context.Process.Services.GetService("nvdrv");
-
- return NvDrv.GetNvMap(NvMapHandle);
+ return ServiceNvDrv.NvMaps.GetData<NvMap>(Context.Process, NvMapHandle);
}
private int GetFreeSlotBlocking(int Width, int Height)
diff --git a/Ryujinx.Core/OsHle/Services/Vi/ServiceVi.cs b/Ryujinx.Core/OsHle/Services/Vi/ServiceVi.cs
index 2c3dd2a3..360cb6fa 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/ServiceVi.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/ServiceVi.cs
@@ -1,15 +1,13 @@
using Ryujinx.Core.OsHle.Ipc;
using System.Collections.Generic;
-using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
-
namespace Ryujinx.Core.OsHle.IpcServices.Vi
{
- class ServiceVi : IIpcService
+ class ServiceVi : IpcService
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
- public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
public ServiceVi()
{
diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs
index 9417473c..96bef5e4 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs
+++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs
@@ -3,6 +3,7 @@ using ChocolArm64.State;
using Ryujinx.Core.OsHle.Exceptions;
using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Ipc;
+using Ryujinx.Core.OsHle.IpcServices;
using System;
using System.Threading;
@@ -34,7 +35,28 @@ namespace Ryujinx.Core.OsHle.Svc
{
int Handle = (int)ThreadState.X0;
- Process.HandleTable.CloseHandle(Handle);
+ object Obj = Process.HandleTable.CloseHandle(Handle);
+
+ if (Obj == null)
+ {
+ Logging.Warn($"Tried to CloseHandle on invalid handle 0x{Handle:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+
+ return;
+ }
+
+ if (Obj is KSession Session)
+ {
+ Session.Dispose();
+ }
+ else if (Obj is HTransferMem TMem)
+ {
+ TMem.Memory.Manager.Reprotect(
+ TMem.Position,
+ TMem.Size,
+ TMem.Perm);
+ }
ThreadState.X0 = 0;
}
@@ -43,25 +65,78 @@ namespace Ryujinx.Core.OsHle.Svc
{
int Handle = (int)ThreadState.X0;
- //TODO: Implement events.
+ KEvent Event = Process.HandleTable.GetData<KEvent>(Handle);
- ThreadState.X0 = 0;
+ if (Event != null)
+ {
+ Event.Handle.Reset();
+
+ ThreadState.X0 = 0;
+ }
+ else
+ {
+ Logging.Warn($"Tried to ResetSignal on invalid event handle 0x{Handle:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+ }
}
private void SvcWaitSynchronization(AThreadState ThreadState)
{
- long HandlesPtr = (long)ThreadState.X0;
+ long HandlesPtr = (long)ThreadState.X1;
int HandlesCount = (int)ThreadState.X2;
long Timeout = (long)ThreadState.X3;
- //TODO: Implement events.
+ KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
- HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
+ WaitHandle[] Handles = new WaitHandle[HandlesCount];
+
+ for (int Index = 0; Index < HandlesCount; Index++)
+ {
+ int Handle = Memory.ReadInt32(HandlesPtr + Index * 4);
+
+ KSynchronizationObject SyncObj = Process.HandleTable.GetData<KSynchronizationObject>(Handle);
+
+ if (SyncObj == null)
+ {
+ Logging.Warn($"Tried to WaitSynchronization on invalid handle 0x{Handle:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+
+ return;
+ }
+
+ Handles[Index] = SyncObj.Handle;
+ }
Process.Scheduler.Suspend(CurrThread.ProcessorId);
+
+ int HandleIndex;
+
+ ulong Result = 0;
+
+ if (Timeout != -1)
+ {
+ HandleIndex = WaitHandle.WaitAny(Handles, (int)(Timeout / 1000000));
+
+ if (HandleIndex == WaitHandle.WaitTimeout)
+ {
+ Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
+ }
+ }
+ else
+ {
+ HandleIndex = WaitHandle.WaitAny(Handles);
+ }
+
Process.Scheduler.Resume(CurrThread);
- ThreadState.X0 = 0;
+ ThreadState.X0 = Result;
+
+ if (Result == 0)
+ {
+ ThreadState.X1 = (ulong)HandleIndex;
+ }
}
private void SvcGetSystemTick(AThreadState ThreadState)
@@ -78,8 +153,7 @@ namespace Ryujinx.Core.OsHle.Svc
//TODO: Validate that app has perms to access the service, and that the service
//actually exists, return error codes otherwise.
-
- HSession Session = new HSession(Process.Services.GetService(Name));
+ KSession Session = new KSession(ServiceFactory.MakeService(Name));
ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session);
@@ -89,65 +163,46 @@ namespace Ryujinx.Core.OsHle.Svc
private void SvcSendSyncRequest(AThreadState ThreadState)
{
- SendSyncRequest(ThreadState, false);
+ SendSyncRequest(ThreadState, ThreadState.Tpidr, 0x100, (int)ThreadState.X0);
}
private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState)
{
- SendSyncRequest(ThreadState, true);
+ SendSyncRequest(
+ ThreadState,
+ (long)ThreadState.X0,
+ (long)ThreadState.X1,
+ (int)ThreadState.X2);
}
- private void SendSyncRequest(AThreadState ThreadState, bool UserBuffer)
+ private void SendSyncRequest(AThreadState ThreadState, long CmdPtr, long Size, int Handle)
{
- long CmdPtr = ThreadState.Tpidr;
- long Size = 0x100;
- int Handle = 0;
+ KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
- if (UserBuffer)
- {
- CmdPtr = (long)ThreadState.X0;
- Size = (long)ThreadState.X1;
- Handle = (int)ThreadState.X2;
- }
- else
- {
- Handle = (int)ThreadState.X0;
- }
+ byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
- HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
+ KSession Session = Process.HandleTable.GetData<KSession>(Handle);
- Process.Scheduler.Suspend(CurrThread.ProcessorId);
+ if (Session != null)
+ {
+ Process.Scheduler.Suspend(CurrThread.ProcessorId);
- byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
+ IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
- HSession Session = Process.HandleTable.GetData<HSession>(Handle);
+ IpcHandler.IpcCall(Ns, Process, Memory, Session, Cmd, CmdPtr);
- IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr, Session is HDomain);
+ Thread.Yield();
- if (Session != null)
- {
- IpcHandler.IpcCall(
- Ns,
- Process,
- Memory,
- Session,
- Cmd,
- ThreadState.ThreadId,
- CmdPtr,
- Handle);
-
- byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
+ Process.Scheduler.Resume(CurrThread);
ThreadState.X0 = 0;
}
else
{
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidIpcReq);
- }
+ Logging.Warn($"Tried to SendSyncRequest on invalid session handle 0x{Handle:x8}!");
- Thread.Yield();
-
- Process.Scheduler.Resume(CurrThread);
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+ }
}
private void SvcBreak(AThreadState ThreadState)
diff --git a/Ryujinx.Core/OsHle/Svc/SvcThread.cs b/Ryujinx.Core/OsHle/Svc/SvcThread.cs
index 231ee2a2..77cef44c 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcThread.cs
+++ b/Ryujinx.Core/OsHle/Svc/SvcThread.cs
@@ -39,7 +39,7 @@ namespace Ryujinx.Core.OsHle.Svc
{
int Handle = (int)ThreadState.X0;
- HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
+ KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
if (Thread != null)
{
@@ -53,16 +53,18 @@ namespace Ryujinx.Core.OsHle.Svc
private void SvcExitThread(AThreadState ThreadState)
{
- HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
-
+ KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
+
CurrThread.Thread.StopExecution();
+
+ CurrThread.Handle.Set();
}
private void SvcSleepThread(AThreadState ThreadState)
{
ulong NanoSecs = ThreadState.X0;
- HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
+ KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
if (NanoSecs == 0)
{
@@ -78,7 +80,7 @@ namespace Ryujinx.Core.OsHle.Svc
{
int Handle = (int)ThreadState.X1;
- HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
+ KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
if (Thread != null)
{
@@ -91,10 +93,10 @@ namespace Ryujinx.Core.OsHle.Svc
private void SvcSetThreadPriority(AThreadState ThreadState)
{
+ int Prio = (int)ThreadState.X0;
int Handle = (int)ThreadState.X1;
- int Prio = (int)ThreadState.X0;
- HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
+ KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
if (Thread != null)
{
@@ -117,7 +119,7 @@ namespace Ryujinx.Core.OsHle.Svc
{
int Handle = (int)ThreadState.X0;
- HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
+ KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
if (Thread != null)
{
diff --git a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
index 38356073..318688b8 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
+++ b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
@@ -13,7 +13,7 @@ namespace Ryujinx.Core.OsHle.Svc
long MutexAddress = (long)ThreadState.X1;
int RequestingThreadHandle = (int)ThreadState.X2;
- HThread RequestingThread = Process.HandleTable.GetData<HThread>(RequestingThreadHandle);
+ KThread RequestingThread = Process.HandleTable.GetData<KThread>(RequestingThreadHandle);
Mutex M = new Mutex(Process, MutexAddress, OwnerThreadHandle);
@@ -43,7 +43,7 @@ namespace Ryujinx.Core.OsHle.Svc
int ThreadHandle = (int)ThreadState.X2;
long Timeout = (long)ThreadState.X3;
- HThread Thread = Process.HandleTable.GetData<HThread>(ThreadHandle);
+ KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle);
Mutex M = new Mutex(Process, MutexAddress, ThreadHandle);
@@ -72,7 +72,7 @@ namespace Ryujinx.Core.OsHle.Svc
long CondVarAddress = (long)ThreadState.X0;
int Count = (int)ThreadState.X1;
- HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
+ KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
if (Ns.Os.CondVars.TryGetValue(CondVarAddress, out CondVar Cv))
{
diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs
index 92d78f45..0df8b126 100644
--- a/Ryujinx.Core/Switch.cs
+++ b/Ryujinx.Core/Switch.cs
@@ -14,10 +14,10 @@ namespace Ryujinx.Core
internal NsGpu Gpu { get; private set; }
- internal Horizon Os { get; private set; }
-
internal VirtualFileSystem VFs { get; private set; }
+ public Horizon Os { get; private set; }
+
public SystemSettings Settings { get; private set; }
public PerformanceStatistics Statistics { get; private set; }
@@ -40,12 +40,12 @@ namespace Ryujinx.Core
this.AudioOut = AudioOut;
- Gpu = new NsGpu(Renderer);
-
- Os = new Horizon(this);
+ Gpu = new NsGpu(Renderer);
VFs = new VirtualFileSystem();
+ Os = new Horizon(this);
+
Settings = new SystemSettings();
Statistics = new PerformanceStatistics();
diff --git a/Ryujinx.Graphics/Gpu/NsGpuPGraph.cs b/Ryujinx.Graphics/Gpu/NsGpuPGraph.cs
index 6543b1d1..652f3e75 100644
--- a/Ryujinx.Graphics/Gpu/NsGpuPGraph.cs
+++ b/Ryujinx.Graphics/Gpu/NsGpuPGraph.cs
@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gpu
{
private NsGpu Gpu;
- private int[] Registers;
+ private uint[] Registers;
public NsGpuEngine[] SubChannels;
@@ -18,7 +18,7 @@ namespace Ryujinx.Graphics.Gpu
{
this.Gpu = Gpu;
- Registers = new int[0x1000];
+ Registers = new uint[0x1000];
SubChannels = new NsGpuEngine[8];
@@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Gpu
{
if (Entry.Arguments.Count == 1)
{
- SetRegister(Entry.Register, Entry.Arguments[0]);
+ SetRegister(Entry.Register, (uint)Entry.Arguments[0]);
}
switch (Entry.Register)
@@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Gpu
case NsGpuRegister._3dVertexArray0Fetch:
SendVertexBuffers(Memory);
break;
-
+
case NsGpuRegister._3dCbData0:
if (GetRegister(NsGpuRegister._3dCbPos) == 0x20)
{
@@ -62,6 +62,22 @@ namespace Ryujinx.Graphics.Gpu
case NsGpuRegister._3dQueryGet:
HasQuery = true;
break;
+
+ case NsGpuRegister._3dSetShader:
+ uint ShaderPrg = (uint)Entry.Arguments[0];
+ uint ShaderId = (uint)Entry.Arguments[1];
+ uint CodeAddr = (uint)Entry.Arguments[2];
+ uint ShaderType = (uint)Entry.Arguments[3];
+ uint CodeEnd = (uint)Entry.Arguments[4];
+
+ SendShader(
+ Memory,
+ ShaderPrg,
+ ShaderId,
+ CodeAddr,
+ ShaderType,
+ CodeEnd);
+ break;
}
}
@@ -71,10 +87,10 @@ namespace Ryujinx.Graphics.Gpu
(long)GetRegister(NsGpuRegister._3dQueryAddressHigh) << 32 |
(long)GetRegister(NsGpuRegister._3dQueryAddressLow) << 0;
- int Seq = GetRegister(NsGpuRegister._3dQuerySequence);
- int Get = GetRegister(NsGpuRegister._3dQueryGet);
+ uint Seq = GetRegister(NsGpuRegister._3dQuerySequence);
+ uint Get = GetRegister(NsGpuRegister._3dQueryGet);
- int Mode = Get & 3;
+ uint Mode = Get & 3;
if (Mode == 0)
{
@@ -85,7 +101,7 @@ namespace Ryujinx.Graphics.Gpu
{
Gpu.Renderer.QueueAction(delegate()
{
- Memory.WriteInt32(Position, Seq);
+ Memory.WriteUInt32(Position, Seq);
});
}
}
@@ -119,13 +135,13 @@ namespace Ryujinx.Graphics.Gpu
{
byte[] Buffer = AMemoryHelper.ReadBytes(Memory, Position, Size);
- int Stride = GetRegister(NsGpuRegister._3dVertexArray0Fetch) & 0xfff;
+ int Stride = (int)GetRegister(NsGpuRegister._3dVertexArray0Fetch) & 0xfff;
List<GalVertexAttrib> Attribs = new List<GalVertexAttrib>();
for (int Attr = 0; Attr < 16; Attr++)
{
- int Packed = GetRegister(NsGpuRegister._3dVertexAttrib0Format + Attr * 4);
+ int Packed = (int)GetRegister(NsGpuRegister._3dVertexAttrib0Format + Attr * 4);
GalVertexAttrib Attrib = new GalVertexAttrib(Attr,
(Packed >> 0) & 0x1f,
@@ -154,10 +170,10 @@ namespace Ryujinx.Graphics.Gpu
long TicPos = (long)GetRegister(NsGpuRegister._3dTicAddressHigh) << 32 |
(long)GetRegister(NsGpuRegister._3dTicAddressLow) << 0;
- int CbData = GetRegister(NsGpuRegister._3dCbData0);
+ uint CbData = GetRegister(NsGpuRegister._3dCbData0);
- int TicIndex = (CbData >> 0) & 0xfffff;
- int TscIndex = (CbData >> 20) & 0xfff; //I guess?
+ uint TicIndex = (CbData >> 0) & 0xfffff;
+ uint TscIndex = (CbData >> 20) & 0xfff; //I guess?
TicPos = Gpu.MemoryMgr.GetCpuAddr(TicPos + TicIndex * 0x20);
@@ -198,6 +214,19 @@ namespace Ryujinx.Graphics.Gpu
}
}
+ private void SendShader(
+ AMemory Memory,
+ uint ShaderPrg,
+ uint ShaderId,
+ uint CodeAddr,
+ uint ShaderType,
+ uint CodeEnd)
+ {
+ long CodePos = Gpu.MemoryMgr.GetCpuAddr(CodeAddr);
+
+ byte[] Data = AMemoryHelper.ReadBytes(Memory, CodePos, 0x300);
+ }
+
private static byte[] GetDecodedTexture(
AMemory Memory,
NsGpuTextureFormat Format,
@@ -263,12 +292,12 @@ namespace Ryujinx.Graphics.Gpu
return Data;
}
- public int GetRegister(NsGpuRegister Register)
+ public uint GetRegister(NsGpuRegister Register)
{
return Registers[((int)Register >> 2) & 0xfff];
}
- public void SetRegister(NsGpuRegister Register, int Value)
+ public void SetRegister(NsGpuRegister Register, uint Value)
{
Registers[((int)Register >> 2) & 0xfff] = Value;
}
diff --git a/Ryujinx.Graphics/Gpu/NsGpuRegister.cs b/Ryujinx.Graphics/Gpu/NsGpuRegister.cs
index 319e2c01..4642e68d 100644
--- a/Ryujinx.Graphics/Gpu/NsGpuRegister.cs
+++ b/Ryujinx.Graphics/Gpu/NsGpuRegister.cs
@@ -89,5 +89,6 @@ namespace Ryujinx.Graphics.Gpu
_3dCbData13 = 0x23c4,
_3dCbData14 = 0x23c8,
_3dCbData15 = 0x23cc,
+ _3dSetShader = 0x3890
}
} \ No newline at end of file
diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs
index b0dca81b..3bcef921 100644
--- a/Ryujinx/Ui/GLScreen.cs
+++ b/Ryujinx/Ui/GLScreen.cs
@@ -181,6 +181,8 @@ namespace Ryujinx
SwapBuffers();
Ns.Statistics.EndSystemFrame();
+
+ Ns.Os.SignalVsync();
}
protected override void OnResize(EventArgs e)