mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2024-12-22 23:25:46 +00:00
[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
This commit is contained in:
parent
4940cf0ea5
commit
4314a8f3e5
101 changed files with 1120 additions and 836 deletions
|
@ -2,7 +2,11 @@ namespace Ryujinx.Audio
|
||||||
{
|
{
|
||||||
public interface IAalOutput
|
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);
|
void CloseTrack(int Track);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using OpenTK.Audio.OpenAL;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.OpenAL
|
namespace Ryujinx.Audio.OpenAL
|
||||||
{
|
{
|
||||||
|
@ -22,20 +23,27 @@ namespace Ryujinx.Audio.OpenAL
|
||||||
|
|
||||||
public ALFormat Format { get; private set; }
|
public ALFormat Format { get; private set; }
|
||||||
|
|
||||||
|
private ReleaseCallback Callback;
|
||||||
|
|
||||||
public PlaybackState State { get; set; }
|
public PlaybackState State { get; set; }
|
||||||
|
|
||||||
|
private bool ShouldCallReleaseCallback;
|
||||||
|
|
||||||
private ConcurrentDictionary<long, int> Buffers;
|
private ConcurrentDictionary<long, int> Buffers;
|
||||||
|
|
||||||
private Queue<long> QueuedTagsQueue;
|
private Queue<long> QueuedTagsQueue;
|
||||||
|
|
||||||
private Queue<long> ReleasedTagsQueue;
|
private Queue<long> ReleasedTagsQueue;
|
||||||
|
|
||||||
|
private int LastReleasedCount;
|
||||||
|
|
||||||
private bool Disposed;
|
private bool Disposed;
|
||||||
|
|
||||||
public Track(int SampleRate, ALFormat Format)
|
public Track(int SampleRate, ALFormat Format, ReleaseCallback Callback)
|
||||||
{
|
{
|
||||||
this.SampleRate = SampleRate;
|
this.SampleRate = SampleRate;
|
||||||
this.Format = Format;
|
this.Format = Format;
|
||||||
|
this.Callback = Callback;
|
||||||
|
|
||||||
State = PlaybackState.Stopped;
|
State = PlaybackState.Stopped;
|
||||||
|
|
||||||
|
@ -109,11 +117,42 @@ namespace Ryujinx.Audio.OpenAL
|
||||||
|
|
||||||
AL.GetSource(SourceId, ALGetSourcei.BuffersProcessed, out int ReleasedCount);
|
AL.GetSource(SourceId, ALGetSourcei.BuffersProcessed, out int ReleasedCount);
|
||||||
|
|
||||||
|
CheckReleaseChanges(ReleasedCount);
|
||||||
|
|
||||||
if (ReleasedCount > 0)
|
if (ReleasedCount > 0)
|
||||||
{
|
{
|
||||||
AL.SourceUnqueueBuffers(SourceId, ReleasedCount);
|
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()
|
private void SyncQueuedTags()
|
||||||
{
|
{
|
||||||
|
@ -156,18 +195,46 @@ namespace Ryujinx.Audio.OpenAL
|
||||||
|
|
||||||
private ConcurrentDictionary<int, Track> Tracks;
|
private ConcurrentDictionary<int, Track> Tracks;
|
||||||
|
|
||||||
|
private Thread AudioPollerThread;
|
||||||
|
|
||||||
|
private bool KeepPolling;
|
||||||
|
|
||||||
public OpenALAudioOut()
|
public OpenALAudioOut()
|
||||||
{
|
{
|
||||||
Context = new AudioContext();
|
Context = new AudioContext();
|
||||||
|
|
||||||
Tracks = new ConcurrentDictionary<int, Track>();
|
Tracks = new ConcurrentDictionary<int, Track>();
|
||||||
|
|
||||||
|
KeepPolling = true;
|
||||||
|
|
||||||
|
AudioPollerThread = new Thread(AudioPollerWork);
|
||||||
|
|
||||||
|
AudioPollerThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int OpenTrack(int SampleRate, int Channels, out AudioFormat Format)
|
private void AudioPollerWork()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
foreach (Track Td in Tracks.Values)
|
||||||
|
{
|
||||||
|
Td.CallReleaseCallbackIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Yield();
|
||||||
|
}
|
||||||
|
while (KeepPolling);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int OpenTrack(
|
||||||
|
int SampleRate,
|
||||||
|
int Channels,
|
||||||
|
ReleaseCallback Callback,
|
||||||
|
out AudioFormat Format)
|
||||||
{
|
{
|
||||||
Format = AudioFormat.PcmInt16;
|
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++)
|
for (int Id = 0; Id < MaxTracks; Id++)
|
||||||
{
|
{
|
||||||
|
@ -292,5 +359,7 @@ namespace Ryujinx.Audio.OpenAL
|
||||||
|
|
||||||
return PlaybackState.Stopped;
|
return PlaybackState.Stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
4
Ryujinx.Audio/ReleaseCallback.cs
Normal file
4
Ryujinx.Audio/ReleaseCallback.cs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
namespace Ryujinx.Audio
|
||||||
|
{
|
||||||
|
public delegate void ReleaseCallback();
|
||||||
|
}
|
62
Ryujinx.Core/OsHle/AppletStateMgr.cs
Normal file
62
Ryujinx.Core/OsHle/AppletStateMgr.cs
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
private bool OwnsCondVarValue;
|
private bool OwnsCondVarValue;
|
||||||
|
|
||||||
private List<HThread> WaitingThreads;
|
private List<KThread> WaitingThreads;
|
||||||
|
|
||||||
public CondVar(Process Process, long CondVarAddress, long Timeout)
|
public CondVar(Process Process, long CondVarAddress, long Timeout)
|
||||||
{
|
{
|
||||||
|
@ -21,10 +21,10 @@ namespace Ryujinx.Core.OsHle
|
||||||
this.CondVarAddress = CondVarAddress;
|
this.CondVarAddress = CondVarAddress;
|
||||||
this.Timeout = Timeout;
|
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);
|
int Count = Process.Memory.ReadInt32(CondVarAddress);
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSignal(HThread Thread, int Count)
|
public void SetSignal(KThread Thread, int Count)
|
||||||
{
|
{
|
||||||
lock (WaitingThreads)
|
lock (WaitingThreads)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
namespace Ryujinx.Core.OsHle
|
|
||||||
{
|
|
||||||
class FileDesc
|
|
||||||
{
|
|
||||||
public string Name { get; private set; }
|
|
||||||
|
|
||||||
public FileDesc(string Name)
|
|
||||||
{
|
|
||||||
this.Name = Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
62
Ryujinx.Core/OsHle/GlobalStateTable.cs
Normal file
62
Ryujinx.Core/OsHle/GlobalStateTable.cs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
namespace Ryujinx.Core.OsHle.Handles
|
|
||||||
{
|
|
||||||
class HEvent
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
4
Ryujinx.Core/OsHle/Handles/KEvent.cs
Normal file
4
Ryujinx.Core/OsHle/Handles/KEvent.cs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
{
|
||||||
|
class KEvent : KSynchronizationObject { }
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.Handles
|
namespace Ryujinx.Core.OsHle.Handles
|
||||||
{
|
{
|
||||||
class KProcessHandleTable : IDisposable
|
class KProcessHandleTable
|
||||||
{
|
{
|
||||||
private IdDictionary Handles;
|
private IdDictionary Handles;
|
||||||
|
|
||||||
|
@ -21,43 +21,14 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
return Handles.GetData<T>(Handle);
|
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);
|
return Handles.Delete(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public ICollection<object> Clear()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
return Handles.Clear();
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool Disposing)
|
|
||||||
{
|
|
||||||
if (Disposing)
|
|
||||||
{
|
|
||||||
foreach (object Obj in Handles)
|
|
||||||
{
|
|
||||||
if (Obj is IDisposable DisposableObj)
|
|
||||||
{
|
|
||||||
DisposableObj.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,15 +5,15 @@ using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.Handles
|
namespace Ryujinx.Core.OsHle.Handles
|
||||||
{
|
{
|
||||||
public class KProcessScheduler : IDisposable
|
class KProcessScheduler : IDisposable
|
||||||
{
|
{
|
||||||
private class SchedulerThread : IDisposable
|
private class SchedulerThread : IDisposable
|
||||||
{
|
{
|
||||||
public HThread Thread { get; private set; }
|
public KThread Thread { get; private set; }
|
||||||
|
|
||||||
public AutoResetEvent WaitEvent { get; private set; }
|
public AutoResetEvent WaitEvent { get; private set; }
|
||||||
|
|
||||||
public SchedulerThread(HThread Thread)
|
public SchedulerThread(KThread Thread)
|
||||||
{
|
{
|
||||||
this.Thread = 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;
|
private ThreadQueue[] WaitingToRun;
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
|
||||||
public KProcessScheduler()
|
public KProcessScheduler()
|
||||||
{
|
{
|
||||||
AllThreads = new ConcurrentDictionary<HThread, SchedulerThread>();
|
AllThreads = new ConcurrentDictionary<KThread, SchedulerThread>();
|
||||||
|
|
||||||
WaitingToRun = new ThreadQueue[4];
|
WaitingToRun = new ThreadQueue[4];
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
SchedLock = new object();
|
SchedLock = new object();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartThread(HThread Thread)
|
public void StartThread(KThread Thread)
|
||||||
{
|
{
|
||||||
lock (SchedLock)
|
lock (SchedLock)
|
||||||
{
|
{
|
||||||
|
@ -164,7 +164,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Resume(HThread CurrThread)
|
public void Resume(KThread CurrThread)
|
||||||
{
|
{
|
||||||
SchedulerThread SchedThread;
|
SchedulerThread SchedThread;
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
TryResumingExecution(SchedThread);
|
TryResumingExecution(SchedThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WaitForSignal(HThread Thread, int Timeout = -1)
|
public bool WaitForSignal(KThread Thread, int Timeout = -1)
|
||||||
{
|
{
|
||||||
SchedulerThread SchedThread;
|
SchedulerThread SchedThread;
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
|
||||||
private void TryResumingExecution(SchedulerThread SchedThread)
|
private void TryResumingExecution(SchedulerThread SchedThread)
|
||||||
{
|
{
|
||||||
HThread Thread = SchedThread.Thread;
|
KThread Thread = SchedThread.Thread;
|
||||||
|
|
||||||
lock (SchedLock)
|
lock (SchedLock)
|
||||||
{
|
{
|
||||||
|
@ -249,7 +249,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
Logging.Debug($"{GetDbgThreadInfo(Thread)} resuming execution...");
|
Logging.Debug($"{GetDbgThreadInfo(Thread)} resuming execution...");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Yield(HThread Thread)
|
public void Yield(KThread Thread)
|
||||||
{
|
{
|
||||||
SchedulerThread SchedThread;
|
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)
|
lock (SchedLock)
|
||||||
{
|
{
|
||||||
foreach (HThread Thread in Threads)
|
foreach (KThread Thread in Threads)
|
||||||
{
|
{
|
||||||
if (AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
|
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}";
|
return $"Thread {Thread.ThreadId} (core {Thread.ProcessorId}) prio {Thread.Priority}";
|
||||||
}
|
}
|
||||||
|
|
28
Ryujinx.Core/OsHle/Handles/KSession.cs
Normal file
28
Ryujinx.Core/OsHle/Handles/KSession.cs
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs
Normal file
28
Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ using ChocolArm64;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.Handles
|
namespace Ryujinx.Core.OsHle.Handles
|
||||||
{
|
{
|
||||||
public class HThread
|
class KThread : KSynchronizationObject
|
||||||
{
|
{
|
||||||
public AThread Thread { get; private set; }
|
public AThread Thread { get; private set; }
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
|
||||||
public int ThreadId => Thread.ThreadId;
|
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.Thread = Thread;
|
||||||
this.ProcessorId = ProcessorId;
|
this.ProcessorId = ProcessorId;
|
|
@ -16,8 +16,10 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
private ConcurrentDictionary<int, Process> Processes;
|
private ConcurrentDictionary<int, Process> Processes;
|
||||||
|
|
||||||
internal HSharedMem HidSharedMem;
|
internal HSharedMem HidSharedMem { get; private set; }
|
||||||
internal HSharedMem FontSharedMem;
|
internal HSharedMem FontSharedMem { get; private set; }
|
||||||
|
|
||||||
|
internal KEvent VsyncEvent { get; private set; }
|
||||||
|
|
||||||
private Switch Ns;
|
private Switch Ns;
|
||||||
|
|
||||||
|
@ -32,6 +34,8 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
HidSharedMem = new HSharedMem();
|
HidSharedMem = new HSharedMem();
|
||||||
FontSharedMem = new HSharedMem();
|
FontSharedMem = new HSharedMem();
|
||||||
|
|
||||||
|
VsyncEvent = new KEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadCart(string ExeFsDir, string RomFsFile = null)
|
public void LoadCart(string ExeFsDir, string RomFsFile = null)
|
||||||
|
@ -91,6 +95,8 @@ namespace Ryujinx.Core.OsHle
|
||||||
MainProcess.Run(IsNro);
|
MainProcess.Run(IsNro);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SignalVsync() => VsyncEvent.Handle.Set();
|
||||||
|
|
||||||
private Process MakeProcess()
|
private Process MakeProcess()
|
||||||
{
|
{
|
||||||
Process Process;
|
Process Process;
|
||||||
|
@ -109,9 +115,16 @@ namespace Ryujinx.Core.OsHle
|
||||||
Processes.TryAdd(ProcessId, Process);
|
Processes.TryAdd(ProcessId, Process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InitializeProcess(Process);
|
||||||
|
|
||||||
return Process;
|
return Process;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeProcess(Process Process)
|
||||||
|
{
|
||||||
|
Process.AppletState.SetFocus(true);
|
||||||
|
}
|
||||||
|
|
||||||
internal void ExitProcess(int ProcessId)
|
internal void ExitProcess(int ProcessId)
|
||||||
{
|
{
|
||||||
if (Processes.TryGetValue(ProcessId, out Process Process) && Process.NeedsHbAbi)
|
if (Processes.TryGetValue(ProcessId, out Process Process) && Process.NeedsHbAbi)
|
||||||
|
@ -171,6 +184,8 @@ namespace Ryujinx.Core.OsHle
|
||||||
Process.StopAllThreadsAsync();
|
Process.StopAllThreadsAsync();
|
||||||
Process.Dispose();
|
Process.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VsyncEvent.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle
|
namespace Ryujinx.Core.OsHle
|
||||||
{
|
{
|
||||||
class IdDictionary : IEnumerable<object>
|
class IdDictionary
|
||||||
{
|
{
|
||||||
private ConcurrentDictionary<int, object> Objs;
|
private ConcurrentDictionary<int, object> Objs;
|
||||||
|
|
||||||
|
@ -39,18 +38,6 @@ namespace Ryujinx.Core.OsHle
|
||||||
throw new InvalidOperationException();
|
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)
|
public object GetData(int Id)
|
||||||
{
|
{
|
||||||
if (Objs.TryGetValue(Id, out object Data))
|
if (Objs.TryGetValue(Id, out object Data))
|
||||||
|
@ -71,31 +58,25 @@ namespace Ryujinx.Core.OsHle
|
||||||
return default(T);
|
return default(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Delete(int Id)
|
public object Delete(int Id)
|
||||||
{
|
{
|
||||||
if (Objs.TryRemove(Id, out object Obj))
|
if (Objs.TryRemove(Id, out object Obj))
|
||||||
{
|
{
|
||||||
if (Obj is IDisposable DisposableObj)
|
|
||||||
{
|
|
||||||
DisposableObj.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeIdHint = Id;
|
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()
|
Objs.Clear();
|
||||||
{
|
|
||||||
return Objs.Values.GetEnumerator();
|
return Values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
namespace Ryujinx.Core.OsHle.Ipc
|
|
||||||
{
|
|
||||||
enum IpcDomCmd
|
|
||||||
{
|
|
||||||
SendMsg = 1,
|
|
||||||
DeleteObj = 2
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
using Ryujinx.Core.OsHle.Handles;
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.IpcServices;
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
@ -8,20 +7,15 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
{
|
{
|
||||||
static class IpcHandler
|
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(
|
public static void IpcCall(
|
||||||
Switch Ns,
|
Switch Ns,
|
||||||
Process Process,
|
Process Process,
|
||||||
AMemory Memory,
|
AMemory Memory,
|
||||||
HSession Session,
|
KSession Session,
|
||||||
IpcMessage Request,
|
IpcMessage Request,
|
||||||
int ThreadId,
|
long CmdPtr)
|
||||||
long CmdPtr,
|
|
||||||
int HndId)
|
|
||||||
{
|
{
|
||||||
IpcMessage Response = new IpcMessage(Request.IsDomain && Request.Type == IpcMessageType.Request);
|
IpcMessage Response = new IpcMessage();
|
||||||
|
|
||||||
using (MemoryStream Raw = new MemoryStream(Request.RawData))
|
using (MemoryStream Raw = new MemoryStream(Request.RawData))
|
||||||
{
|
{
|
||||||
|
@ -29,94 +23,25 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
|
|
||||||
if (Request.Type == IpcMessageType.Request)
|
if (Request.Type == IpcMessageType.Request)
|
||||||
{
|
{
|
||||||
string ServiceName = Session.Service.GetType().Name;
|
Response.Type = IpcMessageType.Response;
|
||||||
|
|
||||||
ServiceProcessRequest ProcReq = null;
|
using (MemoryStream ResMS = new MemoryStream())
|
||||||
|
|
||||||
bool IgnoreNullPR = false;
|
|
||||||
|
|
||||||
string DbgServiceName = string.Empty;
|
|
||||||
|
|
||||||
if (Session is HDomain Dom)
|
|
||||||
{
|
{
|
||||||
if (Request.DomCmd == IpcDomCmd.SendMsg)
|
BinaryWriter ResWriter = new BinaryWriter(ResMS);
|
||||||
{
|
|
||||||
long Magic = ReqReader.ReadInt64();
|
|
||||||
int CmdId = (int)ReqReader.ReadInt64();
|
|
||||||
|
|
||||||
object Obj = Dom.GetObject(Request.DomObjId);
|
ServiceCtx Context = new ServiceCtx(
|
||||||
|
Ns,
|
||||||
|
Process,
|
||||||
|
Memory,
|
||||||
|
Session,
|
||||||
|
Request,
|
||||||
|
Response,
|
||||||
|
ReqReader,
|
||||||
|
ResWriter);
|
||||||
|
|
||||||
if (Obj is HDomain)
|
Session.Service.CallMethod(Context);
|
||||||
{
|
|
||||||
Session.Service.Commands.TryGetValue(CmdId, out ProcReq);
|
|
||||||
|
|
||||||
DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}";
|
Response.RawData = ResMS.ToArray();
|
||||||
}
|
|
||||||
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;
|
|
||||||
|
|
||||||
((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())
|
|
||||||
{
|
|
||||||
BinaryWriter ResWriter = new BinaryWriter(ResMS);
|
|
||||||
|
|
||||||
ServiceCtx Context = new ServiceCtx(
|
|
||||||
Ns,
|
|
||||||
Process,
|
|
||||||
Memory,
|
|
||||||
Session,
|
|
||||||
Request,
|
|
||||||
Response,
|
|
||||||
ReqReader,
|
|
||||||
ResWriter);
|
|
||||||
|
|
||||||
long Result = ProcReq(Context);
|
|
||||||
|
|
||||||
Response = FillResponse(Response, Result, ResMS.ToArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!IgnoreNullPR)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException(DbgServiceName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Request.Type == IpcMessageType.Control)
|
else if (Request.Type == IpcMessageType.Control)
|
||||||
|
@ -128,11 +53,7 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
HDomain Dom = new HDomain(Session);
|
Request = FillResponse(Response, 0, Session.Service.ConvertToDomain());
|
||||||
|
|
||||||
Process.HandleTable.ReplaceData(HndId, Dom);
|
|
||||||
|
|
||||||
Request = FillResponse(Response, 0, Dom.Add(Dom));
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +119,7 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
{
|
{
|
||||||
BinaryWriter Writer = new BinaryWriter(MS);
|
BinaryWriter Writer = new BinaryWriter(MS);
|
||||||
|
|
||||||
Writer.Write(SfcoMagic);
|
Writer.Write(IpcMagic.Sfco);
|
||||||
Writer.Write(Result);
|
Writer.Write(Result);
|
||||||
|
|
||||||
if (Data != null)
|
if (Data != null)
|
||||||
|
|
|
@ -125,8 +125,7 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
|
|
||||||
Reader.ReadInt64(); //Padding
|
Reader.ReadInt64(); //Padding
|
||||||
|
|
||||||
IpcMessage += Environment.NewLine + $" Domain:" + Environment.NewLine +
|
IpcMessage += Environment.NewLine + $" Domain:" + Environment.NewLine + Environment.NewLine +
|
||||||
$" DomCmd: {Enum.GetName(typeof(IpcDomCmd), DomCmd)}" + Environment.NewLine +
|
|
||||||
$" DomObjId: {DomObjId.ToString()}" + Environment.NewLine;
|
$" DomObjId: {DomObjId.ToString()}" + Environment.NewLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
Ryujinx.Core/OsHle/Ipc/IpcMagic.cs
Normal file
8
Ryujinx.Core/OsHle/Ipc/IpcMagic.cs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,10 +17,6 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
|
|
||||||
public List<int> ResponseObjIds { get; private set; }
|
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 byte[] RawData { get; set; }
|
||||||
|
|
||||||
public IpcMessage()
|
public IpcMessage()
|
||||||
|
@ -34,27 +30,18 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
ResponseObjIds = new List<int>();
|
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))
|
using (MemoryStream MS = new MemoryStream(Data))
|
||||||
{
|
{
|
||||||
BinaryReader Reader = new BinaryReader(MS);
|
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 Word0 = Reader.ReadInt32();
|
||||||
int Word1 = Reader.ReadInt32();
|
int Word1 = Reader.ReadInt32();
|
||||||
|
|
||||||
|
@ -110,19 +97,6 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
RecvListCount = 0;
|
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);
|
RawData = Reader.ReadBytes(RawDataSize);
|
||||||
|
|
||||||
Reader.BaseStream.Seek(RecvListPos, SeekOrigin.Begin);
|
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...
|
//This is the weirdest padding I've seen so far...
|
||||||
int Pad1 = 0x10 - Pad0;
|
int Pad1 = 0x10 - Pad0;
|
||||||
|
|
||||||
DataLength = (DataLength + Pad0 + Pad1 + (IsDomain ? 0x10 : 0)) / 4;
|
DataLength = (DataLength + Pad0 + Pad1) / 4;
|
||||||
|
|
||||||
DataLength += ResponseObjIds.Count;
|
|
||||||
|
|
||||||
Word1 = DataLength & 0x3ff;
|
Word1 = DataLength & 0x3ff;
|
||||||
|
|
||||||
|
@ -182,23 +154,11 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
|
|
||||||
MS.Seek(Pad0, SeekOrigin.Current);
|
MS.Seek(Pad0, SeekOrigin.Current);
|
||||||
|
|
||||||
if (IsDomain)
|
|
||||||
{
|
|
||||||
Writer.Write(ResponseObjIds.Count);
|
|
||||||
Writer.Write(0);
|
|
||||||
Writer.Write(0L);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RawData != null)
|
if (RawData != null)
|
||||||
{
|
{
|
||||||
Writer.Write(RawData);
|
Writer.Write(RawData);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (int Id in ResponseObjIds)
|
|
||||||
{
|
|
||||||
Writer.Write(Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Writer.Write(new byte[Pad1]);
|
Writer.Write(new byte[Pad1]);
|
||||||
|
|
||||||
return MS.ToArray();
|
return MS.ToArray();
|
||||||
|
|
|
@ -6,6 +6,5 @@ namespace Ryujinx.Core.OsHle
|
||||||
public const int InvalidHandle = 114;
|
public const int InvalidHandle = 114;
|
||||||
public const int Timeout = 117;
|
public const int Timeout = 117;
|
||||||
public const int InvalidInfo = 120;
|
public const int InvalidInfo = 120;
|
||||||
public const int InvalidIpcReq = 123;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
private object EnterWaitLock;
|
private object EnterWaitLock;
|
||||||
|
|
||||||
private ConcurrentQueue<HThread> WaitingThreads;
|
private ConcurrentQueue<KThread> WaitingThreads;
|
||||||
|
|
||||||
public Mutex(Process Process, long MutexAddress, int OwnerThreadHandle)
|
public Mutex(Process Process, long MutexAddress, int OwnerThreadHandle)
|
||||||
{
|
{
|
||||||
|
@ -27,10 +27,10 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
EnterWaitLock = new object();
|
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();
|
AcquireMutexValue();
|
||||||
|
|
||||||
|
@ -83,11 +83,11 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
ReleaseMutexValue();
|
ReleaseMutexValue();
|
||||||
|
|
||||||
HThread[] UnlockedThreads = new HThread[WaitingThreads.Count];
|
KThread[] UnlockedThreads = new KThread[WaitingThreads.Count];
|
||||||
|
|
||||||
int Index = 0;
|
int Index = 0;
|
||||||
|
|
||||||
while (WaitingThreads.TryDequeue(out HThread Thread))
|
while (WaitingThreads.TryDequeue(out KThread Thread))
|
||||||
{
|
{
|
||||||
UnlockedThreads[Index++] = Thread;
|
UnlockedThreads[Index++] = Thread;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Ryujinx.Core.Loaders;
|
||||||
using Ryujinx.Core.Loaders.Executables;
|
using Ryujinx.Core.Loaders.Executables;
|
||||||
using Ryujinx.Core.OsHle.Exceptions;
|
using Ryujinx.Core.OsHle.Exceptions;
|
||||||
using Ryujinx.Core.OsHle.Handles;
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
|
using Ryujinx.Core.OsHle.IpcServices.NvServices;
|
||||||
using Ryujinx.Core.OsHle.Svc;
|
using Ryujinx.Core.OsHle.Svc;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
@ -31,21 +32,21 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
public AMemory Memory { get; private set; }
|
public AMemory Memory { get; private set; }
|
||||||
|
|
||||||
public ServiceMgr Services { get; private set; }
|
|
||||||
|
|
||||||
public KProcessScheduler Scheduler { get; private set; }
|
public KProcessScheduler Scheduler { get; private set; }
|
||||||
|
|
||||||
public KProcessHandleTable HandleTable { get; private set; }
|
public KProcessHandleTable HandleTable { get; private set; }
|
||||||
|
|
||||||
|
public AppletStateMgr AppletState { get; private set; }
|
||||||
|
|
||||||
private SvcHandler SvcHandler;
|
private SvcHandler SvcHandler;
|
||||||
|
|
||||||
private ConcurrentDictionary<int, AThread> TlsSlots;
|
private ConcurrentDictionary<int, AThread> TlsSlots;
|
||||||
|
|
||||||
private ConcurrentDictionary<long, HThread> ThreadsByTpidr;
|
private ConcurrentDictionary<long, KThread> ThreadsByTpidr;
|
||||||
|
|
||||||
private List<Executable> Executables;
|
private List<Executable> Executables;
|
||||||
|
|
||||||
private HThread MainThread;
|
private KThread MainThread;
|
||||||
|
|
||||||
private long ImageBase;
|
private long ImageBase;
|
||||||
|
|
||||||
|
@ -60,17 +61,17 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
Memory = new AMemory();
|
Memory = new AMemory();
|
||||||
|
|
||||||
Services = new ServiceMgr();
|
|
||||||
|
|
||||||
HandleTable = new KProcessHandleTable();
|
HandleTable = new KProcessHandleTable();
|
||||||
|
|
||||||
Scheduler = new KProcessScheduler();
|
Scheduler = new KProcessScheduler();
|
||||||
|
|
||||||
|
AppletState = new AppletStateMgr();
|
||||||
|
|
||||||
SvcHandler = new SvcHandler(Ns, this);
|
SvcHandler = new SvcHandler(Ns, this);
|
||||||
|
|
||||||
TlsSlots = new ConcurrentDictionary<int, AThread>();
|
TlsSlots = new ConcurrentDictionary<int, AThread>();
|
||||||
|
|
||||||
ThreadsByTpidr = new ConcurrentDictionary<long, HThread>();
|
ThreadsByTpidr = new ConcurrentDictionary<long, KThread>();
|
||||||
|
|
||||||
Executables = new List<Executable>();
|
Executables = new List<Executable>();
|
||||||
|
|
||||||
|
@ -132,7 +133,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MainThread = HandleTable.GetData<HThread>(Handle);
|
MainThread = HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
if (NeedsHbAbi)
|
if (NeedsHbAbi)
|
||||||
{
|
{
|
||||||
|
@ -186,7 +187,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
AThread Thread = new AThread(GetTranslator(), Memory, EntryPoint);
|
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);
|
int Handle = HandleTable.OpenHandle(ThreadHnd);
|
||||||
|
|
||||||
|
@ -311,9 +312,9 @@ namespace Ryujinx.Core.OsHle
|
||||||
return (int)((Position - MemoryRegions.TlsPagesAddress) / TlsSize);
|
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!");
|
Logging.Error($"Thread with TPIDR 0x{Tpidr:x16} not found!");
|
||||||
}
|
}
|
||||||
|
@ -344,11 +345,27 @@ namespace Ryujinx.Core.OsHle
|
||||||
}
|
}
|
||||||
|
|
||||||
Disposed = true;
|
Disposed = true;
|
||||||
|
|
||||||
Services.Dispose();
|
foreach (object Obj in HandleTable.Clear())
|
||||||
HandleTable.Dispose();
|
{
|
||||||
|
if (Obj is KSession Session)
|
||||||
|
{
|
||||||
|
Session.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceNvDrv.Fds.DeleteProcess(this);
|
||||||
|
|
||||||
|
ServiceNvDrv.NvMaps.DeleteProcess(this);
|
||||||
|
|
||||||
|
ServiceNvDrv.NvMapsById.DeleteProcess(this);
|
||||||
|
|
||||||
Scheduler.Dispose();
|
Scheduler.Dispose();
|
||||||
|
|
||||||
|
AppletState.Dispose();
|
||||||
|
|
||||||
SvcHandler.Dispose();
|
SvcHandler.Dispose();
|
||||||
|
|
||||||
Memory.Dispose();
|
Memory.Dispose();
|
||||||
|
|
||||||
Logging.Info($"Process {ProcessId} exiting...");
|
Logging.Info($"Process {ProcessId} exiting...");
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
public Switch Ns { get; private set; }
|
public Switch Ns { get; private set; }
|
||||||
public Process Process { get; private set; }
|
public Process Process { get; private set; }
|
||||||
public AMemory Memory { 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 Request { get; private set; }
|
||||||
public IpcMessage Response { get; private set; }
|
public IpcMessage Response { get; private set; }
|
||||||
public BinaryReader RequestData { get; private set; }
|
public BinaryReader RequestData { get; private set; }
|
||||||
|
@ -20,7 +20,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
Switch Ns,
|
Switch Ns,
|
||||||
Process Process,
|
Process Process,
|
||||||
AMemory Memory,
|
AMemory Memory,
|
||||||
HSession Session,
|
KSession Session,
|
||||||
IpcMessage Request,
|
IpcMessage Request,
|
||||||
IpcMessage Response,
|
IpcMessage Response,
|
||||||
BinaryReader RequestData,
|
BinaryReader RequestData,
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Acc
|
namespace Ryujinx.Core.OsHle.IpcServices.Acc
|
||||||
{
|
{
|
||||||
class IManagerForApplication : IIpcService
|
class IManagerForApplication : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IManagerForApplication()
|
public IManagerForApplication()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Acc
|
namespace Ryujinx.Core.OsHle.IpcServices.Acc
|
||||||
{
|
{
|
||||||
class IProfile : IIpcService
|
class IProfile : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IProfile()
|
public IProfile()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Acc
|
namespace Ryujinx.Core.OsHle.IpcServices.Acc
|
||||||
{
|
{
|
||||||
class ServiceAcc : IIpcService
|
class ServiceAcc : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceAcc()
|
public ServiceAcc()
|
||||||
{
|
{
|
||||||
|
|
7
Ryujinx.Core/OsHle/Services/Am/AmErr.cs
Normal file
7
Ryujinx.Core/OsHle/Services/Am/AmErr.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
|
{
|
||||||
|
static class AmErr
|
||||||
|
{
|
||||||
|
public const int NoMessages = 3;
|
||||||
|
}
|
||||||
|
}
|
8
Ryujinx.Core/OsHle/Services/Am/FocusState.cs
Normal file
8
Ryujinx.Core/OsHle/Services/Am/FocusState.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
|
{
|
||||||
|
enum FocusState
|
||||||
|
{
|
||||||
|
InFocus = 1,
|
||||||
|
OutOfFocus = 2
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,15 +2,13 @@ using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class IApplicationFunctions : IIpcService
|
class IApplicationFunctions : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IApplicationFunctions()
|
public IApplicationFunctions()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class IApplicationProxy : IIpcService
|
class IApplicationProxy : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IApplicationProxy()
|
public IApplicationProxy()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class IAudioController : IIpcService
|
class IAudioController : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IAudioController()
|
public IAudioController()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using static Ryujinx.Core.OsHle.ErrorCode;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class ICommonStateGetter : IIpcService
|
class ICommonStateGetter : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ICommonStateGetter()
|
public ICommonStateGetter()
|
||||||
{
|
{
|
||||||
|
@ -17,37 +20,31 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{ 1, ReceiveMessage },
|
{ 1, ReceiveMessage },
|
||||||
{ 5, GetOperationMode },
|
{ 5, GetOperationMode },
|
||||||
{ 6, GetPerformanceMode },
|
{ 6, GetPerformanceMode },
|
||||||
{ 9, GetCurrentFocusState },
|
{ 9, GetCurrentFocusState }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum FocusState
|
|
||||||
{
|
|
||||||
InFocus = 1,
|
|
||||||
OutOfFocus = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum OperationMode
|
|
||||||
{
|
|
||||||
Handheld = 0,
|
|
||||||
Docked = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
public long GetEventHandle(ServiceCtx Context)
|
public long GetEventHandle(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
Context.ResponseData.Write(0L);
|
KEvent Event = Context.Process.AppletState.MessageEvent;
|
||||||
|
|
||||||
|
int Handle = Context.Process.HandleTable.OpenHandle(Event);
|
||||||
|
|
||||||
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long ReceiveMessage(ServiceCtx Context)
|
public long ReceiveMessage(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
//Program expects 0xF at 0x17ae70 on puyo sdk,
|
if (!Context.Process.AppletState.TryDequeueMessage(out MessageInfo Message))
|
||||||
//otherwise runs on a infinite loop until it reads said value.
|
{
|
||||||
//What it means is still unknown.
|
return MakeError(ErrorModule.Am, AmErr.NoMessages);
|
||||||
Context.ResponseData.Write(0xfL);
|
}
|
||||||
|
|
||||||
return 0; //0x680;
|
Context.ResponseData.Write((int)Message);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetOperationMode(ServiceCtx Context)
|
public long GetOperationMode(ServiceCtx Context)
|
||||||
|
@ -66,7 +63,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
|
|
||||||
public long GetCurrentFocusState(ServiceCtx Context)
|
public long GetCurrentFocusState(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
Context.ResponseData.Write((byte)FocusState.InFocus);
|
Context.ResponseData.Write((byte)Context.Process.AppletState.FocusState);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class IDebugFunctions : IIpcService
|
class IDebugFunctions : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IDebugFunctions()
|
public IDebugFunctions()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class IDisplayController : IIpcService
|
class IDisplayController : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IDisplayController()
|
public IDisplayController()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class ILibraryAppletCreator : IIpcService
|
class ILibraryAppletCreator : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ILibraryAppletCreator()
|
public ILibraryAppletCreator()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class ISelfController : IIpcService
|
class ISelfController : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ISelfController()
|
public ISelfController()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class IStorage : IIpcService
|
class IStorage : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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; }
|
public byte[] Data { get; private set; }
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class IStorageAccessor : IIpcService
|
class IStorageAccessor : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
private IStorage Storage;
|
private IStorage Storage;
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class IWindowController : IIpcService
|
class IWindowController : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IWindowController()
|
public IWindowController()
|
||||||
{
|
{
|
||||||
|
|
9
Ryujinx.Core/OsHle/Services/Am/MessageInfo.cs
Normal file
9
Ryujinx.Core/OsHle/Services/Am/MessageInfo.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
|
{
|
||||||
|
enum MessageInfo
|
||||||
|
{
|
||||||
|
FocusStateChanged = 0xf,
|
||||||
|
OperationModeChanged = 0x1e,
|
||||||
|
PerformanceModeChanged = 0x1f
|
||||||
|
}
|
||||||
|
}
|
8
Ryujinx.Core/OsHle/Services/Am/OperationMode.cs
Normal file
8
Ryujinx.Core/OsHle/Services/Am/OperationMode.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
|
{
|
||||||
|
enum OperationMode
|
||||||
|
{
|
||||||
|
Handheld = 0,
|
||||||
|
Docked = 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
class ServiceAppletOE : IIpcService
|
class ServiceAppletOE : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceAppletOE()
|
public ServiceAppletOE()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Apm
|
namespace Ryujinx.Core.OsHle.IpcServices.Apm
|
||||||
{
|
{
|
||||||
class ISession : IIpcService
|
class ISession : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ISession()
|
public ISession()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Apm
|
namespace Ryujinx.Core.OsHle.IpcServices.Apm
|
||||||
{
|
{
|
||||||
class ServiceApm : IIpcService
|
class ServiceApm : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceApm()
|
public ServiceApm()
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,11 +5,11 @@ using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
{
|
{
|
||||||
class IAudioDevice : IIpcService
|
class IAudioDevice : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IAudioDevice()
|
public IAudioDevice()
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,17 +7,19 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
{
|
{
|
||||||
class IAudioOut : IIpcService, IDisposable
|
class IAudioOut : IpcService, IDisposable
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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 IAalOutput AudioOut;
|
||||||
|
|
||||||
|
private KEvent ReleaseEvent;
|
||||||
|
|
||||||
private int Track;
|
private int Track;
|
||||||
|
|
||||||
public IAudioOut(IAalOutput AudioOut, int Track)
|
public IAudioOut(IAalOutput AudioOut, KEvent ReleaseEvent, int Track)
|
||||||
{
|
{
|
||||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||||
{
|
{
|
||||||
|
@ -32,8 +34,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
{ 8, GetReleasedAudioOutBufferEx }
|
{ 8, GetReleasedAudioOutBufferEx }
|
||||||
};
|
};
|
||||||
|
|
||||||
this.AudioOut = AudioOut;
|
this.AudioOut = AudioOut;
|
||||||
this.Track = Track;
|
this.ReleaseEvent = ReleaseEvent;
|
||||||
|
this.Track = Track;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetAudioOutState(ServiceCtx Context)
|
public long GetAudioOutState(ServiceCtx Context)
|
||||||
|
@ -77,7 +80,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
|
|
||||||
public long RegisterBufferEvent(ServiceCtx Context)
|
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);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
@ -143,6 +146,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
if (Disposing)
|
if (Disposing)
|
||||||
{
|
{
|
||||||
AudioOut.CloseTrack(Track);
|
AudioOut.CloseTrack(Track);
|
||||||
|
|
||||||
|
ReleaseEvent.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
using Ryujinx.Core.OsHle.Handles;
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
{
|
{
|
||||||
class IAudioRenderer : IIpcService
|
class IAudioRenderer : IpcService, IDisposable
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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()
|
public IAudioRenderer()
|
||||||
{
|
{
|
||||||
|
@ -19,6 +22,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
{ 6, StopAudioRenderer },
|
{ 6, StopAudioRenderer },
|
||||||
{ 7, QuerySystemEvent }
|
{ 7, QuerySystemEvent }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UpdateEvent = new KEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long RequestUpdateAudioRenderer(ServiceCtx Context)
|
public long RequestUpdateAudioRenderer(ServiceCtx Context)
|
||||||
|
@ -41,6 +46,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
Context.Memory.WriteInt32(Position + Offset, 5);
|
Context.Memory.WriteInt32(Position + Offset, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: We shouldn't be signaling this here.
|
||||||
|
UpdateEvent.Handle.Set();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,11 +64,24 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
|
|
||||||
public long QuerySystemEvent(ServiceCtx Context)
|
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);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool Disposing)
|
||||||
|
{
|
||||||
|
if (Disposing)
|
||||||
|
{
|
||||||
|
UpdateEvent.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,18 +1,17 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
using Ryujinx.Audio;
|
using Ryujinx.Audio;
|
||||||
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
{
|
{
|
||||||
class ServiceAudOut : IIpcService
|
class ServiceAudOut : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceAudOut()
|
public ServiceAudOut()
|
||||||
{
|
{
|
||||||
|
@ -73,9 +72,16 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
Channels = 2;
|
Channels = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Track = AudioOut.OpenTrack(SampleRate, Channels, out AudioFormat Format);
|
KEvent ReleaseEvent = new KEvent();
|
||||||
|
|
||||||
MakeObject(Context, new IAudioOut(AudioOut, Track));
|
ReleaseCallback Callback = () =>
|
||||||
|
{
|
||||||
|
ReleaseEvent.Handle.Set();
|
||||||
|
};
|
||||||
|
|
||||||
|
int Track = AudioOut.OpenTrack(SampleRate, Channels, Callback, out AudioFormat Format);
|
||||||
|
|
||||||
|
MakeObject(Context, new IAudioOut(AudioOut, ReleaseEvent, Track));
|
||||||
|
|
||||||
Context.ResponseData.Write(SampleRate);
|
Context.ResponseData.Write(SampleRate);
|
||||||
Context.ResponseData.Write(Channels);
|
Context.ResponseData.Write(Channels);
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
namespace Ryujinx.Core.OsHle.IpcServices.Aud
|
||||||
{
|
{
|
||||||
class ServiceAudRen : IIpcService
|
class ServiceAudRen : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceAudRen()
|
public ServiceAudRen()
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,11 +51,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd
|
||||||
public Socket Handle;
|
public Socket Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServiceBsd : IIpcService
|
class ServiceBsd : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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>();
|
private List<SocketBsd> Sockets = new List<SocketBsd>();
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Friend
|
namespace Ryujinx.Core.OsHle.IpcServices.Friend
|
||||||
{
|
{
|
||||||
class IFriendService : IIpcService
|
class IFriendService : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IFriendService()
|
public IFriendService()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Friend
|
namespace Ryujinx.Core.OsHle.IpcServices.Friend
|
||||||
{
|
{
|
||||||
class ServiceFriend : IIpcService
|
class ServiceFriend : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceFriend()
|
public ServiceFriend()
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,13 +7,13 @@ using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
|
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
|
||||||
{
|
{
|
||||||
class IDirectory : IIpcService, IDisposable
|
class IDirectory : IpcService, IDisposable
|
||||||
{
|
{
|
||||||
private const int DirectoryEntrySize = 0x310;
|
private const int DirectoryEntrySize = 0x310;
|
||||||
|
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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;
|
private List<string> DirectoryEntries;
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,11 @@ using System.IO;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
|
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
|
||||||
{
|
{
|
||||||
class IFile : IIpcService, IDisposable
|
class IFile : IpcService, IDisposable
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
private Stream BaseStream;
|
private Stream BaseStream;
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,14 @@ using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.ErrorCode;
|
using static Ryujinx.Core.OsHle.ErrorCode;
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
|
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
|
||||||
{
|
{
|
||||||
class IFileSystem : IIpcService
|
class IFileSystem : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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;
|
private HashSet<string> OpenPaths;
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@ using System.IO;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
|
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
|
||||||
{
|
{
|
||||||
class IStorage : IIpcService
|
class IStorage : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
private Stream BaseStream;
|
private Stream BaseStream;
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
|
namespace Ryujinx.Core.OsHle.IpcServices.FspSrv
|
||||||
{
|
{
|
||||||
class ServiceFspSrv : IIpcService
|
class ServiceFspSrv : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceFspSrv()
|
public ServiceFspSrv()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Hid
|
namespace Ryujinx.Core.OsHle.IpcServices.Hid
|
||||||
{
|
{
|
||||||
class IActiveApplicationDeviceList : IIpcService
|
class IActiveApplicationDeviceList : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IActiveApplicationDeviceList()
|
public IActiveApplicationDeviceList()
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,11 +4,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Hid
|
namespace Ryujinx.Core.OsHle.IpcServices.Hid
|
||||||
{
|
{
|
||||||
class IAppletResource : IIpcService
|
class IAppletResource : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
private HSharedMem HidSharedMem;
|
private HSharedMem HidSharedMem;
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,13 @@ using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Ryujinx.Core.Input;
|
using Ryujinx.Core.Input;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Hid
|
namespace Ryujinx.Core.OsHle.IpcServices.Hid
|
||||||
{
|
{
|
||||||
class ServiceHid : IIpcService
|
class ServiceHid : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceHid()
|
public ServiceHid()
|
||||||
{
|
{
|
||||||
|
|
151
Ryujinx.Core/OsHle/Services/IpcService.cs
Normal file
151
Ryujinx.Core/OsHle/Services/IpcService.cs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,11 +7,11 @@ using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Lm
|
namespace Ryujinx.Core.OsHle.IpcServices.Lm
|
||||||
{
|
{
|
||||||
class ILogger : IIpcService
|
class ILogger : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ILogger()
|
public ILogger()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Lm
|
namespace Ryujinx.Core.OsHle.IpcServices.Lm
|
||||||
{
|
{
|
||||||
class ServiceLm : IIpcService
|
class ServiceLm : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceLm()
|
public ServiceLm()
|
||||||
{
|
{
|
||||||
|
@ -21,8 +19,6 @@ namespace Ryujinx.Core.OsHle.IpcServices.Lm
|
||||||
|
|
||||||
public long Initialize(ServiceCtx Context)
|
public long Initialize(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
Context.Session.Initialize();
|
|
||||||
|
|
||||||
MakeObject(Context, new ILogger());
|
MakeObject(Context, new ILogger());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Nifm
|
namespace Ryujinx.Core.OsHle.IpcServices.Nifm
|
||||||
{
|
{
|
||||||
class IGeneralService : IIpcService
|
class IGeneralService : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IGeneralService()
|
public IGeneralService()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Nifm
|
namespace Ryujinx.Core.OsHle.IpcServices.Nifm
|
||||||
{
|
{
|
||||||
class IRequest : IIpcService
|
class IRequest : IpcService, IDisposable
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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()
|
public IRequest()
|
||||||
{
|
{
|
||||||
|
@ -17,9 +21,10 @@ namespace Ryujinx.Core.OsHle.IpcServices.Nifm
|
||||||
{ 1, GetResult },
|
{ 1, GetResult },
|
||||||
{ 2, GetSystemEventReadableHandles }
|
{ 2, GetSystemEventReadableHandles }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Event = new KEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
// -> i32
|
|
||||||
public long GetRequestState(ServiceCtx Context)
|
public long GetRequestState(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
Context.ResponseData.Write(0);
|
Context.ResponseData.Write(0);
|
||||||
|
@ -39,11 +44,25 @@ namespace Ryujinx.Core.OsHle.IpcServices.Nifm
|
||||||
//GetSystemEventReadableHandles() -> (KObject, KObject)
|
//GetSystemEventReadableHandles() -> (KObject, KObject)
|
||||||
public long GetSystemEventReadableHandles(ServiceCtx Context)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool Disposing)
|
||||||
|
{
|
||||||
|
if (Disposing)
|
||||||
|
{
|
||||||
|
Event.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Nifm
|
namespace Ryujinx.Core.OsHle.IpcServices.Nifm
|
||||||
{
|
{
|
||||||
class ServiceNifm : IIpcService
|
class ServiceNifm : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceNifm()
|
public ServiceNifm()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Ns
|
namespace Ryujinx.Core.OsHle.IpcServices.Ns
|
||||||
{
|
{
|
||||||
class ServiceNs : IIpcService
|
class ServiceNs : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceNs()
|
public ServiceNs()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using Ryujinx.Core.OsHle.Utilities;
|
using Ryujinx.Core.OsHle.Utilities;
|
||||||
using Ryujinx.Graphics.Gpu;
|
using Ryujinx.Graphics.Gpu;
|
||||||
|
@ -7,20 +8,22 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
{
|
{
|
||||||
class ServiceNvDrv : IIpcService
|
class ServiceNvDrv : IpcService, IDisposable
|
||||||
{
|
{
|
||||||
private delegate long ServiceProcessIoctl(ServiceCtx Context);
|
private delegate long ServiceProcessIoctl(ServiceCtx Context);
|
||||||
|
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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 Dictionary<(string, int), ServiceProcessIoctl> IoctlCmds;
|
||||||
|
|
||||||
private IdDictionary Fds;
|
public static GlobalStateTable Fds { get; private set; }
|
||||||
|
|
||||||
private IdDictionary NvMaps;
|
public static GlobalStateTable NvMaps { get; private set; }
|
||||||
private IdDictionary NvMapsById;
|
public static GlobalStateTable NvMapsById { get; private set; }
|
||||||
|
|
||||||
|
private KEvent Event;
|
||||||
|
|
||||||
public ServiceNvDrv()
|
public ServiceNvDrv()
|
||||||
{
|
{
|
||||||
|
@ -64,10 +67,15 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
{ ("/dev/nvmap", 0x010e), NvMapIocGetId },
|
{ ("/dev/nvmap", 0x010e), NvMapIocGetId },
|
||||||
};
|
};
|
||||||
|
|
||||||
Fds = new IdDictionary();
|
Event = new KEvent();
|
||||||
|
}
|
||||||
|
|
||||||
NvMaps = new IdDictionary();
|
static ServiceNvDrv()
|
||||||
NvMapsById = new IdDictionary();
|
{
|
||||||
|
Fds = new GlobalStateTable();
|
||||||
|
|
||||||
|
NvMaps = new GlobalStateTable();
|
||||||
|
NvMapsById = new GlobalStateTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long Open(ServiceCtx Context)
|
public long Open(ServiceCtx Context)
|
||||||
|
@ -76,7 +84,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
|
|
||||||
string Name = AMemoryHelper.ReadAsciiString(Context.Memory, NamePtr);
|
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(Fd);
|
||||||
Context.ResponseData.Write(0);
|
Context.ResponseData.Write(0);
|
||||||
|
@ -89,7 +97,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
int Fd = Context.RequestData.ReadInt32();
|
int Fd = Context.RequestData.ReadInt32();
|
||||||
int Cmd = Context.RequestData.ReadInt32() & 0xffff;
|
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();
|
long Position = Context.Request.GetSendBuffPtr();
|
||||||
|
|
||||||
|
@ -109,7 +117,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
{
|
{
|
||||||
int Fd = Context.RequestData.ReadInt32();
|
int Fd = Context.RequestData.ReadInt32();
|
||||||
|
|
||||||
Fds.Delete(Fd);
|
Fds.Delete(Context.Process, Fd);
|
||||||
|
|
||||||
Context.ResponseData.Write(0);
|
Context.ResponseData.Write(0);
|
||||||
|
|
||||||
|
@ -131,7 +139,10 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
int Fd = Context.RequestData.ReadInt32();
|
int Fd = Context.RequestData.ReadInt32();
|
||||||
int EventId = 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);
|
Context.ResponseData.Write(0);
|
||||||
|
|
||||||
|
@ -203,7 +214,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvMap Map = NvMaps.GetData<NvMap>(Handle);
|
NvMap Map = NvMaps.GetData<NvMap>(Context.Process, Handle);
|
||||||
|
|
||||||
if (Map == null)
|
if (Map == null)
|
||||||
{
|
{
|
||||||
|
@ -550,9 +561,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
|
|
||||||
NvMap Map = new NvMap() { Size = Size };
|
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);
|
Context.Memory.WriteInt32(Position + 4, Map.Handle);
|
||||||
|
|
||||||
|
@ -567,7 +578,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
|
|
||||||
int Id = Context.Memory.ReadInt32(Position);
|
int Id = Context.Memory.ReadInt32(Position);
|
||||||
|
|
||||||
NvMap Map = NvMapsById.GetData<NvMap>(Id);
|
NvMap Map = NvMapsById.GetData<NvMap>(Context.Process, Id);
|
||||||
|
|
||||||
if (Map == null)
|
if (Map == null)
|
||||||
{
|
{
|
||||||
|
@ -594,7 +605,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
byte Kind = (byte)Reader.ReadInt64();
|
byte Kind = (byte)Reader.ReadInt64();
|
||||||
long Addr = Reader.ReadInt64();
|
long Addr = Reader.ReadInt64();
|
||||||
|
|
||||||
NvMap Map = NvMaps.GetData<NvMap>(Handle);
|
NvMap Map = NvMaps.GetData<NvMap>(Context.Process, Handle);
|
||||||
|
|
||||||
if (Map == null)
|
if (Map == null)
|
||||||
{
|
{
|
||||||
|
@ -620,7 +631,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
int Handle = Reader.ReadInt32();
|
int Handle = Reader.ReadInt32();
|
||||||
int Padding = Reader.ReadInt32();
|
int Padding = Reader.ReadInt32();
|
||||||
|
|
||||||
NvMap Map = NvMaps.GetData<NvMap>(Handle);
|
NvMap Map = NvMaps.GetData<NvMap>(Context.Process, Handle);
|
||||||
|
|
||||||
if (Map == null)
|
if (Map == null)
|
||||||
{
|
{
|
||||||
|
@ -645,7 +656,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
int Handle = Reader.ReadInt32();
|
int Handle = Reader.ReadInt32();
|
||||||
int Param = Reader.ReadInt32();
|
int Param = Reader.ReadInt32();
|
||||||
|
|
||||||
NvMap Map = NvMaps.GetData<NvMap>(Handle);
|
NvMap Map = NvMaps.GetData<NvMap>(Context.Process, Handle);
|
||||||
|
|
||||||
if (Map == null)
|
if (Map == null)
|
||||||
{
|
{
|
||||||
|
@ -675,7 +686,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
|
|
||||||
int Handle = Context.Memory.ReadInt32(Position + 4);
|
int Handle = Context.Memory.ReadInt32(Position + 4);
|
||||||
|
|
||||||
NvMap Map = NvMaps.GetData<NvMap>(Handle);
|
NvMap Map = NvMaps.GetData<NvMap>(Context.Process, Handle);
|
||||||
|
|
||||||
if (Map == null)
|
if (Map == null)
|
||||||
{
|
{
|
||||||
|
@ -689,9 +700,17 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
return 0;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Pctl
|
namespace Ryujinx.Core.OsHle.IpcServices.Pctl
|
||||||
{
|
{
|
||||||
class IParentalControlService : IIpcService
|
class IParentalControlService : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IParentalControlService()
|
public IParentalControlService()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Pctl
|
namespace Ryujinx.Core.OsHle.IpcServices.Pctl
|
||||||
{
|
{
|
||||||
class ServicePctl : IIpcService
|
class ServicePctl : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServicePctl()
|
public ServicePctl()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Pl
|
namespace Ryujinx.Core.OsHle.IpcServices.Pl
|
||||||
{
|
{
|
||||||
class ServicePl : IIpcService
|
class ServicePl : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServicePl()
|
public ServicePl()
|
||||||
{
|
{
|
||||||
|
|
119
Ryujinx.Core/OsHle/Services/ServiceFactory.cs
Normal file
119
Ryujinx.Core/OsHle/Services/ServiceFactory.cs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,11 +5,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Set
|
namespace Ryujinx.Core.OsHle.IpcServices.Set
|
||||||
{
|
{
|
||||||
class ServiceSet : IIpcService
|
class ServiceSet : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceSet()
|
public ServiceSet()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Set
|
namespace Ryujinx.Core.OsHle.IpcServices.Set
|
||||||
{
|
{
|
||||||
class ServiceSetSys : IIpcService
|
class ServiceSetSys : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceSetSys()
|
public ServiceSetSys()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Sfdnsres
|
namespace Ryujinx.Core.OsHle.IpcServices.Sfdnsres
|
||||||
{
|
{
|
||||||
class ServiceSfdnsres : IIpcService
|
class ServiceSfdnsres : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceSfdnsres()
|
public ServiceSfdnsres()
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,11 +4,13 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Sm
|
namespace Ryujinx.Core.OsHle.IpcServices.Sm
|
||||||
{
|
{
|
||||||
class ServiceSm : IIpcService
|
class ServiceSm : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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()
|
public ServiceSm()
|
||||||
{
|
{
|
||||||
|
@ -23,7 +25,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Sm
|
||||||
|
|
||||||
public long Initialize(ServiceCtx Context)
|
public long Initialize(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
Context.Session.Initialize();
|
IsInitialized = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +33,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Sm
|
||||||
public long GetService(ServiceCtx Context)
|
public long GetService(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
//Only for kernel version > 3.0.0.
|
//Only for kernel version > 3.0.0.
|
||||||
if (!Context.Session.IsInitialized)
|
if (!IsInitialized)
|
||||||
{
|
{
|
||||||
//return SmNotInitialized;
|
//return SmNotInitialized;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +57,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Sm
|
||||||
return 0;
|
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);
|
int Handle = Context.Process.HandleTable.OpenHandle(Session);
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Ssl
|
namespace Ryujinx.Core.OsHle.IpcServices.Ssl
|
||||||
{
|
{
|
||||||
class ServiceSsl : IIpcService
|
class ServiceSsl : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceSsl()
|
public ServiceSsl()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Time
|
namespace Ryujinx.Core.OsHle.IpcServices.Time
|
||||||
{
|
{
|
||||||
class ISteadyClock : IIpcService
|
class ISteadyClock : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ISteadyClock()
|
public ISteadyClock()
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,11 +4,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Time
|
namespace Ryujinx.Core.OsHle.IpcServices.Time
|
||||||
{
|
{
|
||||||
class ISystemClock : IIpcService
|
class ISystemClock : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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);
|
private static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Time
|
namespace Ryujinx.Core.OsHle.IpcServices.Time
|
||||||
{
|
{
|
||||||
class ITimeZoneService : IIpcService
|
class ITimeZoneService : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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);
|
private static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Time
|
namespace Ryujinx.Core.OsHle.IpcServices.Time
|
||||||
{
|
{
|
||||||
class ServiceTime : IIpcService
|
class ServiceTime : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceTime()
|
public ServiceTime()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
using Ryujinx.Core.OsHle.Handles;
|
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.Android.Parcel;
|
using static Ryujinx.Core.OsHle.IpcServices.Android.Parcel;
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
{
|
{
|
||||||
class IApplicationDisplayService : IIpcService
|
class IApplicationDisplayService : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
private IdDictionary Displays;
|
private IdDictionary Displays;
|
||||||
|
|
||||||
|
@ -145,7 +143,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
{
|
{
|
||||||
string Name = GetDisplayName(Context);
|
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);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using Ryujinx.Core.OsHle.IpcServices.Android;
|
using Ryujinx.Core.OsHle.IpcServices.Android;
|
||||||
using Ryujinx.Graphics.Gal;
|
using Ryujinx.Graphics.Gal;
|
||||||
|
@ -7,11 +8,13 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
{
|
{
|
||||||
class IHOSBinderDriver : IIpcService, IDisposable
|
class IHOSBinderDriver : IpcService, IDisposable
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
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;
|
private NvFlinger Flinger;
|
||||||
|
|
||||||
|
@ -24,7 +27,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
{ 2, GetNativeHandle }
|
{ 2, GetNativeHandle }
|
||||||
};
|
};
|
||||||
|
|
||||||
Flinger = new NvFlinger(Renderer);
|
ReleaseEvent = new KEvent();
|
||||||
|
|
||||||
|
Flinger = new NvFlinger(Renderer, ReleaseEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long TransactParcel(ServiceCtx Context)
|
public long TransactParcel(ServiceCtx Context)
|
||||||
|
@ -56,7 +61,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
int Id = Context.RequestData.ReadInt32();
|
int Id = Context.RequestData.ReadInt32();
|
||||||
uint Unk = Context.RequestData.ReadUInt32();
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +77,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
{
|
{
|
||||||
if (Disposing)
|
if (Disposing)
|
||||||
{
|
{
|
||||||
|
ReleaseEvent.Dispose();
|
||||||
|
|
||||||
Flinger.Dispose();
|
Flinger.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
{
|
{
|
||||||
class IManagerDisplayService : IIpcService
|
class IManagerDisplayService : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public IManagerDisplayService()
|
public IManagerDisplayService()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
{
|
{
|
||||||
class ISystemDisplayService : IIpcService
|
class ISystemDisplayService : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ISystemDisplayService()
|
public ISystemDisplayService()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.IpcServices.NvServices;
|
using Ryujinx.Core.OsHle.IpcServices.NvServices;
|
||||||
using Ryujinx.Graphics.Gal;
|
using Ryujinx.Graphics.Gal;
|
||||||
using System;
|
using System;
|
||||||
|
@ -17,6 +18,10 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
|
|
||||||
private Dictionary<(string, int), ServiceProcessParcel> Commands;
|
private Dictionary<(string, int), ServiceProcessParcel> Commands;
|
||||||
|
|
||||||
|
private KEvent ReleaseEvent;
|
||||||
|
|
||||||
|
private IGalRenderer Renderer;
|
||||||
|
|
||||||
private const int BufferQueueCount = 0x40;
|
private const int BufferQueueCount = 0x40;
|
||||||
private const int BufferQueueMask = BufferQueueCount - 1;
|
private const int BufferQueueMask = BufferQueueCount - 1;
|
||||||
|
|
||||||
|
@ -55,8 +60,6 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
public GbpBuffer Data;
|
public GbpBuffer Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IGalRenderer Renderer;
|
|
||||||
|
|
||||||
private BufferEntry[] BufferQueue;
|
private BufferEntry[] BufferQueue;
|
||||||
|
|
||||||
private ManualResetEvent WaitBufferFree;
|
private ManualResetEvent WaitBufferFree;
|
||||||
|
@ -69,7 +72,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
|
|
||||||
private bool KeepRunning;
|
private bool KeepRunning;
|
||||||
|
|
||||||
public NvFlinger(IGalRenderer Renderer)
|
public NvFlinger(IGalRenderer Renderer, KEvent ReleaseEvent)
|
||||||
{
|
{
|
||||||
Commands = new Dictionary<(string, int), ServiceProcessParcel>()
|
Commands = new Dictionary<(string, int), ServiceProcessParcel>()
|
||||||
{
|
{
|
||||||
|
@ -83,8 +86,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
{ ("android.gui.IGraphicBufferProducer", 0xb), GbpDisconnect },
|
{ ("android.gui.IGraphicBufferProducer", 0xb), GbpDisconnect },
|
||||||
{ ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer }
|
{ ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer }
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Renderer = Renderer;
|
this.Renderer = Renderer;
|
||||||
|
this.ReleaseEvent = ReleaseEvent;
|
||||||
|
|
||||||
BufferQueue = new BufferEntry[0x40];
|
BufferQueue = new BufferEntry[0x40];
|
||||||
|
|
||||||
|
@ -293,6 +297,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
|
|
||||||
BufferQueue[Slot].State = BufferState.Free;
|
BufferQueue[Slot].State = BufferState.Free;
|
||||||
|
|
||||||
|
ReleaseEvent.Handle.Set();
|
||||||
|
|
||||||
WaitBufferFree.Set();
|
WaitBufferFree.Set();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -377,6 +383,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
|
|
||||||
Interlocked.Decrement(ref RenderQueueCount);
|
Interlocked.Decrement(ref RenderQueueCount);
|
||||||
|
|
||||||
|
ReleaseEvent.Handle.Set();
|
||||||
|
|
||||||
lock (WaitBufferFree)
|
lock (WaitBufferFree)
|
||||||
{
|
{
|
||||||
WaitBufferFree.Set();
|
WaitBufferFree.Set();
|
||||||
|
@ -397,9 +405,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
NvMapHandle = BitConverter.ToInt32(RawValue, 0);
|
NvMapHandle = BitConverter.ToInt32(RawValue, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceNvDrv NvDrv = (ServiceNvDrv)Context.Process.Services.GetService("nvdrv");
|
return ServiceNvDrv.NvMaps.GetData<NvMap>(Context.Process, NvMapHandle);
|
||||||
|
|
||||||
return NvDrv.GetNvMap(NvMapHandle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetFreeSlotBlocking(int Width, int Height)
|
private int GetFreeSlotBlocking(int Width, int Height)
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
{
|
{
|
||||||
class ServiceVi : IIpcService
|
class ServiceVi : IpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ServiceVi()
|
public ServiceVi()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ using ChocolArm64.State;
|
||||||
using Ryujinx.Core.OsHle.Exceptions;
|
using Ryujinx.Core.OsHle.Exceptions;
|
||||||
using Ryujinx.Core.OsHle.Handles;
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
|
using Ryujinx.Core.OsHle.IpcServices;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
@ -34,7 +35,28 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
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;
|
ThreadState.X0 = 0;
|
||||||
}
|
}
|
||||||
|
@ -43,25 +65,78 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
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)
|
private void SvcWaitSynchronization(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
long HandlesPtr = (long)ThreadState.X0;
|
long HandlesPtr = (long)ThreadState.X1;
|
||||||
int HandlesCount = (int)ThreadState.X2;
|
int HandlesCount = (int)ThreadState.X2;
|
||||||
long Timeout = (long)ThreadState.X3;
|
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);
|
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);
|
Process.Scheduler.Resume(CurrThread);
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = Result;
|
||||||
|
|
||||||
|
if (Result == 0)
|
||||||
|
{
|
||||||
|
ThreadState.X1 = (ulong)HandleIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcGetSystemTick(AThreadState ThreadState)
|
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
|
//TODO: Validate that app has perms to access the service, and that the service
|
||||||
//actually exists, return error codes otherwise.
|
//actually exists, return error codes otherwise.
|
||||||
|
KSession Session = new KSession(ServiceFactory.MakeService(Name));
|
||||||
HSession Session = new HSession(Process.Services.GetService(Name));
|
|
||||||
|
|
||||||
ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session);
|
ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session);
|
||||||
|
|
||||||
|
@ -89,65 +163,46 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
private void SvcSendSyncRequest(AThreadState ThreadState)
|
private void SvcSendSyncRequest(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
SendSyncRequest(ThreadState, false);
|
SendSyncRequest(ThreadState, ThreadState.Tpidr, 0x100, (int)ThreadState.X0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState)
|
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;
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
long Size = 0x100;
|
|
||||||
int Handle = 0;
|
|
||||||
|
|
||||||
if (UserBuffer)
|
|
||||||
{
|
|
||||||
CmdPtr = (long)ThreadState.X0;
|
|
||||||
Size = (long)ThreadState.X1;
|
|
||||||
Handle = (int)ThreadState.X2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Handle = (int)ThreadState.X0;
|
|
||||||
}
|
|
||||||
|
|
||||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
|
||||||
|
|
||||||
Process.Scheduler.Suspend(CurrThread.ProcessorId);
|
|
||||||
|
|
||||||
byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
|
byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
|
||||||
|
|
||||||
HSession Session = Process.HandleTable.GetData<HSession>(Handle);
|
KSession Session = Process.HandleTable.GetData<KSession>(Handle);
|
||||||
|
|
||||||
IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr, Session is HDomain);
|
|
||||||
|
|
||||||
if (Session != null)
|
if (Session != null)
|
||||||
{
|
{
|
||||||
IpcHandler.IpcCall(
|
Process.Scheduler.Suspend(CurrThread.ProcessorId);
|
||||||
Ns,
|
|
||||||
Process,
|
|
||||||
Memory,
|
|
||||||
Session,
|
|
||||||
Cmd,
|
|
||||||
ThreadState.ThreadId,
|
|
||||||
CmdPtr,
|
|
||||||
Handle);
|
|
||||||
|
|
||||||
byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
|
IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
|
||||||
|
|
||||||
|
IpcHandler.IpcCall(Ns, Process, Memory, Session, Cmd, CmdPtr);
|
||||||
|
|
||||||
|
Thread.Yield();
|
||||||
|
|
||||||
|
Process.Scheduler.Resume(CurrThread);
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidIpcReq);
|
Logging.Warn($"Tried to SendSyncRequest on invalid session handle 0x{Handle:x8}!");
|
||||||
|
|
||||||
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread.Yield();
|
|
||||||
|
|
||||||
Process.Scheduler.Resume(CurrThread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcBreak(AThreadState ThreadState)
|
private void SvcBreak(AThreadState ThreadState)
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
|
|
||||||
HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
|
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
@ -53,16 +53,18 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
private void SvcExitThread(AThreadState ThreadState)
|
private void SvcExitThread(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
|
|
||||||
CurrThread.Thread.StopExecution();
|
CurrThread.Thread.StopExecution();
|
||||||
|
|
||||||
|
CurrThread.Handle.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcSleepThread(AThreadState ThreadState)
|
private void SvcSleepThread(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
ulong NanoSecs = ThreadState.X0;
|
ulong NanoSecs = ThreadState.X0;
|
||||||
|
|
||||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
|
|
||||||
if (NanoSecs == 0)
|
if (NanoSecs == 0)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +80,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X1;
|
int Handle = (int)ThreadState.X1;
|
||||||
|
|
||||||
HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
|
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
@ -91,10 +93,10 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
private void SvcSetThreadPriority(AThreadState ThreadState)
|
private void SvcSetThreadPriority(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
|
int Prio = (int)ThreadState.X0;
|
||||||
int Handle = (int)ThreadState.X1;
|
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)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
@ -117,7 +119,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
|
|
||||||
HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
|
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
long MutexAddress = (long)ThreadState.X1;
|
long MutexAddress = (long)ThreadState.X1;
|
||||||
int RequestingThreadHandle = (int)ThreadState.X2;
|
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);
|
Mutex M = new Mutex(Process, MutexAddress, OwnerThreadHandle);
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
int ThreadHandle = (int)ThreadState.X2;
|
int ThreadHandle = (int)ThreadState.X2;
|
||||||
long Timeout = (long)ThreadState.X3;
|
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);
|
Mutex M = new Mutex(Process, MutexAddress, ThreadHandle);
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
long CondVarAddress = (long)ThreadState.X0;
|
long CondVarAddress = (long)ThreadState.X0;
|
||||||
int Count = (int)ThreadState.X1;
|
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))
|
if (Ns.Os.CondVars.TryGetValue(CondVarAddress, out CondVar Cv))
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,10 +14,10 @@ namespace Ryujinx.Core
|
||||||
|
|
||||||
internal NsGpu Gpu { get; private set; }
|
internal NsGpu Gpu { get; private set; }
|
||||||
|
|
||||||
internal Horizon Os { get; private set; }
|
|
||||||
|
|
||||||
internal VirtualFileSystem VFs { get; private set; }
|
internal VirtualFileSystem VFs { get; private set; }
|
||||||
|
|
||||||
|
public Horizon Os { get; private set; }
|
||||||
|
|
||||||
public SystemSettings Settings { get; private set; }
|
public SystemSettings Settings { get; private set; }
|
||||||
|
|
||||||
public PerformanceStatistics Statistics { get; private set; }
|
public PerformanceStatistics Statistics { get; private set; }
|
||||||
|
@ -40,12 +40,12 @@ namespace Ryujinx.Core
|
||||||
|
|
||||||
this.AudioOut = AudioOut;
|
this.AudioOut = AudioOut;
|
||||||
|
|
||||||
Gpu = new NsGpu(Renderer);
|
Gpu = new NsGpu(Renderer);
|
||||||
|
|
||||||
Os = new Horizon(this);
|
|
||||||
|
|
||||||
VFs = new VirtualFileSystem();
|
VFs = new VirtualFileSystem();
|
||||||
|
|
||||||
|
Os = new Horizon(this);
|
||||||
|
|
||||||
Settings = new SystemSettings();
|
Settings = new SystemSettings();
|
||||||
|
|
||||||
Statistics = new PerformanceStatistics();
|
Statistics = new PerformanceStatistics();
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
{
|
{
|
||||||
private NsGpu Gpu;
|
private NsGpu Gpu;
|
||||||
|
|
||||||
private int[] Registers;
|
private uint[] Registers;
|
||||||
|
|
||||||
public NsGpuEngine[] SubChannels;
|
public NsGpuEngine[] SubChannels;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
{
|
{
|
||||||
this.Gpu = Gpu;
|
this.Gpu = Gpu;
|
||||||
|
|
||||||
Registers = new int[0x1000];
|
Registers = new uint[0x1000];
|
||||||
|
|
||||||
SubChannels = new NsGpuEngine[8];
|
SubChannels = new NsGpuEngine[8];
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
{
|
{
|
||||||
if (Entry.Arguments.Count == 1)
|
if (Entry.Arguments.Count == 1)
|
||||||
{
|
{
|
||||||
SetRegister(Entry.Register, Entry.Arguments[0]);
|
SetRegister(Entry.Register, (uint)Entry.Arguments[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Entry.Register)
|
switch (Entry.Register)
|
||||||
|
@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
case NsGpuRegister._3dVertexArray0Fetch:
|
case NsGpuRegister._3dVertexArray0Fetch:
|
||||||
SendVertexBuffers(Memory);
|
SendVertexBuffers(Memory);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NsGpuRegister._3dCbData0:
|
case NsGpuRegister._3dCbData0:
|
||||||
if (GetRegister(NsGpuRegister._3dCbPos) == 0x20)
|
if (GetRegister(NsGpuRegister._3dCbPos) == 0x20)
|
||||||
{
|
{
|
||||||
|
@ -62,6 +62,22 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
case NsGpuRegister._3dQueryGet:
|
case NsGpuRegister._3dQueryGet:
|
||||||
HasQuery = true;
|
HasQuery = true;
|
||||||
break;
|
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._3dQueryAddressHigh) << 32 |
|
||||||
(long)GetRegister(NsGpuRegister._3dQueryAddressLow) << 0;
|
(long)GetRegister(NsGpuRegister._3dQueryAddressLow) << 0;
|
||||||
|
|
||||||
int Seq = GetRegister(NsGpuRegister._3dQuerySequence);
|
uint Seq = GetRegister(NsGpuRegister._3dQuerySequence);
|
||||||
int Get = GetRegister(NsGpuRegister._3dQueryGet);
|
uint Get = GetRegister(NsGpuRegister._3dQueryGet);
|
||||||
|
|
||||||
int Mode = Get & 3;
|
uint Mode = Get & 3;
|
||||||
|
|
||||||
if (Mode == 0)
|
if (Mode == 0)
|
||||||
{
|
{
|
||||||
|
@ -85,7 +101,7 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
{
|
{
|
||||||
Gpu.Renderer.QueueAction(delegate()
|
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);
|
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>();
|
List<GalVertexAttrib> Attribs = new List<GalVertexAttrib>();
|
||||||
|
|
||||||
for (int Attr = 0; Attr < 16; Attr++)
|
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,
|
GalVertexAttrib Attrib = new GalVertexAttrib(Attr,
|
||||||
(Packed >> 0) & 0x1f,
|
(Packed >> 0) & 0x1f,
|
||||||
|
@ -154,10 +170,10 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
long TicPos = (long)GetRegister(NsGpuRegister._3dTicAddressHigh) << 32 |
|
long TicPos = (long)GetRegister(NsGpuRegister._3dTicAddressHigh) << 32 |
|
||||||
(long)GetRegister(NsGpuRegister._3dTicAddressLow) << 0;
|
(long)GetRegister(NsGpuRegister._3dTicAddressLow) << 0;
|
||||||
|
|
||||||
int CbData = GetRegister(NsGpuRegister._3dCbData0);
|
uint CbData = GetRegister(NsGpuRegister._3dCbData0);
|
||||||
|
|
||||||
int TicIndex = (CbData >> 0) & 0xfffff;
|
uint TicIndex = (CbData >> 0) & 0xfffff;
|
||||||
int TscIndex = (CbData >> 20) & 0xfff; //I guess?
|
uint TscIndex = (CbData >> 20) & 0xfff; //I guess?
|
||||||
|
|
||||||
TicPos = Gpu.MemoryMgr.GetCpuAddr(TicPos + TicIndex * 0x20);
|
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(
|
private static byte[] GetDecodedTexture(
|
||||||
AMemory Memory,
|
AMemory Memory,
|
||||||
NsGpuTextureFormat Format,
|
NsGpuTextureFormat Format,
|
||||||
|
@ -263,12 +292,12 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
return Data;
|
return Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetRegister(NsGpuRegister Register)
|
public uint GetRegister(NsGpuRegister Register)
|
||||||
{
|
{
|
||||||
return Registers[((int)Register >> 2) & 0xfff];
|
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;
|
Registers[((int)Register >> 2) & 0xfff] = Value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,5 +89,6 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
_3dCbData13 = 0x23c4,
|
_3dCbData13 = 0x23c4,
|
||||||
_3dCbData14 = 0x23c8,
|
_3dCbData14 = 0x23c8,
|
||||||
_3dCbData15 = 0x23cc,
|
_3dCbData15 = 0x23cc,
|
||||||
|
_3dSetShader = 0x3890
|
||||||
}
|
}
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue