From fba0bf873257c4ac17f4584036661be08a1694d3 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 25 Feb 2018 01:34:16 -0300 Subject: Refactor IPC services to have commands into separate classes, fix readme url --- README.md | 2 +- Ryujinx.Core/OsHle/Handles/HSession.cs | 10 +- Ryujinx.Core/OsHle/Ipc/IpcHandler.cs | 78 +-- .../IpcServices/Acc/IManagerForApplication.cs | 33 ++ Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs | 33 ++ Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs | 49 ++ .../OsHle/IpcServices/Am/IApplicationFunctions.cs | 80 +++ .../OsHle/IpcServices/Am/IApplicationProxy.cs | 85 +++ .../OsHle/IpcServices/Am/IAudioController.cs | 20 + .../OsHle/IpcServices/Am/ICommonStateGetter.cs | 74 +++ .../OsHle/IpcServices/Am/IDebugFunctions.cs | 20 + .../OsHle/IpcServices/Am/IDisplayController.cs | 20 + .../OsHle/IpcServices/Am/ILibraryAppletCreator.cs | 20 + .../OsHle/IpcServices/Am/ISelfController.cs | 61 ++ Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs | 33 ++ .../OsHle/IpcServices/Am/IStorageAccessor.cs | 62 ++ .../OsHle/IpcServices/Am/IWindowController.cs | 33 ++ .../OsHle/IpcServices/Am/ServiceAppletOE.cs | 29 + .../OsHle/IpcServices/Android/GbpBuffer.cs | 60 ++ .../OsHle/IpcServices/Android/NvFlinger.cs | 395 +++++++++++++ Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs | 58 ++ Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs | 28 + Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs | 29 + Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs | 180 ++++++ .../OsHle/IpcServices/Aud/IAudioRenderer.cs | 66 +++ .../OsHle/IpcServices/Aud/ServiceAudOut.cs | 57 ++ .../OsHle/IpcServices/Aud/ServiceAudRen.cs | 51 ++ Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs | 10 + Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs | 7 + .../OsHle/IpcServices/Friend/IFriendService.cs | 20 + .../OsHle/IpcServices/Friend/ServiceFriend.cs | 29 + Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs | 9 + .../OsHle/IpcServices/FspSrv/IDirectory.cs | 117 ++++ Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs | 111 ++++ .../OsHle/IpcServices/FspSrv/IFileSystem.cs | 383 +++++++++++++ Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs | 52 ++ .../OsHle/IpcServices/FspSrv/ServiceFspSrv.cs | 67 +++ .../IpcServices/Hid/IActiveVibrationDeviceList.cs | 17 + .../OsHle/IpcServices/Hid/IAppletResource.cs | 32 ++ Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs | 98 ++++ Ryujinx.Core/OsHle/IpcServices/IIpcService.cs | 10 + Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs | 27 + .../OsHle/IpcServices/NvServices/ServiceNvDrv.cs | 627 +++++++++++++++++++++ Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs | 24 + .../IpcServices/Pctl/IParentalControlService.cs | 20 + Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs | 29 + Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs | 51 ++ Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs | 50 ++ Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs | 46 ++ Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs | 67 +++ .../OsHle/IpcServices/Time/ISteadyClock.cs | 20 + .../OsHle/IpcServices/Time/ISystemClock.cs | 42 ++ .../OsHle/IpcServices/Time/ITimeZoneService.cs | 20 + Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs | 62 ++ .../OsHle/IpcServices/Time/SystemClockType.cs | 9 + .../IpcServices/Vi/IApplicationDisplayService.cs | 176 ++++++ .../OsHle/IpcServices/Vi/IHOSBinderDriver.cs | 76 +++ .../OsHle/IpcServices/Vi/IManagerDisplayService.cs | 33 ++ .../OsHle/IpcServices/Vi/ISystemDisplayService.cs | 25 + Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs | 31 + .../OsHle/Objects/Acc/IManagerForApplication.cs | 33 -- Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs | 33 -- .../OsHle/Objects/Am/IApplicationFunctions.cs | 80 --- Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs | 85 --- Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs | 20 - .../OsHle/Objects/Am/ICommonStateGetter.cs | 74 --- Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs | 20 - .../OsHle/Objects/Am/IDisplayController.cs | 20 - .../OsHle/Objects/Am/ILibraryAppletCreator.cs | 20 - .../OsHle/Objects/Am/IParentalControlService.cs | 20 - Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs | 61 -- Ryujinx.Core/OsHle/Objects/Am/IStorage.cs | 33 -- Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs | 62 -- Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs | 33 -- Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs | 60 -- Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs | 395 ------------- Ryujinx.Core/OsHle/Objects/Android/Parcel.cs | 58 -- Ryujinx.Core/OsHle/Objects/Apm/ISession.cs | 28 - Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs | 180 ------ Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs | 66 --- Ryujinx.Core/OsHle/Objects/ErrorCode.cs | 10 - Ryujinx.Core/OsHle/Objects/ErrorModule.cs | 7 - .../OsHle/Objects/Friend/IFriendService.cs | 20 - Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs | 9 - Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs | 117 ---- Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs | 111 ---- Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs | 383 ------------- Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs | 52 -- .../Objects/Hid/IActiveVibrationDeviceList.cs | 17 - Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs | 32 -- Ryujinx.Core/OsHle/Objects/IIpcInterface.cs | 10 - Ryujinx.Core/OsHle/Objects/ObjHelper.cs | 24 - Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs | 20 - Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs | 42 -- .../OsHle/Objects/Time/ITimeZoneService.cs | 20 - Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs | 9 - .../OsHle/Objects/Vi/IApplicationDisplayService.cs | 176 ------ Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs | 76 --- .../OsHle/Objects/Vi/IManagerDisplayService.cs | 33 -- .../OsHle/Objects/Vi/ISystemDisplayService.cs | 25 - Ryujinx.Core/OsHle/Services/ServiceAcc.cs | 33 -- Ryujinx.Core/OsHle/Services/ServiceApm.cs | 16 - Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs | 16 - Ryujinx.Core/OsHle/Services/ServiceAud.cs | 71 --- Ryujinx.Core/OsHle/Services/ServiceFriend.cs | 16 - Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs | 49 -- Ryujinx.Core/OsHle/Services/ServiceHid.cs | 77 --- Ryujinx.Core/OsHle/Services/ServiceLm.cs | 12 - Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs | 610 -------------------- Ryujinx.Core/OsHle/Services/ServicePctl.cs | 16 - Ryujinx.Core/OsHle/Services/ServicePl.cs | 35 -- Ryujinx.Core/OsHle/Services/ServiceSet.cs | 32 -- Ryujinx.Core/OsHle/Services/ServiceSm.cs | 48 -- Ryujinx.Core/OsHle/Services/ServiceTime.cs | 45 -- Ryujinx.Core/OsHle/Services/ServiceVi.cs | 18 - Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 3 +- 116 files changed, 3988 insertions(+), 3746 deletions(-) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/IIpcService.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Acc/IManagerForApplication.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/IApplicationFunctions.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/ICommonStateGetter.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/IDisplayController.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/ILibraryAppletCreator.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/IParentalControlService.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/IStorage.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Android/Parcel.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Apm/ISession.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/ErrorCode.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/ErrorModule.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Friend/IFriendService.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/IIpcInterface.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/ObjHelper.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Time/ITimeZoneService.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Vi/IApplicationDisplayService.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Vi/IManagerDisplayService.cs delete mode 100644 Ryujinx.Core/OsHle/Objects/Vi/ISystemDisplayService.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceAcc.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceApm.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceAud.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceFriend.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceHid.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceLm.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServicePctl.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServicePl.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceSet.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceSm.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceTime.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceVi.cs diff --git a/README.md b/README.md index 6a241127..841a8258 100644 --- a/README.md +++ b/README.md @@ -67,4 +67,4 @@ Run `dotnet run -c Release -- path\to\game_exefs_and_romfs_folder` to run offici **Latest build** These builds are compiled automatically for each commit on the master branch. They may be unstable or not work at all. -To download the latest automatic build for Windows (64-bits), [Click Here](https://ci.appveyor.com/api/projects/gdkchan/ryujinx/artifacts/ryujinx_latest_unstable.zip). +To download the latest automatic build for Windows (64-bits), [Click Here](https://ci.appveyor.com/api/projects/gdkchan/ryujinx/artifacts/ryujinx_latest_unstable.zip?pr=false). diff --git a/Ryujinx.Core/OsHle/Handles/HSession.cs b/Ryujinx.Core/OsHle/Handles/HSession.cs index 8aa1c06b..f30e91f9 100644 --- a/Ryujinx.Core/OsHle/Handles/HSession.cs +++ b/Ryujinx.Core/OsHle/Handles/HSession.cs @@ -1,21 +1,23 @@ +using Ryujinx.Core.OsHle.IpcServices; + namespace Ryujinx.Core.OsHle.Handles { class HSession { - public string ServiceName { get; private set; } + public IIpcService Service { get; private set; } public bool IsInitialized { get; private set; } public int State { get; set; } - public HSession(string ServiceName) + public HSession(IIpcService Service) { - this.ServiceName = ServiceName; + this.Service = Service; } public HSession(HSession Session) { - ServiceName = Session.ServiceName; + Service = Session.Service; IsInitialized = Session.IsInitialized; } diff --git a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs index 5785dbf3..2495d701 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs @@ -1,79 +1,13 @@ using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Objects; -using Ryujinx.Core.OsHle.Services; +using Ryujinx.Core.OsHle.IpcServices; using System; -using System.Collections.Generic; using System.IO; namespace Ryujinx.Core.OsHle.Ipc { static class IpcHandler { - private static Dictionary<(string, int), ServiceProcessRequest> ServiceCmds = - new Dictionary<(string, int), ServiceProcessRequest>() - { - { ( "acc:u0", 3), Service.AccU0ListOpenUsers }, - { ( "acc:u0", 5), Service.AccU0GetProfile }, - { ( "acc:u0", 100), Service.AccU0InitializeApplicationInfo }, - { ( "acc:u0", 101), Service.AccU0GetBaasAccountManagerForApplication }, - { ( "apm", 0), Service.ApmOpenSession }, - { ( "apm:p", 0), Service.ApmOpenSession }, - { ( "appletOE", 0), Service.AppletOpenApplicationProxy }, - { ( "audout:u", 0), Service.AudOutListAudioOuts }, - { ( "audout:u", 1), Service.AudOutOpenAudioOut }, - { ( "audren:u", 0), Service.AudRenOpenAudioRenderer }, - { ( "audren:u", 1), Service.AudRenGetAudioRendererWorkBufferSize }, - { ( "friend:a", 0), Service.FriendCreateFriendService }, - { ( "fsp-srv", 1), Service.FspSrvInitialize }, - { ( "fsp-srv", 18), Service.FspSrvMountSdCard }, - { ( "fsp-srv", 51), Service.FspSrvMountSaveData }, - { ( "fsp-srv", 200), Service.FspSrvOpenDataStorageByCurrentProcess }, - { ( "fsp-srv", 203), Service.FspSrvOpenRomStorage }, - { ( "fsp-srv", 1005), Service.FspSrvGetGlobalAccessLogMode }, - { ( "hid", 0), Service.HidCreateAppletResource }, - { ( "hid", 11), Service.HidActivateTouchScreen }, - { ( "hid", 100), Service.HidSetSupportedNpadStyleSet }, - { ( "hid", 101), Service.HidGetSupportedNpadStyleSet }, - { ( "hid", 102), Service.HidSetSupportedNpadIdType }, - { ( "hid", 103), Service.HidActivateNpad }, - { ( "hid", 120), Service.HidSetNpadJoyHoldType }, - { ( "hid", 121), Service.HidGetNpadJoyHoldType }, - { ( "hid", 203), Service.HidCreateActiveVibrationDeviceList }, - { ( "lm", 0), Service.LmInitialize }, - { ( "nvdrv", 0), Service.NvDrvOpen }, - { ( "nvdrv", 1), Service.NvDrvIoctl }, - { ( "nvdrv", 2), Service.NvDrvClose }, - { ( "nvdrv", 3), Service.NvDrvInitialize }, - { ( "nvdrv", 4), Service.NvDrvQueryEvent }, - { ( "nvdrv", 8), Service.NvDrvSetClientPid }, - { ( "nvdrv:a", 0), Service.NvDrvOpen }, - { ( "nvdrv:a", 1), Service.NvDrvIoctl }, - { ( "nvdrv:a", 2), Service.NvDrvClose }, - { ( "nvdrv:a", 3), Service.NvDrvInitialize }, - { ( "nvdrv:a", 4), Service.NvDrvQueryEvent }, - { ( "nvdrv:a", 8), Service.NvDrvSetClientPid }, - { ( "pctl:a", 0), Service.PctlCreateService }, - { ( "pl:u", 1), Service.PlGetLoadState }, - { ( "pl:u", 2), Service.PlGetFontSize }, - { ( "pl:u", 3), Service.PlGetSharedMemoryAddressOffset }, - { ( "pl:u", 4), Service.PlGetSharedMemoryNativeHandle }, - { ( "set", 1), Service.SetGetAvailableLanguageCodes }, - { ( "sm:", 0), Service.SmInitialize }, - { ( "sm:", 1), Service.SmGetService }, - { ( "time:u", 0), Service.TimeGetStandardUserSystemClock }, - { ( "time:u", 1), Service.TimeGetStandardNetworkSystemClock }, - { ( "time:u", 2), Service.TimeGetStandardSteadyClock }, - { ( "time:u", 3), Service.TimeGetTimeZoneService }, - { ( "time:u", 4), Service.TimeGetStandardLocalSystemClock }, - { ( "time:s", 0), Service.TimeGetStandardUserSystemClock }, - { ( "time:s", 1), Service.TimeGetStandardNetworkSystemClock }, - { ( "time:s", 2), Service.TimeGetStandardSteadyClock }, - { ( "time:s", 3), Service.TimeGetTimeZoneService }, - { ( "time:s", 4), Service.TimeGetStandardLocalSystemClock }, - { ( "vi:m", 2), Service.ViGetDisplayService }, - }; - private const long SfciMagic = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'I' << 24; private const long SfcoMagic = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'O' << 24; @@ -94,7 +28,7 @@ namespace Ryujinx.Core.OsHle.Ipc if (Request.Type == IpcMessageType.Request) { - string ServiceName = Session.ServiceName; + string ServiceName = Session.Service.GetType().Name; ServiceProcessRequest ProcReq = null; @@ -113,13 +47,13 @@ namespace Ryujinx.Core.OsHle.Ipc if (Obj is HDomain) { - ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq); + Session.Service.Commands.TryGetValue(CmdId, out ProcReq); DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}"; } else if (Obj != null) { - ((IIpcInterface)Obj).Commands.TryGetValue(CmdId, out ProcReq); + ((IIpcService)Obj).Commands.TryGetValue(CmdId, out ProcReq); DbgServiceName = $"{Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}"; } @@ -142,13 +76,13 @@ namespace Ryujinx.Core.OsHle.Ipc { object Obj = ((HSessionObj)Session).Obj; - ((IIpcInterface)Obj).Commands.TryGetValue(CmdId, out ProcReq); + ((IIpcService)Obj).Commands.TryGetValue(CmdId, out ProcReq); DbgServiceName = $"{Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}"; } else { - ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq); + Session.Service.Commands.TryGetValue(CmdId, out ProcReq); DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}"; } diff --git a/Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs b/Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs new file mode 100644 index 00000000..ab491eac --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs @@ -0,0 +1,33 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Acc +{ + class IManagerForApplication : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IManagerForApplication() + { + m_Commands = new Dictionary() + { + { 0, CheckAvailability }, + { 1, GetAccountId } + }; + } + + public long CheckAvailability(ServiceCtx Context) + { + return 0; + } + + public long GetAccountId(ServiceCtx Context) + { + Context.ResponseData.Write(0xcafeL); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs b/Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs new file mode 100644 index 00000000..77fe2b48 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs @@ -0,0 +1,33 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Acc +{ + class IProfile : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IProfile() + { + m_Commands = new Dictionary() + { + { 1, GetBase } + }; + } + + public long GetBase(ServiceCtx Context) + { + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs b/Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs new file mode 100644 index 00000000..8844bb5d --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs @@ -0,0 +1,49 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Acc +{ + class ServiceAcc : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceAcc() + { + m_Commands = new Dictionary() + { + { 3, ListOpenUsers }, + { 5, GetProfile }, + { 100, InitializeApplicationInfo }, + { 101, GetBaasAccountManagerForApplication } + }; + } + + public long ListOpenUsers(ServiceCtx Context) + { + return 0; + } + + public long GetProfile(ServiceCtx Context) + { + MakeObject(Context, new IProfile()); + + return 0; + } + + public long InitializeApplicationInfo(ServiceCtx Context) + { + return 0; + } + + public long GetBaasAccountManagerForApplication(ServiceCtx Context) + { + MakeObject(Context, new IManagerForApplication()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs new file mode 100644 index 00000000..30020c1d --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs @@ -0,0 +1,80 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; +using System.IO; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class IApplicationFunctions : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IApplicationFunctions() + { + m_Commands = new Dictionary() + { + { 1, PopLaunchParameter }, + { 20, EnsureSaveData }, + { 21, GetDesiredLanguage }, + { 40, NotifyRunning } + }; + } + + private const uint LaunchParamsMagic = 0xc79497ca; + + public long PopLaunchParameter(ServiceCtx Context) + { + //Only the first 0x18 bytes of the Data seems to be actually used. + MakeObject(Context, new IStorage(MakeLaunchParams())); + + return 0; + } + + public long EnsureSaveData(ServiceCtx Context) + { + long UIdLow = Context.RequestData.ReadInt64(); + long UIdHigh = Context.RequestData.ReadInt64(); + + Context.ResponseData.Write(0L); + + return 0; + } + + public long GetDesiredLanguage(ServiceCtx Context) + { + //This is an enumerator where each number is a differnet language. + //0 is Japanese and 1 is English, need to figure out the other codes. + Context.ResponseData.Write(1L); + + return 0; + } + + public long NotifyRunning(ServiceCtx Context) + { + Context.ResponseData.Write(1); + + return 0; + } + + private byte[] MakeLaunchParams() + { + //Size needs to be at least 0x88 bytes otherwise application errors. + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + MS.SetLength(0x88); + + Writer.Write(LaunchParamsMagic); + Writer.Write(1); //IsAccountSelected? Only lower 8 bits actually used. + Writer.Write(1L); //User Id Low (note: User Id needs to be != 0) + Writer.Write(0L); //User Id High + + return MS.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs new file mode 100644 index 00000000..5417d7f0 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs @@ -0,0 +1,85 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class IApplicationProxy : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IApplicationProxy() + { + m_Commands = new Dictionary() + { + { 0, GetCommonStateGetter }, + { 1, GetSelfController }, + { 2, GetWindowController }, + { 3, GetAudioController }, + { 4, GetDisplayController }, + { 11, GetLibraryAppletCreator }, + { 20, GetApplicationFunctions }, + { 1000, GetDebugFunctions } + }; + } + + public long GetCommonStateGetter(ServiceCtx Context) + { + MakeObject(Context, new ICommonStateGetter()); + + return 0; + } + + public long GetSelfController(ServiceCtx Context) + { + MakeObject(Context, new ISelfController()); + + return 0; + } + + public long GetWindowController(ServiceCtx Context) + { + MakeObject(Context, new IWindowController()); + + return 0; + } + + public long GetAudioController(ServiceCtx Context) + { + MakeObject(Context, new IAudioController()); + + return 0; + } + + public long GetDisplayController(ServiceCtx Context) + { + MakeObject(Context, new IDisplayController()); + + return 0; + } + + public long GetLibraryAppletCreator(ServiceCtx Context) + { + MakeObject(Context, new ILibraryAppletCreator()); + + return 0; + } + + public long GetApplicationFunctions(ServiceCtx Context) + { + MakeObject(Context, new IApplicationFunctions()); + + return 0; + } + + public long GetDebugFunctions(ServiceCtx Context) + { + MakeObject(Context, new IDebugFunctions()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs new file mode 100644 index 00000000..1212f1e2 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs @@ -0,0 +1,20 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class IAudioController : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IAudioController() + { + m_Commands = new Dictionary() + { + //... + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs b/Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs new file mode 100644 index 00000000..2999bbba --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs @@ -0,0 +1,74 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class ICommonStateGetter : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ICommonStateGetter() + { + m_Commands = new Dictionary() + { + { 0, GetEventHandle }, + { 1, ReceiveMessage }, + { 5, GetOperationMode }, + { 6, GetPerformanceMode }, + { 9, GetCurrentFocusState }, + }; + } + + private enum FocusState + { + InFocus = 1, + OutOfFocus = 2 + } + + private enum OperationMode + { + Handheld = 0, + Docked = 1 + } + + public long GetEventHandle(ServiceCtx Context) + { + Context.ResponseData.Write(0L); + + return 0; + } + + public long ReceiveMessage(ServiceCtx Context) + { + //Program expects 0xF at 0x17ae70 on puyo sdk, + //otherwise runs on a infinite loop until it reads said value. + //What it means is still unknown. + Context.ResponseData.Write(0xfL); + + return 0; //0x680; + } + + public long GetOperationMode(ServiceCtx Context) + { + Context.ResponseData.Write((byte)OperationMode.Handheld); + + return 0; + } + + public long GetPerformanceMode(ServiceCtx Context) + { + Context.ResponseData.Write((byte)0); + + return 0; + } + + public long GetCurrentFocusState(ServiceCtx Context) + { + Context.ResponseData.Write((byte)FocusState.InFocus); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs new file mode 100644 index 00000000..944e58d8 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs @@ -0,0 +1,20 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class IDebugFunctions : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IDebugFunctions() + { + m_Commands = new Dictionary() + { + //... + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs new file mode 100644 index 00000000..979e842a --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs @@ -0,0 +1,20 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class IDisplayController : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IDisplayController() + { + m_Commands = new Dictionary() + { + //... + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs b/Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs new file mode 100644 index 00000000..9f5b5e69 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs @@ -0,0 +1,20 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class ILibraryAppletCreator : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ILibraryAppletCreator() + { + m_Commands = new Dictionary() + { + //... + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs b/Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs new file mode 100644 index 00000000..90ddd54b --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs @@ -0,0 +1,61 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class ISelfController : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ISelfController() + { + m_Commands = new Dictionary() + { + { 10, SetScreenShotPermission }, + { 11, SetOperationModeChangedNotification }, + { 12, SetPerformanceModeChangedNotification }, + { 13, SetFocusHandlingMode }, + { 16, SetOutOfFocusSuspendingEnabled } + }; + } + + public long SetScreenShotPermission(ServiceCtx Context) + { + bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + + public long SetOperationModeChangedNotification(ServiceCtx Context) + { + bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + + public long SetPerformanceModeChangedNotification(ServiceCtx Context) + { + bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + + public long SetFocusHandlingMode(ServiceCtx Context) + { + bool Flag1 = Context.RequestData.ReadByte() != 0 ? true : false; + bool Flag2 = Context.RequestData.ReadByte() != 0 ? true : false; + bool Flag3 = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + + public long SetOutOfFocusSuspendingEnabled(ServiceCtx Context) + { + bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs new file mode 100644 index 00000000..375b960b --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs @@ -0,0 +1,33 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class IStorage : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public byte[] Data { get; private set; } + + public IStorage(byte[] Data) + { + m_Commands = new Dictionary() + { + { 0, Open } + }; + + this.Data = Data; + } + + public long Open(ServiceCtx Context) + { + MakeObject(Context, new IStorageAccessor(this)); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs new file mode 100644 index 00000000..6d83e6f9 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs @@ -0,0 +1,62 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class IStorageAccessor : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private IStorage Storage; + + public IStorageAccessor(IStorage Storage) + { + m_Commands = new Dictionary() + { + { 0, GetSize }, + { 11, Read } + }; + + this.Storage = Storage; + } + + public long GetSize(ServiceCtx Context) + { + Context.ResponseData.Write((long)Storage.Data.Length); + + return 0; + } + + public long Read(ServiceCtx Context) + { + long ReadPosition = Context.RequestData.ReadInt64(); + + if (Context.Request.RecvListBuff.Count > 0) + { + long Position = Context.Request.RecvListBuff[0].Position; + short Size = Context.Request.RecvListBuff[0].Size; + + byte[] Data; + + if (Storage.Data.Length > Size) + { + Data = new byte[Size]; + + Buffer.BlockCopy(Storage.Data, 0, Data, 0, Size); + } + else + { + Data = Storage.Data; + } + + AMemoryHelper.WriteBytes(Context.Memory, Position, Data); + } + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs new file mode 100644 index 00000000..ddc73bce --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs @@ -0,0 +1,33 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class IWindowController : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IWindowController() + { + m_Commands = new Dictionary() + { + { 1, GetAppletResourceUserId }, + { 10, AcquireForegroundRights } + }; + } + + public long GetAppletResourceUserId(ServiceCtx Context) + { + Context.ResponseData.Write(0L); + + return 0; + } + + public long AcquireForegroundRights(ServiceCtx Context) + { + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs b/Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs new file mode 100644 index 00000000..b60c93dd --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs @@ -0,0 +1,29 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class ServiceAppletOE : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceAppletOE() + { + m_Commands = new Dictionary() + { + { 0, OpenApplicationProxy } + }; + } + + public long OpenApplicationProxy(ServiceCtx Context) + { + MakeObject(Context, new IApplicationProxy()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs b/Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs new file mode 100644 index 00000000..5fe585d0 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs @@ -0,0 +1,60 @@ +using System.IO; + +namespace Ryujinx.Core.OsHle.IpcServices.Android +{ + struct GbpBuffer + { + public int Magic { get; private set; } + public int Width { get; private set; } + public int Height { get; private set; } + public int Stride { get; private set; } + public int Format { get; private set; } + public int Usage { get; private set; } + + public int Pid { get; private set; } + public int RefCount { get; private set; } + + public int FdsCount { get; private set; } + public int IntsCount { get; private set; } + + public byte[] RawData { get; private set; } + + public int Size => RawData.Length + 10 * 4; + + public GbpBuffer(BinaryReader Reader) + { + Magic = Reader.ReadInt32(); + Width = Reader.ReadInt32(); + Height = Reader.ReadInt32(); + Stride = Reader.ReadInt32(); + Format = Reader.ReadInt32(); + Usage = Reader.ReadInt32(); + + Pid = Reader.ReadInt32(); + RefCount = Reader.ReadInt32(); + + FdsCount = Reader.ReadInt32(); + IntsCount = Reader.ReadInt32(); + + RawData = Reader.ReadBytes((FdsCount + IntsCount) * 4); + } + + public void Write(BinaryWriter Writer) + { + Writer.Write(Magic); + Writer.Write(Width); + Writer.Write(Height); + Writer.Write(Stride); + Writer.Write(Format); + Writer.Write(Usage); + + Writer.Write(Pid); + Writer.Write(RefCount); + + Writer.Write(FdsCount); + Writer.Write(IntsCount); + + Writer.Write(RawData); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs b/Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs new file mode 100644 index 00000000..85a06cea --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs @@ -0,0 +1,395 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Handles; +using System; +using System.IO; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +using static Ryujinx.Core.OsHle.IpcServices.Android.Parcel; + +namespace Ryujinx.Core.OsHle.IpcServices.Android +{ + class NvFlinger : IDisposable + { + private delegate long ServiceProcessParcel(ServiceCtx Context, BinaryReader ParcelReader); + + private Dictionary<(string, int), ServiceProcessParcel> Commands; + + private const int BufferQueueCount = 0x40; + private const int BufferQueueMask = BufferQueueCount - 1; + + [Flags] + private enum HalTransform + { + FlipX = 1 << 0, + FlipY = 1 << 1, + Rotate90 = 1 << 2 + } + + private enum BufferState + { + Free, + Dequeued, + Queued, + Acquired + } + + private struct BufferEntry + { + public BufferState State; + + public HalTransform Transform; + + public GbpBuffer Data; + } + + private BufferEntry[] BufferQueue; + + private ManualResetEvent WaitBufferFree; + + private bool KeepRunning; + + public NvFlinger() + { + Commands = new Dictionary<(string, int), ServiceProcessParcel>() + { + { ("android.gui.IGraphicBufferProducer", 0x1), GbpRequestBuffer }, + { ("android.gui.IGraphicBufferProducer", 0x3), GbpDequeueBuffer }, + { ("android.gui.IGraphicBufferProducer", 0x7), GbpQueueBuffer }, + { ("android.gui.IGraphicBufferProducer", 0x8), GbpCancelBuffer }, + { ("android.gui.IGraphicBufferProducer", 0x9), GbpQuery }, + { ("android.gui.IGraphicBufferProducer", 0xa), GbpConnect }, + { ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer } + }; + + BufferQueue = new BufferEntry[0x40]; + + WaitBufferFree = new ManualResetEvent(false); + + KeepRunning = true; + } + + public long ProcessParcelRequest(ServiceCtx Context, byte[] ParcelData, int Code) + { + using (MemoryStream MS = new MemoryStream(ParcelData)) + { + BinaryReader Reader = new BinaryReader(MS); + + MS.Seek(4, SeekOrigin.Current); + + int StrSize = Reader.ReadInt32(); + + string InterfaceName = Encoding.Unicode.GetString(Reader.ReadBytes(StrSize * 2)); + + long Remainder = MS.Position & 0xf; + + if (Remainder != 0) + { + MS.Seek(0x10 - Remainder, SeekOrigin.Current); + } + + MS.Seek(0x50, SeekOrigin.Begin); + + if (Commands.TryGetValue((InterfaceName, Code), out ServiceProcessParcel ProcReq)) + { + Logging.Debug($"{InterfaceName} {ProcReq.Method.Name}"); + + return ProcReq(Context, Reader); + } + else + { + throw new NotImplementedException($"{InterfaceName} {Code}"); + } + } + } + + private long GbpRequestBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + int Slot = ParcelReader.ReadInt32(); + + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + BufferEntry Entry = BufferQueue[Slot]; + + int BufferCount = 1; //? + long BufferSize = Entry.Data.Size; + + Writer.Write(BufferCount); + Writer.Write(BufferSize); + + Entry.Data.Write(Writer); + + Writer.Write(0); + + return MakeReplyParcel(Context, MS.ToArray()); + } + } + + private long GbpDequeueBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + //TODO: Errors. + int Format = ParcelReader.ReadInt32(); + int Width = ParcelReader.ReadInt32(); + int Height = ParcelReader.ReadInt32(); + int GetTimestamps = ParcelReader.ReadInt32(); + int Usage = ParcelReader.ReadInt32(); + + int Slot = GetFreeSlotBlocking(Width, Height); + + return MakeReplyParcel(Context, Slot, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + + private long GbpQueueBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + //TODO: Errors. + int Slot = ParcelReader.ReadInt32(); + int Unknown4 = ParcelReader.ReadInt32(); + int Unknown8 = ParcelReader.ReadInt32(); + int Unknownc = ParcelReader.ReadInt32(); + int Timestamp = ParcelReader.ReadInt32(); + int IsAutoTimestamp = ParcelReader.ReadInt32(); + int CropTop = ParcelReader.ReadInt32(); + int CropLeft = ParcelReader.ReadInt32(); + int CropRight = ParcelReader.ReadInt32(); + int CropBottom = ParcelReader.ReadInt32(); + int ScalingMode = ParcelReader.ReadInt32(); + int Transform = ParcelReader.ReadInt32(); + int StickyTransform = ParcelReader.ReadInt32(); + int Unknown34 = ParcelReader.ReadInt32(); + int Unknown38 = ParcelReader.ReadInt32(); + int IsFenceValid = ParcelReader.ReadInt32(); + int Fence0Id = ParcelReader.ReadInt32(); + int Fence0Value = ParcelReader.ReadInt32(); + int Fence1Id = ParcelReader.ReadInt32(); + int Fence1Value = ParcelReader.ReadInt32(); + + BufferQueue[Slot].Transform = (HalTransform)Transform; + + BufferQueue[Slot].State = BufferState.Queued; + + SendFrameBuffer(Context, Slot); + + return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); + } + + private long GbpCancelBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + //TODO: Errors. + int Slot = ParcelReader.ReadInt32(); + + BufferQueue[Slot].State = BufferState.Free; + + return MakeReplyParcel(Context, 0); + } + + private long GbpQuery(ServiceCtx Context, BinaryReader ParcelReader) + { + return MakeReplyParcel(Context, 0, 0); + } + + private long GbpConnect(ServiceCtx Context, BinaryReader ParcelReader) + { + return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); + } + + private long GbpPreallocBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + int Slot = ParcelReader.ReadInt32(); + + int BufferCount = ParcelReader.ReadInt32(); + long BufferSize = ParcelReader.ReadInt64(); + + BufferQueue[Slot].State = BufferState.Free; + + BufferQueue[Slot].Data = new GbpBuffer(ParcelReader); + + return MakeReplyParcel(Context, 0); + } + + private long MakeReplyParcel(ServiceCtx Context, params int[] Ints) + { + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + foreach (int Int in Ints) + { + Writer.Write(Int); + } + + return MakeReplyParcel(Context, MS.ToArray()); + } + } + + private long MakeReplyParcel(ServiceCtx Context, byte[] Data) + { + long ReplyPos = Context.Request.ReceiveBuff[0].Position; + long ReplySize = Context.Request.ReceiveBuff[0].Size; + + byte[] Reply = MakeParcel(Data, new byte[0]); + + AMemoryHelper.WriteBytes(Context.Memory, ReplyPos, Reply); + + return 0; + } + + private unsafe void SendFrameBuffer(ServiceCtx Context, int Slot) + { + int FbWidth = BufferQueue[Slot].Data.Width; + int FbHeight = BufferQueue[Slot].Data.Height; + + int FbSize = FbWidth * FbHeight * 4; + + HNvMap NvMap = GetNvMap(Context, Slot); + + if (FbSize < 0 || NvMap.Address < 0 || NvMap.Address + FbSize > AMemoryMgr.AddrSize) + { + Logging.Error($"Frame buffer address {NvMap.Address:x16} is invalid!"); + + BufferQueue[Slot].State = BufferState.Free; + + WaitBufferFree.Set(); + + return; + } + + BufferQueue[Slot].State = BufferState.Acquired; + + float ScaleX = 1; + float ScaleY = 1; + float Rotate = 0; + + if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX)) + { + ScaleX = -1; + } + + if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY)) + { + ScaleY = -1; + } + + if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90)) + { + Rotate = MathF.PI * 0.5f; + } + + byte* Fb = (byte*)Context.Ns.Ram + NvMap.Address; + + Context.Ns.Gpu.Renderer.QueueAction(delegate() + { + Context.Ns.Gpu.Renderer.SetFrameBuffer( + Fb, + FbWidth, + FbHeight, + ScaleX, + ScaleY, + Rotate); + + BufferQueue[Slot].State = BufferState.Free; + + lock (WaitBufferFree) + { + WaitBufferFree.Set(); + } + }); + } + + private HNvMap GetNvMap(ServiceCtx Context, int Slot) + { + int NvMapHandle = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x4c); + + if (!BitConverter.IsLittleEndian) + { + byte[] RawValue = BitConverter.GetBytes(NvMapHandle); + + Array.Reverse(RawValue); + + NvMapHandle = BitConverter.ToInt32(RawValue, 0); + } + + return Context.Ns.Os.Handles.GetData(NvMapHandle); + } + + private int GetFreeSlotBlocking(int Width, int Height) + { + int Slot; + + do + { + lock (WaitBufferFree) + { + if ((Slot = GetFreeSlot(Width, Height)) != -1) + { + break; + } + + Logging.Debug("Waiting for a free BufferQueue slot..."); + + if (!KeepRunning) + { + break; + } + + WaitBufferFree.Reset(); + } + + WaitBufferFree.WaitOne(); + } + while (KeepRunning); + + Logging.Debug($"Found free BufferQueue slot {Slot}!"); + + return Slot; + } + + private int GetFreeSlot(int Width, int Height) + { + lock (BufferQueue) + { + for (int Slot = 0; Slot < BufferQueue.Length; Slot++) + { + if (BufferQueue[Slot].State != BufferState.Free) + { + continue; + } + + GbpBuffer Data = BufferQueue[Slot].Data; + + if (Data.Width == Width && + Data.Height == Height) + { + BufferQueue[Slot].State = BufferState.Dequeued; + + return Slot; + } + } + } + + return -1; + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + lock (WaitBufferFree) + { + KeepRunning = false; + + WaitBufferFree.Set(); + } + + WaitBufferFree.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs b/Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs new file mode 100644 index 00000000..3404c227 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs @@ -0,0 +1,58 @@ +using System; +using System.IO; + +namespace Ryujinx.Core.OsHle.IpcServices.Android +{ + static class Parcel + { + public static byte[] GetParcelData(byte[] Parcel) + { + if (Parcel == null) + { + throw new ArgumentNullException(nameof(Parcel)); + } + + using (MemoryStream MS = new MemoryStream(Parcel)) + { + BinaryReader Reader = new BinaryReader(MS); + + int DataSize = Reader.ReadInt32(); + int DataOffset = Reader.ReadInt32(); + int ObjsSize = Reader.ReadInt32(); + int ObjsOffset = Reader.ReadInt32(); + + MS.Seek(DataOffset - 0x10, SeekOrigin.Current); + + return Reader.ReadBytes(DataSize); + } + } + + public static byte[] MakeParcel(byte[] Data, byte[] Objs) + { + if (Data == null) + { + throw new ArgumentNullException(nameof(Data)); + } + + if (Objs == null) + { + throw new ArgumentNullException(nameof(Objs)); + } + + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + Writer.Write(Data.Length); + Writer.Write(0x10); + Writer.Write(Objs.Length); + Writer.Write(Data.Length + 0x10); + + Writer.Write(Data); + Writer.Write(Objs); + + return MS.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs b/Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs new file mode 100644 index 00000000..500f7596 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs @@ -0,0 +1,28 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Apm +{ + class ISession : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ISession() + { + m_Commands = new Dictionary() + { + { 0, SetPerformanceConfiguration } + }; + } + + public long SetPerformanceConfiguration(ServiceCtx Context) + { + int PerfMode = Context.RequestData.ReadInt32(); + int PerfConfig = Context.RequestData.ReadInt32(); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs b/Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs new file mode 100644 index 00000000..d6c0400a --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs @@ -0,0 +1,29 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Apm +{ + class ServiceApm : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceApm() + { + m_Commands = new Dictionary() + { + { 0, OpenSession } + }; + } + + public long OpenSession(ServiceCtx Context) + { + MakeObject(Context, new ISession()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs new file mode 100644 index 00000000..a45b23cc --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs @@ -0,0 +1,180 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using OpenTK.Audio; +using OpenTK.Audio.OpenAL; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Ryujinx.Core.OsHle.IpcServices.Aud +{ + class IAudioOut : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IAudioOut() + { + m_Commands = new Dictionary() + { + { 0, GetAudioOutState }, + { 1, StartAudioOut }, + { 2, StopAudioOut }, + { 3, AppendAudioOutBuffer }, + { 4, RegisterBufferEvent }, + { 5, GetReleasedAudioOutBuffer }, + { 6, ContainsAudioOutBuffer }, + { 7, AppendAudioOutBuffer_ex }, + { 8, GetReleasedAudioOutBuffer_ex } + }; + } + + enum AudioOutState + { + Started, + Stopped + }; + + //IAudioOut + private AudioOutState State = AudioOutState.Stopped; + private Queue KeysQueue = new Queue(); + + //OpenAL + private bool OpenALInstalled = true; + private AudioContext AudioCtx; + private int Source; + private int Buffer; + + //Return State of IAudioOut + public long GetAudioOutState(ServiceCtx Context) + { + Context.ResponseData.Write((int)State); + + return 0; + } + + public long StartAudioOut(ServiceCtx Context) + { + if (State == AudioOutState.Stopped) + { + State = AudioOutState.Started; + + try + { + AudioCtx = new AudioContext(); //Create the audio context + } + catch (Exception) + { + Logging.Warn("OpenAL Error! PS: Install OpenAL Core SDK!"); + OpenALInstalled = false; + } + + if (OpenALInstalled) AL.Listener(ALListenerf.Gain, (float)8.0); //Add more gain to it + } + + return 0; + } + + public long StopAudioOut(ServiceCtx Context) + { + if (State == AudioOutState.Started) + { + if (OpenALInstalled) + { + if (AudioCtx == null) //Needed to call the instance of AudioContext() + return 0; + + AL.SourceStop(Source); + AL.DeleteSource(Source); + } + State = AudioOutState.Stopped; + } + + return 0; + } + + public long AppendAudioOutBuffer(ServiceCtx Context) + { + long BufferId = Context.RequestData.ReadInt64(); + + KeysQueue.Enqueue(BufferId); + + byte[] AudioOutBuffer = AMemoryHelper.ReadBytes(Context.Memory, Context.Request.SendBuff[0].Position, sizeof(long) * 5); + using (MemoryStream MS = new MemoryStream(AudioOutBuffer)) + { + BinaryReader Reader = new BinaryReader(MS); + long PointerNextBuffer = Reader.ReadInt64(); + long PointerSampleBuffer = Reader.ReadInt64(); + long CapacitySampleBuffer = Reader.ReadInt64(); + long SizeDataInSampleBuffer = Reader.ReadInt64(); + long OffsetDataInSampleBuffer = Reader.ReadInt64(); + + byte[] AudioSampleBuffer = AMemoryHelper.ReadBytes(Context.Memory, PointerSampleBuffer + OffsetDataInSampleBuffer, (int)SizeDataInSampleBuffer); + + if (OpenALInstalled) + { + if (AudioCtx == null) //Needed to call the instance of AudioContext() + return 0; + + Buffer = AL.GenBuffer(); + AL.BufferData(Buffer, ALFormat.Stereo16, AudioSampleBuffer, AudioSampleBuffer.Length, 48000); + + Source = AL.GenSource(); + AL.SourceQueueBuffer(Source, Buffer); + } + } + + return 0; + } + + public long RegisterBufferEvent(ServiceCtx Context) + { + int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); + + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); + + return 0; + } + + public long GetReleasedAudioOutBuffer(ServiceCtx Context) + { + long TempKey = 0; + + if (KeysQueue.Count > 0) TempKey = KeysQueue.Dequeue(); + + AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, BitConverter.GetBytes(TempKey)); + + int ReleasedBuffersCount = 1; + Context.ResponseData.Write(ReleasedBuffersCount); + + if (OpenALInstalled) + { + if (AudioCtx == null) //Needed to call the instance of AudioContext() + return 0; + + AL.SourcePlay(Source); + int[] FreeBuffers = AL.SourceUnqueueBuffers(Source, 1); + AL.DeleteBuffers(FreeBuffers); + } + + return 0; + } + + public long ContainsAudioOutBuffer(ServiceCtx Context) + { + return 0; + } + + public long AppendAudioOutBuffer_ex(ServiceCtx Context) + { + return 0; + } + + public long GetReleasedAudioOutBuffer_ex(ServiceCtx Context) + { + return 0; + } + } +} diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs b/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs new file mode 100644 index 00000000..bfde0b65 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs @@ -0,0 +1,66 @@ +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Aud +{ + class IAudioRenderer : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IAudioRenderer() + { + m_Commands = new Dictionary() + { + { 4, RequestUpdateAudioRenderer }, + { 5, StartAudioRenderer }, + { 6, StopAudioRenderer }, + { 7, QuerySystemEvent } + }; + } + + public long RequestUpdateAudioRenderer(ServiceCtx Context) + { + //(buffer) -> (buffer, buffer) + + long Position = Context.Request.ReceiveBuff[0].Position; + + //0x40 bytes header + Context.Memory.WriteInt32(Position + 0x4, 0xb0); //Behavior Out State Size? (note: this is the last section) + Context.Memory.WriteInt32(Position + 0x8, 0x18e0); //Memory Pool Out State Size? + Context.Memory.WriteInt32(Position + 0xc, 0x600); //Voice Out State Size? + Context.Memory.WriteInt32(Position + 0x14, 0xe0); //Effect Out State Size? + Context.Memory.WriteInt32(Position + 0x1c, 0x20); //Sink Out State Size? + Context.Memory.WriteInt32(Position + 0x20, 0x10); //Performance Out State Size? + Context.Memory.WriteInt32(Position + 0x3c, 0x20e0); //Total Size (including 0x40 bytes header) + + for (int Offset = 0x40; Offset < 0x40 + 0x18e0; Offset += 0x10) + { + Context.Memory.WriteInt32(Position + Offset, 5); + } + + return 0; + } + + public long StartAudioRenderer(ServiceCtx Context) + { + return 0; + } + + public long StopAudioRenderer(ServiceCtx Context) + { + return 0; + } + + public long QuerySystemEvent(ServiceCtx Context) + { + int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); + + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs b/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs new file mode 100644 index 00000000..eb923562 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs @@ -0,0 +1,57 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; +using System.Text; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Aud +{ + class ServiceAudOut : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceAudOut() + { + m_Commands = new Dictionary() + { + { 0, ListAudioOuts }, + { 1, OpenAudioOut }, + }; + } + + public long ListAudioOuts(ServiceCtx Context) + { + long Position = Context.Request.ReceiveBuff[0].Position; + + AMemoryHelper.WriteBytes(Context.Memory, Position, Encoding.ASCII.GetBytes("iface")); + + Context.ResponseData.Write(1); + + return 0; + } + + public long OpenAudioOut(ServiceCtx Context) + { + MakeObject(Context, new IAudioOut()); + + Context.ResponseData.Write(48000); //Sample Rate + Context.ResponseData.Write(2); //Channel Count + Context.ResponseData.Write(2); //PCM Format + /* + 0 - Invalid + 1 - INT8 + 2 - INT16 + 3 - INT24 + 4 - INT32 + 5 - PCM Float + 6 - ADPCM + */ + Context.ResponseData.Write(0); //Unknown + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs b/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs new file mode 100644 index 00000000..eccc699c --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs @@ -0,0 +1,51 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Aud +{ + class ServiceAudRen : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceAudRen() + { + m_Commands = new Dictionary() + { + { 0, OpenAudioRenderer }, + { 1, GetAudioRendererWorkBufferSize }, + }; + } + + public long OpenAudioRenderer(ServiceCtx Context) + { + MakeObject(Context, new IAudioRenderer()); + + return 0; + } + + public long GetAudioRendererWorkBufferSize(ServiceCtx Context) + { + int SampleRate = Context.RequestData.ReadInt32(); + int Unknown4 = Context.RequestData.ReadInt32(); + int Unknown8 = Context.RequestData.ReadInt32(); + int UnknownC = Context.RequestData.ReadInt32(); + int Unknown10 = Context.RequestData.ReadInt32(); + int Unknown14 = Context.RequestData.ReadInt32(); + int Unknown18 = Context.RequestData.ReadInt32(); + int Unknown1c = Context.RequestData.ReadInt32(); + int Unknown20 = Context.RequestData.ReadInt32(); + int Unknown24 = Context.RequestData.ReadInt32(); + int Unknown28 = Context.RequestData.ReadInt32(); + int Unknown2c = Context.RequestData.ReadInt32(); + int Rev1Magic = Context.RequestData.ReadInt32(); + + Context.ResponseData.Write(0x400L); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs b/Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs new file mode 100644 index 00000000..a4e197b2 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.Core.OsHle.IpcServices +{ + static class ErrorCode + { + public static long MakeError(ErrorModule Module, int Code) + { + return (int)Module | (Code << 9); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs b/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs new file mode 100644 index 00000000..0d15db60 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.Core.OsHle.IpcServices +{ + enum ErrorModule + { + Fs = 2, + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs b/Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs new file mode 100644 index 00000000..e3e03da8 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs @@ -0,0 +1,20 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Friend +{ + class IFriendService : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IFriendService() + { + m_Commands = new Dictionary() + { + //... + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs b/Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs new file mode 100644 index 00000000..674877f6 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs @@ -0,0 +1,29 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Friend +{ + class ServiceFriend : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceFriend() + { + m_Commands = new Dictionary() + { + { 0, CreateFriendService } + }; + } + + public static long CreateFriendService(ServiceCtx Context) + { + MakeObject(Context, new IFriendService()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs new file mode 100644 index 00000000..656d529f --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs @@ -0,0 +1,9 @@ +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv +{ + static class FsErr + { + public const int PathDoesNotExist = 1; + public const int PathAlreadyExists = 2; + public const int PathAlreadyInUse = 7; + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs new file mode 100644 index 00000000..54dbec74 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs @@ -0,0 +1,117 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv +{ + class IDirectory : IIpcService, IDisposable + { + private const int DirectoryEntrySize = 0x310; + + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private List DirectoryEntries; + + private int CurrentItemIndex; + + public event EventHandler Disposed; + + public string HostPath { get; private set; } + + public IDirectory(string HostPath, int Flags) + { + m_Commands = new Dictionary() + { + { 0, Read }, + { 1, GetEntryCount } + }; + + this.HostPath = HostPath; + + DirectoryEntries = new List(); + + if ((Flags & 1) != 0) + { + DirectoryEntries.AddRange(Directory.GetDirectories(HostPath)); + } + + if ((Flags & 2) != 0) + { + DirectoryEntries.AddRange(Directory.GetFiles(HostPath)); + } + + CurrentItemIndex = 0; + } + + public long Read(ServiceCtx Context) + { + long BufferPosition = Context.Request.ReceiveBuff[0].Position; + long BufferLen = Context.Request.ReceiveBuff[0].Size; + + int MaxReadCount = (int)(BufferLen / DirectoryEntrySize); + + int Count = Math.Min(DirectoryEntries.Count - CurrentItemIndex, MaxReadCount); + + for (int Index = 0; Index < Count; Index++) + { + long Position = BufferPosition + Index * DirectoryEntrySize; + + WriteDirectoryEntry(Context, Position, DirectoryEntries[CurrentItemIndex++]); + } + + Context.ResponseData.Write((long)Count); + + return 0; + } + + private void WriteDirectoryEntry(ServiceCtx Context, long Position, string FullPath) + { + for (int Offset = 0; Offset < 0x300; Offset += 8) + { + Context.Memory.WriteInt64(Position + Offset, 0); + } + + byte[] NameBuffer = Encoding.UTF8.GetBytes(Path.GetFileName(FullPath)); + + AMemoryHelper.WriteBytes(Context.Memory, Position, NameBuffer); + + int Type = 0; + long Size = 0; + + if (File.Exists(FullPath)) + { + Type = 1; + Size = new FileInfo(FullPath).Length; + } + + Context.Memory.WriteInt32(Position + 0x300, 0); //Padding? + Context.Memory.WriteInt32(Position + 0x304, Type); + Context.Memory.WriteInt64(Position + 0x308, Size); + } + + public long GetEntryCount(ServiceCtx Context) + { + Context.ResponseData.Write((long)DirectoryEntries.Count); + + return 0; + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + Disposed?.Invoke(this, EventArgs.Empty); + } + } + } +} diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs new file mode 100644 index 00000000..ac2100f2 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs @@ -0,0 +1,111 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System; +using System.Collections.Generic; +using System.IO; + +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv +{ + class IFile : IIpcService, IDisposable + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private Stream BaseStream; + + public event EventHandler Disposed; + + public string HostPath { get; private set; } + + public IFile(Stream BaseStream, string HostPath) + { + m_Commands = new Dictionary() + { + { 0, Read }, + { 1, Write }, + { 2, Flush }, + { 3, SetSize }, + { 4, GetSize } + }; + + this.BaseStream = BaseStream; + this.HostPath = HostPath; + } + + public long Read(ServiceCtx Context) + { + long Position = Context.Request.ReceiveBuff[0].Position; + + long Zero = Context.RequestData.ReadInt64(); + long Offset = Context.RequestData.ReadInt64(); + long Size = Context.RequestData.ReadInt64(); + + byte[] Data = new byte[Size]; + + BaseStream.Seek(Offset, SeekOrigin.Begin); + + int ReadSize = BaseStream.Read(Data, 0, (int)Size); + + AMemoryHelper.WriteBytes(Context.Memory, Position, Data); + + Context.ResponseData.Write((long)ReadSize); + + return 0; + } + + public long Write(ServiceCtx Context) + { + long Position = Context.Request.SendBuff[0].Position; + + long Zero = Context.RequestData.ReadInt64(); + long Offset = Context.RequestData.ReadInt64(); + long Size = Context.RequestData.ReadInt64(); + + byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, Position, (int)Size); + + BaseStream.Seek(Offset, SeekOrigin.Begin); + BaseStream.Write(Data, 0, (int)Size); + + return 0; + } + + public long Flush(ServiceCtx Context) + { + BaseStream.Flush(); + + return 0; + } + + public long SetSize(ServiceCtx Context) + { + long Size = Context.RequestData.ReadInt64(); + + BaseStream.SetLength(Size); + + return 0; + } + + public long GetSize(ServiceCtx Context) + { + Context.ResponseData.Write(BaseStream.Length); + + return 0; + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && BaseStream != null) + { + BaseStream.Dispose(); + + Disposed?.Invoke(this, EventArgs.Empty); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs new file mode 100644 index 00000000..ee9de8bc --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs @@ -0,0 +1,383 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System; +using System.Collections.Generic; +using System.IO; + +using static Ryujinx.Core.OsHle.IpcServices.ErrorCode; +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv +{ + class IFileSystem : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private HashSet OpenPaths; + + private string Path; + + public IFileSystem(string Path) + { + m_Commands = new Dictionary() + { + { 0, CreateFile }, + { 1, DeleteFile }, + { 2, CreateDirectory }, + { 3, DeleteDirectory }, + { 4, DeleteDirectoryRecursively }, + { 5, RenameFile }, + { 6, RenameDirectory }, + { 7, GetEntryType }, + { 8, OpenFile }, + { 9, OpenDirectory }, + { 10, Commit }, + { 11, GetFreeSpaceSize }, + { 12, GetTotalSpaceSize }, + //{ 13, CleanDirectoryRecursively }, + //{ 14, GetFileTimeStampRaw } + }; + + OpenPaths = new HashSet(); + + this.Path = Path; + } + + public long CreateFile(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + long Mode = Context.RequestData.ReadInt64(); + int Size = Context.RequestData.ReadInt32(); + + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (FileName == null) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (File.Exists(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + if (IsPathAlreadyInUse(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + using (FileStream NewFile = File.Create(FileName)) + { + NewFile.SetLength(Size); + } + + return 0; + } + + public long DeleteFile(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (!File.Exists(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (IsPathAlreadyInUse(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + File.Delete(FileName); + + return 0; + } + + public long CreateDirectory(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string DirName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (DirName == null) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (Directory.Exists(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + if (IsPathAlreadyInUse(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + Directory.CreateDirectory(DirName); + + return 0; + } + + public long DeleteDirectory(ServiceCtx Context) + { + return DeleteDirectory(Context, false); + } + + public long DeleteDirectoryRecursively(ServiceCtx Context) + { + return DeleteDirectory(Context, true); + } + + private long DeleteDirectory(ServiceCtx Context, bool Recursive) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string DirName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (!Directory.Exists(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (IsPathAlreadyInUse(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + Directory.Delete(DirName, Recursive); + + return 0; + } + + public long RenameFile(ServiceCtx Context) + { + long OldPosition = Context.Request.PtrBuff[0].Position; + long NewPosition = Context.Request.PtrBuff[0].Position; + + string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); + string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); + + string OldFileName = Context.Ns.VFs.GetFullPath(Path, OldName); + string NewFileName = Context.Ns.VFs.GetFullPath(Path, NewName); + + if (!File.Exists(OldFileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (File.Exists(NewFileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + if (IsPathAlreadyInUse(OldFileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + File.Move(OldFileName, NewFileName); + + return 0; + } + + public long RenameDirectory(ServiceCtx Context) + { + long OldPosition = Context.Request.PtrBuff[0].Position; + long NewPosition = Context.Request.PtrBuff[0].Position; + + string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); + string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); + + string OldDirName = Context.Ns.VFs.GetFullPath(Path, OldName); + string NewDirName = Context.Ns.VFs.GetFullPath(Path, NewName); + + if (!Directory.Exists(OldDirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (Directory.Exists(NewDirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + if (IsPathAlreadyInUse(OldDirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + Directory.Move(OldDirName, NewDirName); + + return 0; + } + + public long GetEntryType(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (File.Exists(FileName)) + { + Context.ResponseData.Write(1); + } + else if (Directory.Exists(FileName)) + { + Context.ResponseData.Write(0); + } + else + { + Context.ResponseData.Write(0); + + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + return 0; + } + + public long OpenFile(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + int FilterFlags = Context.RequestData.ReadInt32(); + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (!File.Exists(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (IsPathAlreadyInUse(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + FileStream Stream = new FileStream(FileName, FileMode.Open); + + IFile FileInterface = new IFile(Stream, FileName); + + FileInterface.Disposed += RemoveFileInUse; + + lock (OpenPaths) + { + OpenPaths.Add(FileName); + } + + MakeObject(Context, FileInterface); + + return 0; + } + + public long OpenDirectory(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + int FilterFlags = Context.RequestData.ReadInt32(); + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string DirName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (!Directory.Exists(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (IsPathAlreadyInUse(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + IDirectory DirInterface = new IDirectory(DirName, FilterFlags); + + DirInterface.Disposed += RemoveDirectoryInUse; + + lock (OpenPaths) + { + OpenPaths.Add(DirName); + } + + MakeObject(Context, DirInterface); + + return 0; + } + + public long Commit(ServiceCtx Context) + { + return 0; + } + + public long GetFreeSpaceSize(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + Context.ResponseData.Write(Context.Ns.VFs.GetDrive().AvailableFreeSpace); + + return 0; + } + + public long GetTotalSpaceSize(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + Context.ResponseData.Write(Context.Ns.VFs.GetDrive().TotalSize); + + return 0; + } + + private bool IsPathAlreadyInUse(string Path) + { + lock (OpenPaths) + { + return OpenPaths.Contains(Path); + } + } + + private void RemoveFileInUse(object sender, EventArgs e) + { + IFile FileInterface = (IFile)sender; + + lock (OpenPaths) + { + FileInterface.Disposed -= RemoveFileInUse; + + OpenPaths.Remove(FileInterface.HostPath); + } + } + + private void RemoveDirectoryInUse(object sender, EventArgs e) + { + IDirectory DirInterface = (IDirectory)sender; + + lock (OpenPaths) + { + DirInterface.Disposed -= RemoveDirectoryInUse; + + OpenPaths.Remove(DirInterface.HostPath); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs new file mode 100644 index 00000000..297461a0 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs @@ -0,0 +1,52 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; +using System.IO; + +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv +{ + class IStorage : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private Stream BaseStream; + + public IStorage(Stream BaseStream) + { + m_Commands = new Dictionary() + { + { 0, Read } + }; + + this.BaseStream = BaseStream; + } + + public long Read(ServiceCtx Context) + { + long Offset = Context.RequestData.ReadInt64(); + long Size = Context.RequestData.ReadInt64(); + + if (Context.Request.ReceiveBuff.Count > 0) + { + IpcBuffDesc BuffDesc = Context.Request.ReceiveBuff[0]; + + //Use smaller length to avoid overflows. + if (Size > BuffDesc.Size) + { + Size = BuffDesc.Size; + } + + byte[] Data = new byte[Size]; + + BaseStream.Seek(Offset, SeekOrigin.Begin); + BaseStream.Read(Data, 0, Data.Length); + + AMemoryHelper.WriteBytes(Context.Memory, BuffDesc.Position, Data); + } + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs new file mode 100644 index 00000000..991f4027 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs @@ -0,0 +1,67 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv +{ + class ServiceFspSrv : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceFspSrv() + { + m_Commands = new Dictionary() + { + { 1, Initialize }, + { 18, MountSdCard }, + { 51, MountSaveData }, + { 200, OpenDataStorageByCurrentProcess }, + { 203, OpenRomStorage }, + { 1005, GetGlobalAccessLogMode } + }; + } + + public long Initialize(ServiceCtx Context) + { + return 0; + } + + public long MountSdCard(ServiceCtx Context) + { + MakeObject(Context, new IFileSystem(Context.Ns.VFs.GetSdCardPath())); + + return 0; + } + + public long MountSaveData(ServiceCtx Context) + { + MakeObject(Context, new IFileSystem(Context.Ns.VFs.GetGameSavesPath())); + + return 0; + } + + public long OpenDataStorageByCurrentProcess(ServiceCtx Context) + { + MakeObject(Context, new IStorage(Context.Ns.VFs.RomFs)); + + return 0; + } + + public long OpenRomStorage(ServiceCtx Context) + { + MakeObject(Context, new IStorage(Context.Ns.VFs.RomFs)); + + return 0; + } + + public long GetGlobalAccessLogMode(ServiceCtx Context) + { + Context.ResponseData.Write(0); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs b/Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs new file mode 100644 index 00000000..020e8e7e --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs @@ -0,0 +1,17 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Hid +{ + class IActiveApplicationDeviceList : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IActiveApplicationDeviceList() + { + m_Commands = new Dictionary() { }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs b/Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs new file mode 100644 index 00000000..d22e0ff2 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs @@ -0,0 +1,32 @@ +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Hid +{ + class IAppletResource : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private HSharedMem Handle; + + public IAppletResource(HSharedMem Handle) + { + m_Commands = new Dictionary() + { + { 0, GetSharedMemoryHandle } + }; + + this.Handle = Handle; + } + + public static long GetSharedMemoryHandle(ServiceCtx Context) + { + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Context.Ns.Os.HidHandle); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs b/Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs new file mode 100644 index 00000000..5cca9319 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs @@ -0,0 +1,98 @@ +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Hid +{ + class ServiceHid : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceHid() + { + m_Commands = new Dictionary() + { + { 0, CreateAppletResource }, + { 11, ActivateTouchScreen }, + { 100, SetSupportedNpadStyleSet }, + { 101, GetSupportedNpadStyleSet }, + { 102, SetSupportedNpadIdType }, + { 103, ActivateNpad }, + { 120, SetNpadJoyHoldType }, + { 121, GetNpadJoyHoldType }, + { 203, CreateActiveVibrationDeviceList }, + }; + } + + public long CreateAppletResource(ServiceCtx Context) + { + HSharedMem HidHndData = Context.Ns.Os.Handles.GetData(Context.Ns.Os.HidHandle); + + MakeObject(Context, new IAppletResource(HidHndData)); + + return 0; + } + + public long ActivateTouchScreen(ServiceCtx Context) + { + long Unknown = Context.RequestData.ReadInt64(); + + return 0; + } + + public long GetSupportedNpadStyleSet(ServiceCtx Context) + { + Context.ResponseData.Write(0); + + return 0; + } + + public long SetSupportedNpadStyleSet(ServiceCtx Context) + { + long Unknown0 = Context.RequestData.ReadInt64(); + long Unknown8 = Context.RequestData.ReadInt64(); + + return 0; + } + + public long SetSupportedNpadIdType(ServiceCtx Context) + { + long Unknown = Context.RequestData.ReadInt64(); + + return 0; + } + + public long ActivateNpad(ServiceCtx Context) + { + long Unknown = Context.RequestData.ReadInt64(); + + return 0; + } + + public long SetNpadJoyHoldType(ServiceCtx Context) + { + long Unknown0 = Context.RequestData.ReadInt64(); + long Unknown8 = Context.RequestData.ReadInt64(); + + return 0; + } + + public long GetNpadJoyHoldType(ServiceCtx Context) + { + Context.ResponseData.Write(0L); + + return 0; + } + + public long CreateActiveVibrationDeviceList(ServiceCtx Context) + { + MakeObject(Context, new IActiveApplicationDeviceList()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/IIpcService.cs b/Ryujinx.Core/OsHle/IpcServices/IIpcService.cs new file mode 100644 index 00000000..eebcdfbe --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/IIpcService.cs @@ -0,0 +1,10 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices +{ + interface IIpcService + { + IReadOnlyDictionary Commands { get; } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs b/Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs new file mode 100644 index 00000000..e665253c --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs @@ -0,0 +1,27 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Lm +{ + class ServiceLm : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceLm() + { + m_Commands = new Dictionary() + { + { 0, Initialize } + }; + } + + public long Initialize(ServiceCtx Context) + { + Context.Session.Initialize(); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs new file mode 100644 index 00000000..1de0ab70 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs @@ -0,0 +1,627 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using Ryujinx.Core.OsHle.Utilities; +using Ryujinx.Graphics.Gpu; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.NvServices +{ + class ServiceNvDrv : IIpcService + { + private delegate long ServiceProcessIoctl(ServiceCtx Context); + + private static Dictionary<(string, int), ServiceProcessIoctl> IoctlCmds = + new Dictionary<(string, int), ServiceProcessIoctl>() + { + { ("/dev/nvhost-as-gpu", 0x4101), NvGpuAsIoctlBindChannel }, + { ("/dev/nvhost-as-gpu", 0x4102), NvGpuAsIoctlAllocSpace }, + { ("/dev/nvhost-as-gpu", 0x4106), NvGpuAsIoctlMapBufferEx }, + { ("/dev/nvhost-as-gpu", 0x4108), NvGpuAsIoctlGetVaRegions }, + { ("/dev/nvhost-as-gpu", 0x4109), NvGpuAsIoctlInitializeEx }, + { ("/dev/nvhost-ctrl", 0x001b), NvHostIoctlCtrlGetConfig }, + { ("/dev/nvhost-ctrl", 0x001d), NvHostIoctlCtrlEventWait }, + { ("/dev/nvhost-ctrl-gpu", 0x4701), NvGpuIoctlZcullGetCtxSize }, + { ("/dev/nvhost-ctrl-gpu", 0x4702), NvGpuIoctlZcullGetInfo }, + { ("/dev/nvhost-ctrl-gpu", 0x4705), NvGpuIoctlGetCharacteristics }, + { ("/dev/nvhost-ctrl-gpu", 0x4706), NvGpuIoctlGetTpcMasks }, + { ("/dev/nvhost-ctrl-gpu", 0x4714), NvGpuIoctlZbcGetActiveSlotMask }, + { ("/dev/nvhost-gpu", 0x4714), NvMapIoctlChannelSetUserData }, + { ("/dev/nvhost-gpu", 0x4801), NvMapIoctlChannelSetNvMap }, + { ("/dev/nvhost-gpu", 0x4808), NvMapIoctlChannelSubmitGpFifo }, + { ("/dev/nvhost-gpu", 0x4809), NvMapIoctlChannelAllocObjCtx }, + { ("/dev/nvhost-gpu", 0x480b), NvMapIoctlChannelZcullBind }, + { ("/dev/nvhost-gpu", 0x480c), NvMapIoctlChannelSetErrorNotifier }, + { ("/dev/nvhost-gpu", 0x480d), NvMapIoctlChannelSetPriority }, + { ("/dev/nvhost-gpu", 0x481a), NvMapIoctlChannelAllocGpFifoEx2 }, + { ("/dev/nvmap", 0x0101), NvMapIocCreate }, + { ("/dev/nvmap", 0x0103), NvMapIocFromId }, + { ("/dev/nvmap", 0x0104), NvMapIocAlloc }, + { ("/dev/nvmap", 0x0109), NvMapIocParam }, + { ("/dev/nvmap", 0x010e), NvMapIocGetId }, + }; + + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceNvDrv() + { + m_Commands = new Dictionary() + { + { 0, Open }, + { 1, Ioctl }, + { 2, Close }, + { 3, Initialize }, + { 4, QueryEvent }, + { 8, SetClientPid }, + }; + } + + public static long Open(ServiceCtx Context) + { + long NamePtr = Context.Request.SendBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, NamePtr); + + int Fd = Context.Ns.Os.Fds.GenerateId(new FileDesc(Name)); + + Context.ResponseData.Write(Fd); + Context.ResponseData.Write(0); + + return 0; + } + + public static long Ioctl(ServiceCtx Context) + { + int Fd = Context.RequestData.ReadInt32(); + int Cmd = Context.RequestData.ReadInt32() & 0xffff; + + FileDesc FdData = Context.Ns.Os.Fds.GetData(Fd); + + long Position = Context.Request.PtrBuff[0].Position; + + Context.ResponseData.Write(0); + + if (IoctlCmds.TryGetValue((FdData.Name, Cmd), out ServiceProcessIoctl ProcReq)) + { + return ProcReq(Context); + } + else + { + throw new NotImplementedException($"{FdData.Name} {Cmd:x4}"); + } + } + + public static long Close(ServiceCtx Context) + { + int Fd = Context.RequestData.ReadInt32(); + + Context.Ns.Os.Fds.Delete(Fd); + + Context.ResponseData.Write(0); + + return 0; + } + + public static long Initialize(ServiceCtx Context) + { + long TransferMemSize = Context.RequestData.ReadInt64(); + int TransferMemHandle = Context.Request.HandleDesc.ToCopy[0]; + + Context.ResponseData.Write(0); + + return 0; + } + + public static long QueryEvent(ServiceCtx Context) + { + int Fd = Context.RequestData.ReadInt32(); + int EventId = Context.RequestData.ReadInt32(); + + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(0xcafe); + + Context.ResponseData.Write(0); + + return 0; + } + + public static long SetClientPid(ServiceCtx Context) + { + long Pid = Context.RequestData.ReadInt64(); + + Context.ResponseData.Write(0); + + return 0; + } + + private static long NvGpuAsIoctlBindChannel(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + int Fd = Context.Memory.ReadInt32(Position); + + return 0; + } + + private static long NvGpuAsIoctlAllocSpace(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + + int Pages = Reader.ReadInt32(); + int PageSize = Reader.ReadInt32(); + int Flags = Reader.ReadInt32(); + int Padding = Reader.ReadInt32(); + long Align = Reader.ReadInt64(); + + if ((Flags & 1) != 0) + { + Align = Context.Ns.Gpu.ReserveMemory(Align, (long)Pages * PageSize, 1); + } + else + { + Align = Context.Ns.Gpu.ReserveMemory((long)Pages * PageSize, Align); + } + + Context.Memory.WriteInt64(Position + 0x10, Align); + + return 0; + } + + private static long NvGpuAsIoctlMapBufferEx(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + + int Flags = Reader.ReadInt32(); + int Kind = Reader.ReadInt32(); + int Handle = Reader.ReadInt32(); + int PageSize = Reader.ReadInt32(); + long BuffAddr = Reader.ReadInt64(); + long MapSize = Reader.ReadInt64(); + long Offset = Reader.ReadInt64(); + + HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); + + if (NvMap != null) + { + if ((Flags & 1) != 0) + { + Offset = Context.Ns.Gpu.MapMemory(NvMap.Address, Offset, NvMap.Size); + } + else + { + Offset = Context.Ns.Gpu.MapMemory(NvMap.Address, NvMap.Size); + } + } + + Context.Memory.WriteInt64(Position + 0x20, Offset); + + return 0; + } + + private static long NvGpuAsIoctlGetVaRegions(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + MemWriter Writer = new MemWriter(Context.Memory, Position); + + long Unused = Reader.ReadInt64(); + int BuffSize = Reader.ReadInt32(); + int Padding = Reader.ReadInt32(); + + BuffSize = 0x30; + + Writer.WriteInt64(Unused); + Writer.WriteInt32(BuffSize); + Writer.WriteInt32(Padding); + + Writer.WriteInt64(0); + Writer.WriteInt32(0); + Writer.WriteInt32(0); + Writer.WriteInt64(0); + + Writer.WriteInt64(0); + Writer.WriteInt32(0); + Writer.WriteInt32(0); + Writer.WriteInt64(0); + + return 0; + } + + private static long NvGpuAsIoctlInitializeEx(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + + int BigPageSize = Reader.ReadInt32(); + int AsFd = Reader.ReadInt32(); + int Flags = Reader.ReadInt32(); + int Reserved = Reader.ReadInt32(); + long Unknown10 = Reader.ReadInt64(); + long Unknown18 = Reader.ReadInt64(); + long Unknown20 = Reader.ReadInt64(); + + return 0; + } + + private static long NvHostIoctlCtrlGetConfig(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + MemWriter Writer = new MemWriter(Context.Memory, Position + 0x82); + + for (int Index = 0; Index < 0x101; Index++) + { + Writer.WriteByte(0); + } + + return 0; + } + + private static long NvHostIoctlCtrlEventWait(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + + int SyncPtId = Reader.ReadInt32(); + int Threshold = Reader.ReadInt32(); + int Timeout = Reader.ReadInt32(); + int Value = Reader.ReadInt32(); + + Context.Memory.WriteInt32(Position + 0xc, 0xcafe); + + return 0; + } + + private static long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + Context.Memory.WriteInt32(Position, 1); + + return 0; + } + + private static long NvGpuIoctlZcullGetInfo(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemWriter Writer = new MemWriter(Context.Memory, Position); + + Writer.WriteInt32(0); + Writer.WriteInt32(0); + Writer.WriteInt32(0); + Writer.WriteInt32(0); + Writer.WriteInt32(0); + Writer.WriteInt32(0); + Writer.WriteInt32(0); + Writer.WriteInt32(0); + Writer.WriteInt32(0); + Writer.WriteInt32(0); + + return 0; + } + + private static long NvGpuIoctlGetCharacteristics(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + MemWriter Writer = new MemWriter(Context.Memory, Position); + + //Note: We should just ignore the BuffAddr, because official code + //does __memcpy_device from Position + 0x10 to BuffAddr. + long BuffSize = Reader.ReadInt64(); + long BuffAddr = Reader.ReadInt64(); + + BuffSize = 0xa0; + + Writer.WriteInt64(BuffSize); + Writer.WriteInt64(BuffAddr); + Writer.WriteInt32(0x120); //NVGPU_GPU_ARCH_GM200 + Writer.WriteInt32(0xb); //NVGPU_GPU_IMPL_GM20B + Writer.WriteInt32(0xa1); + Writer.WriteInt32(1); + Writer.WriteInt64(0x40000); + Writer.WriteInt64(0); + Writer.WriteInt32(2); + Writer.WriteInt32(0x20); //NVGPU_GPU_BUS_TYPE_AXI + Writer.WriteInt32(0x20000); + Writer.WriteInt32(0x20000); + Writer.WriteInt32(0x1b); + Writer.WriteInt32(0x30000); + Writer.WriteInt32(1); + Writer.WriteInt32(0x503); + Writer.WriteInt32(0x503); + Writer.WriteInt32(0x80); + Writer.WriteInt32(0x28); + Writer.WriteInt32(0); + Writer.WriteInt64(0x55); + Writer.WriteInt32(0x902d); //FERMI_TWOD_A + Writer.WriteInt32(0xb197); //MAXWELL_B + Writer.WriteInt32(0xb1c0); //MAXWELL_COMPUTE_B + Writer.WriteInt32(0xb06f); //MAXWELL_CHANNEL_GPFIFO_A + Writer.WriteInt32(0xa140); //KEPLER_INLINE_TO_MEMORY_B + Writer.WriteInt32(0xb0b5); //MAXWELL_DMA_COPY_A + Writer.WriteInt32(1); + Writer.WriteInt32(0); + Writer.WriteInt32(2); + Writer.WriteInt32(1); + Writer.WriteInt32(0); + Writer.WriteInt32(1); + Writer.WriteInt32(0x21d70); + Writer.WriteInt32(0); + Writer.WriteByte((byte)'g'); + Writer.WriteByte((byte)'m'); + Writer.WriteByte((byte)'2'); + Writer.WriteByte((byte)'0'); + Writer.WriteByte((byte)'b'); + Writer.WriteByte((byte)'\0'); + Writer.WriteByte((byte)'\0'); + Writer.WriteByte((byte)'\0'); + Writer.WriteInt64(0); + + return 0; + } + + private static long NvGpuIoctlGetTpcMasks(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + + int MaskBuffSize = Reader.ReadInt32(); + int Reserved = Reader.ReadInt32(); + long MaskBuffAddr = Reader.ReadInt64(); + long Unknown = Reader.ReadInt64(); + + return 0; + } + + private static long NvGpuIoctlZbcGetActiveSlotMask(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + Context.Memory.WriteInt32(Position + 0, 7); + Context.Memory.WriteInt32(Position + 4, 1); + + return 0; + } + + private static long NvMapIoctlChannelSetUserData(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + return 0; + } + + private static long NvMapIoctlChannelSetNvMap(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + int Fd = Context.Memory.ReadInt32(Position); + + return 0; + } + + private static long NvMapIoctlChannelSubmitGpFifo(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + MemWriter Writer = new MemWriter(Context.Memory, Position + 0x10); + + long GpFifo = Reader.ReadInt64(); + int Count = Reader.ReadInt32(); + int Flags = Reader.ReadInt32(); + int FenceId = Reader.ReadInt32(); + int FenceVal = Reader.ReadInt32(); + + for (int Index = 0; Index < Count; Index++) + { + long GpFifoHdr = Reader.ReadInt64(); + + long GpuAddr = GpFifoHdr & 0xffffffffff; + + int Size = (int)(GpFifoHdr >> 40) & 0x7ffffc; + + long CpuAddr = Context.Ns.Gpu.GetCpuAddr(GpuAddr); + + if (CpuAddr != -1) + { + byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, CpuAddr, Size); + + NsGpuPBEntry[] PushBuffer = NsGpuPBEntry.DecodePushBuffer(Data); + + Context.Ns.Gpu.ProcessPushBuffer(PushBuffer, Context.Memory); + } + } + + Writer.WriteInt32(0); + Writer.WriteInt32(0); + + return 0; + } + + private static long NvMapIoctlChannelAllocObjCtx(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + int ClassNum = Context.Memory.ReadInt32(Position + 0); + int Flags = Context.Memory.ReadInt32(Position + 4); + + Context.Memory.WriteInt32(Position + 8, 0); + + return 0; + } + + private static long NvMapIoctlChannelZcullBind(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + + long GpuVa = Reader.ReadInt64(); + int Mode = Reader.ReadInt32(); + int Padding = Reader.ReadInt32(); + + return 0; + } + + private static long NvMapIoctlChannelSetErrorNotifier(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + + long Offset = Reader.ReadInt64(); + long Size = Reader.ReadInt64(); + int Mem = Reader.ReadInt32(); + int Padding = Reader.ReadInt32(); + + return 0; + } + + private static long NvMapIoctlChannelSetPriority(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + int Priority = Context.Memory.ReadInt32(Position); + + return 0; + } + + private static long NvMapIoctlChannelAllocGpFifoEx2(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + MemReader Reader = new MemReader(Context.Memory, Position); + MemWriter Writer = new MemWriter(Context.Memory, Position + 0xc); + + int Count = Reader.ReadInt32(); + int Flags = Reader.ReadInt32(); + int Unknown8 = Reader.ReadInt32(); + long Fence = Reader.ReadInt64(); + int Unknown14 = Reader.ReadInt32(); + int Unknown18 = Reader.ReadInt32(); + + Writer.WriteInt32(0); + Writer.WriteInt32(0); + + return 0; + } + + private static long NvMapIocCreate(ServiceCtx Context) + { + long Position = Context.Request.GetSendBuffPtr(); + + int Size = Context.Memory.ReadInt32(Position); + + int Id = Context.Ns.Os.NvMapIds.GenerateId(); + + int Handle = Context.Ns.Os.Handles.GenerateId(new HNvMap(Id, Size)); + + Context.Memory.WriteInt32(Position + 4, Handle); + + return 0; + } + + private static long NvMapIocFromId(ServiceCtx Context) + { + long Position = Context.Request.GetSendBuffPtr(); + + int Id = Context.Memory.ReadInt32(Position); + + int Handle = -1; + + foreach (KeyValuePair KV in Context.Ns.Os.Handles) + { + if (KV.Value is HNvMap NvMap && NvMap.Id == Id) + { + Handle = KV.Key; + + break; + } + } + + Context.Memory.WriteInt32(Position + 4, Handle); + + return 0; + } + + private static long NvMapIocAlloc(ServiceCtx Context) + { + long Position = Context.Request.GetSendBuffPtr(); + + MemReader Reader = new MemReader(Context.Memory, Position); + + int Handle = Reader.ReadInt32(); + int HeapMask = Reader.ReadInt32(); + int Flags = Reader.ReadInt32(); + int Align = Reader.ReadInt32(); + byte Kind = (byte)Reader.ReadInt64(); + long Addr = Reader.ReadInt64(); + + HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); + + if (NvMap != null) + { + NvMap.Address = Addr; + NvMap.Align = Align; + NvMap.Kind = Kind; + } + + Logging.Debug($"NvMapIocAlloc at {NvMap.Address:x16}"); + + return 0; + } + + private static long NvMapIocParam(ServiceCtx Context) + { + long Position = Context.Request.GetSendBuffPtr(); + + MemReader Reader = new MemReader(Context.Memory, Position); + + int Handle = Reader.ReadInt32(); + int Param = Reader.ReadInt32(); + + HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); + + int Response = 0; + + switch (Param) + { + case 1: Response = NvMap.Size; break; + case 2: Response = NvMap.Align; break; + case 4: Response = 0x40000000; break; + case 5: Response = NvMap.Kind; break; + } + + Context.Memory.WriteInt32(Position + 8, Response); + + return 0; + } + + private static long NvMapIocGetId(ServiceCtx Context) + { + long Position = Context.Request.GetSendBuffPtr(); + + int Handle = Context.Memory.ReadInt32(Position + 4); + + HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); + + Context.Memory.WriteInt32(Position, NvMap.Id); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs b/Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs new file mode 100644 index 00000000..ff71838a --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs @@ -0,0 +1,24 @@ +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.GenerateObjectId(Obj)); + } + else + { + HSessionObj HndData = new HSessionObj(Context.Session, Obj); + + int VHandle = Context.Ns.Os.Handles.GenerateId(HndData); + + Context.Response.HandleDesc = IpcHandleDesc.MakeMove(VHandle); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs b/Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs new file mode 100644 index 00000000..4eb92d31 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs @@ -0,0 +1,20 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Pctl +{ + class IParentalControlService : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IParentalControlService() + { + m_Commands = new Dictionary() + { + //... + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs b/Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs new file mode 100644 index 00000000..2d5e22a4 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs @@ -0,0 +1,29 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Pctl +{ + class ServicePctl : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServicePctl() + { + m_Commands = new Dictionary() + { + { 0, CreateService } + }; + } + + public static long CreateService(ServiceCtx Context) + { + MakeObject(Context, new IParentalControlService()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs b/Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs new file mode 100644 index 00000000..abc34ed2 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs @@ -0,0 +1,51 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Pl +{ + class ServicePl : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServicePl() + { + m_Commands = new Dictionary() + { + { 1, GetLoadState }, + { 2, GetFontSize }, + { 3, GetSharedMemoryAddressOffset }, + { 4, GetSharedMemoryNativeHandle } + }; + } + + public static long GetLoadState(ServiceCtx Context) + { + Context.ResponseData.Write(1); //Loaded + + return 0; + } + + public static long GetFontSize(ServiceCtx Context) + { + Context.ResponseData.Write(Horizon.FontSize); + + return 0; + } + + public static long GetSharedMemoryAddressOffset(ServiceCtx Context) + { + Context.ResponseData.Write(0); + + return 0; + } + + public static long GetSharedMemoryNativeHandle(ServiceCtx Context) + { + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Context.Ns.Os.FontHandle); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs b/Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs new file mode 100644 index 00000000..e9613050 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs @@ -0,0 +1,50 @@ +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.Friend; +using Ryujinx.Core.OsHle.IpcServices.FspSrv; +using Ryujinx.Core.OsHle.IpcServices.Hid; +using Ryujinx.Core.OsHle.IpcServices.Lm; +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.Sm; +using Ryujinx.Core.OsHle.IpcServices.Time; +using Ryujinx.Core.OsHle.IpcServices.Vi; +using System; + +namespace Ryujinx.Core.OsHle.IpcServices +{ + static class ServiceFactory + { + public static IIpcService MakeService(string Name) + { + switch (Name) + { + case "acc:u0": return new ServiceAcc(); + 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 "friend:a": return new ServiceFriend(); + case "fsp-srv": return new ServiceFspSrv(); + case "hid": return new ServiceHid(); + case "lm": return new ServiceLm(); + 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 "sm:": return new ServiceSm(); + case "time:s": return new ServiceTime(); + case "time:u": return new ServiceTime(); + case "vi:m": return new ServiceVi(); + } + + throw new NotImplementedException(Name); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs b/Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs new file mode 100644 index 00000000..05e409b0 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs @@ -0,0 +1,46 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Set +{ + class ServiceSet : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceSet() + { + m_Commands = new Dictionary() + { + { 1, GetAvailableLanguageCodes } + }; + } + + private const int LangCodesCount = 13; + + public static long GetAvailableLanguageCodes(ServiceCtx Context) + { + int PtrBuffSize = Context.RequestData.ReadInt32(); + + if (Context.Request.RecvListBuff.Count > 0) + { + long Position = Context.Request.RecvListBuff[0].Position; + short Size = Context.Request.RecvListBuff[0].Size; + + //This should return an array of ints with values matching the LanguageCode enum. + byte[] Data = new byte[Size]; + + Data[0] = 0; + Data[1] = 1; + + AMemoryHelper.WriteBytes(Context.Memory, Position, Data); + } + + Context.ResponseData.Write(LangCodesCount); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs b/Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs new file mode 100644 index 00000000..a5f1b329 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs @@ -0,0 +1,67 @@ +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Sm +{ + class ServiceSm : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceSm() + { + m_Commands = new Dictionary() + { + { 0, Initialize }, + { 1, GetService } + }; + } + + private const int SmNotInitialized = 0x415; + + public long Initialize(ServiceCtx Context) + { + Context.Session.Initialize(); + + return 0; + } + + public long GetService(ServiceCtx Context) + { + //Only for kernel version > 3.0.0. + if (!Context.Session.IsInitialized) + { + //return SmNotInitialized; + } + + string Name = string.Empty; + + for (int Index = 0; Index < 8 && + Context.RequestData.BaseStream.Position < + Context.RequestData.BaseStream.Length; Index++) + { + byte Chr = Context.RequestData.ReadByte(); + + if (Chr >= 0x20 && Chr < 0x7f) + { + Name += (char)Chr; + } + } + + if (Name == string.Empty) + { + return 0; + } + + HSession Session = new HSession(ServiceFactory.MakeService(Name)); + + int Handle = Context.Ns.Os.Handles.GenerateId(Session); + + Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs b/Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs new file mode 100644 index 00000000..d20e4378 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs @@ -0,0 +1,20 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Time +{ + class ISteadyClock : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ISteadyClock() + { + m_Commands = new Dictionary() + { + //... + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs b/Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs new file mode 100644 index 00000000..4d4493da --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs @@ -0,0 +1,42 @@ +using Ryujinx.Core.OsHle.Ipc; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Time +{ + class ISystemClock : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + private SystemClockType ClockType; + + public ISystemClock(SystemClockType ClockType) + { + m_Commands = new Dictionary() + { + { 0, GetCurrentTime } + }; + + this.ClockType = ClockType; + } + + public long GetCurrentTime(ServiceCtx Context) + { + DateTime CurrentTime = DateTime.Now; + + if (ClockType == SystemClockType.User || + ClockType == SystemClockType.Network) + { + CurrentTime = CurrentTime.ToUniversalTime(); + } + + Context.ResponseData.Write((long)(DateTime.Now - Epoch).TotalSeconds); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs b/Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs new file mode 100644 index 00000000..9875fa2f --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs @@ -0,0 +1,20 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Time +{ + class ITimeZoneService : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ITimeZoneService() + { + m_Commands = new Dictionary() + { + //... + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs b/Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs new file mode 100644 index 00000000..43f28bb8 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs @@ -0,0 +1,62 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Time +{ + class ServiceTime : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceTime() + { + m_Commands = new Dictionary() + { + { 0, GetStandardUserSystemClock }, + { 1, GetStandardNetworkSystemClock }, + { 2, GetStandardSteadyClock }, + { 3, GetTimeZoneService }, + { 4, GetStandardLocalSystemClock } + }; + } + + public long GetStandardUserSystemClock(ServiceCtx Context) + { + MakeObject(Context, new ISystemClock(SystemClockType.User)); + + return 0; + } + + public long GetStandardNetworkSystemClock(ServiceCtx Context) + { + MakeObject(Context, new ISystemClock(SystemClockType.Network)); + + return 0; + } + + public long GetStandardSteadyClock(ServiceCtx Context) + { + MakeObject(Context, new ISteadyClock()); + + return 0; + } + + public long GetTimeZoneService(ServiceCtx Context) + { + MakeObject(Context, new ITimeZoneService()); + + return 0; + } + + public long GetStandardLocalSystemClock(ServiceCtx Context) + { + MakeObject(Context, new ISystemClock(SystemClockType.Local)); + + return 0; + } + + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs b/Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs new file mode 100644 index 00000000..2314942a --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs @@ -0,0 +1,9 @@ +namespace Ryujinx.Core.OsHle.IpcServices.Time +{ + enum SystemClockType + { + User, + Network, + Local + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs b/Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs new file mode 100644 index 00000000..a899cdd5 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs @@ -0,0 +1,176 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; +using System.IO; + +using static Ryujinx.Core.OsHle.IpcServices.Android.Parcel; +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Vi +{ + class IApplicationDisplayService : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IApplicationDisplayService() + { + m_Commands = new Dictionary() + { + { 100, GetRelayService }, + { 101, GetSystemDisplayService }, + { 102, GetManagerDisplayService }, + { 103, GetIndirectDisplayTransactionService }, + { 1010, OpenDisplay }, + { 2020, OpenLayer }, + { 2030, CreateStrayLayer }, + { 2101, SetLayerScalingMode }, + { 5202, GetDisplayVSyncEvent } + }; + } + + public long GetRelayService(ServiceCtx Context) + { + MakeObject(Context, new IHOSBinderDriver()); + + return 0; + } + + public long GetSystemDisplayService(ServiceCtx Context) + { + MakeObject(Context, new ISystemDisplayService()); + + return 0; + } + + public long GetManagerDisplayService(ServiceCtx Context) + { + MakeObject(Context, new IManagerDisplayService()); + + return 0; + } + + public long GetIndirectDisplayTransactionService(ServiceCtx Context) + { + MakeObject(Context, new IHOSBinderDriver()); + + return 0; + } + + public long OpenDisplay(ServiceCtx Context) + { + string Name = GetDisplayName(Context); + + long DisplayId = Context.Ns.Os.Displays.GenerateId(new Display(Name)); + + Context.ResponseData.Write(DisplayId); + + return 0; + } + + public long OpenLayer(ServiceCtx Context) + { + long LayerId = Context.RequestData.ReadInt64(); + long UserId = Context.RequestData.ReadInt64(); + + long ParcelPtr = Context.Request.ReceiveBuff[0].Position; + + byte[] Parcel = MakeIGraphicsBufferProducer(ParcelPtr); + + AMemoryHelper.WriteBytes(Context.Memory, ParcelPtr, Parcel); + + Context.ResponseData.Write((long)Parcel.Length); + + return 0; + } + + public long CreateStrayLayer(ServiceCtx Context) + { + long LayerFlags = Context.RequestData.ReadInt64(); + long DisplayId = Context.RequestData.ReadInt64(); + + long ParcelPtr = Context.Request.ReceiveBuff[0].Position; + + Display Disp = Context.Ns.Os.Displays.GetData((int)DisplayId); + + byte[] Parcel = MakeIGraphicsBufferProducer(ParcelPtr); + + AMemoryHelper.WriteBytes(Context.Memory, ParcelPtr, Parcel); + + Context.ResponseData.Write(0L); + Context.ResponseData.Write((long)Parcel.Length); + + return 0; + } + + public long SetLayerScalingMode(ServiceCtx Context) + { + int ScalingMode = Context.RequestData.ReadInt32(); + long Unknown = Context.RequestData.ReadInt64(); + + return 0; + } + + public long GetDisplayVSyncEvent(ServiceCtx Context) + { + string Name = GetDisplayName(Context); + + int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); + + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); + + return 0; + } + + private byte[] MakeIGraphicsBufferProducer(long BasePtr) + { + long Id = 0x20; + long CookiePtr = 0L; + + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + //flat_binder_object (size is 0x28) + Writer.Write(2); //Type (BINDER_TYPE_WEAK_BINDER) + Writer.Write(0); //Flags + Writer.Write((int)(Id >> 0)); + Writer.Write((int)(Id >> 32)); + Writer.Write((int)(CookiePtr >> 0)); + Writer.Write((int)(CookiePtr >> 32)); + Writer.Write((byte)'d'); + Writer.Write((byte)'i'); + Writer.Write((byte)'s'); + Writer.Write((byte)'p'); + Writer.Write((byte)'d'); + Writer.Write((byte)'r'); + Writer.Write((byte)'v'); + Writer.Write((byte)'\0'); + Writer.Write(0L); //Pad + + return MakeParcel(MS.ToArray(), new byte[] { 0, 0, 0, 0 }); + } + } + + private string GetDisplayName(ServiceCtx Context) + { + string Name = string.Empty; + + for (int Index = 0; Index < 8 && + Context.RequestData.BaseStream.Position < + Context.RequestData.BaseStream.Length; Index++) + { + byte Chr = Context.RequestData.ReadByte(); + + if (Chr >= 0x20 && Chr < 0x7f) + { + Name += (char)Chr; + } + } + + return Name; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs new file mode 100644 index 00000000..a89c1df8 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs @@ -0,0 +1,76 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using Ryujinx.Core.OsHle.IpcServices.Android; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Vi +{ + class IHOSBinderDriver : IIpcService, IDisposable + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private NvFlinger Flinger; + + public IHOSBinderDriver() + { + m_Commands = new Dictionary() + { + { 0, TransactParcel }, + { 1, AdjustRefcount }, + { 2, GetNativeHandle } + }; + + Flinger = new NvFlinger(); + } + + public long TransactParcel(ServiceCtx Context) + { + int Id = Context.RequestData.ReadInt32(); + int Code = Context.RequestData.ReadInt32(); + + long DataPos = Context.Request.SendBuff[0].Position; + long DataSize = Context.Request.SendBuff[0].Size; + + byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, DataPos, (int)DataSize); + + Data = Parcel.GetParcelData(Data); + + return Flinger.ProcessParcelRequest(Context, Data, Code); + } + + public long AdjustRefcount(ServiceCtx Context) + { + int Id = Context.RequestData.ReadInt32(); + int AddVal = Context.RequestData.ReadInt32(); + int Type = Context.RequestData.ReadInt32(); + + return 0; + } + + public long GetNativeHandle(ServiceCtx Context) + { + int Id = Context.RequestData.ReadInt32(); + uint Unk = Context.RequestData.ReadUInt32(); + + Context.Response.HandleDesc = IpcHandleDesc.MakeMove(0xbadcafe); + + return 0; + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + Flinger.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs b/Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs new file mode 100644 index 00000000..5adee78d --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs @@ -0,0 +1,33 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Vi +{ + class IManagerDisplayService : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IManagerDisplayService() + { + m_Commands = new Dictionary() + { + { 2010, CreateManagedLayer }, + { 6000, AddToLayerStack } + }; + } + + public static long CreateManagedLayer(ServiceCtx Context) + { + Context.ResponseData.Write(0L); //LayerId + + return 0; + } + + public static long AddToLayerStack(ServiceCtx Context) + { + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs b/Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs new file mode 100644 index 00000000..d87fcbf6 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs @@ -0,0 +1,25 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Vi +{ + class ISystemDisplayService : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ISystemDisplayService() + { + m_Commands = new Dictionary() + { + { 2205, SetLayerZ } + }; + } + + public static long SetLayerZ(ServiceCtx Context) + { + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs b/Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs new file mode 100644 index 00000000..2c3dd2a3 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs @@ -0,0 +1,31 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Vi +{ + class ServiceVi : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceVi() + { + m_Commands = new Dictionary() + { + { 2, GetDisplayService } + }; + } + + public long GetDisplayService(ServiceCtx Context) + { + int Unknown = Context.RequestData.ReadInt32(); + + MakeObject(Context, new IApplicationDisplayService()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Acc/IManagerForApplication.cs b/Ryujinx.Core/OsHle/Objects/Acc/IManagerForApplication.cs deleted file mode 100644 index afbfab24..00000000 --- a/Ryujinx.Core/OsHle/Objects/Acc/IManagerForApplication.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Acc -{ - class IManagerForApplication : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IManagerForApplication() - { - m_Commands = new Dictionary() - { - { 0, CheckAvailability }, - { 1, GetAccountId } - }; - } - - public long CheckAvailability(ServiceCtx Context) - { - return 0; - } - - public long GetAccountId(ServiceCtx Context) - { - Context.ResponseData.Write(0xcafeL); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs b/Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs deleted file mode 100644 index 94d17183..00000000 --- a/Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Acc -{ - class IProfile : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IProfile() - { - m_Commands = new Dictionary() - { - { 1, GetBase } - }; - } - - public long GetBase(ServiceCtx Context) - { - Context.ResponseData.Write(0L); - Context.ResponseData.Write(0L); - Context.ResponseData.Write(0L); - Context.ResponseData.Write(0L); - Context.ResponseData.Write(0L); - Context.ResponseData.Write(0L); - Context.ResponseData.Write(0L); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/IApplicationFunctions.cs b/Ryujinx.Core/OsHle/Objects/Am/IApplicationFunctions.cs deleted file mode 100644 index 939ad248..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/IApplicationFunctions.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; -using System.IO; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class IApplicationFunctions : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IApplicationFunctions() - { - m_Commands = new Dictionary() - { - { 1, PopLaunchParameter }, - { 20, EnsureSaveData }, - { 21, GetDesiredLanguage }, - { 40, NotifyRunning } - }; - } - - private const uint LaunchParamsMagic = 0xc79497ca; - - public long PopLaunchParameter(ServiceCtx Context) - { - //Only the first 0x18 bytes of the Data seems to be actually used. - MakeObject(Context, new IStorage(MakeLaunchParams())); - - return 0; - } - - public long EnsureSaveData(ServiceCtx Context) - { - long UIdLow = Context.RequestData.ReadInt64(); - long UIdHigh = Context.RequestData.ReadInt64(); - - Context.ResponseData.Write(0L); - - return 0; - } - - public long GetDesiredLanguage(ServiceCtx Context) - { - //This is an enumerator where each number is a differnet language. - //0 is Japanese and 1 is English, need to figure out the other codes. - Context.ResponseData.Write(1L); - - return 0; - } - - public long NotifyRunning(ServiceCtx Context) - { - Context.ResponseData.Write(1); - - return 0; - } - - private byte[] MakeLaunchParams() - { - //Size needs to be at least 0x88 bytes otherwise application errors. - using (MemoryStream MS = new MemoryStream()) - { - BinaryWriter Writer = new BinaryWriter(MS); - - MS.SetLength(0x88); - - Writer.Write(LaunchParamsMagic); - Writer.Write(1); //IsAccountSelected? Only lower 8 bits actually used. - Writer.Write(1L); //User Id Low (note: User Id needs to be != 0) - Writer.Write(0L); //User Id High - - return MS.ToArray(); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs b/Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs deleted file mode 100644 index 4a164daf..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs +++ /dev/null @@ -1,85 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class IApplicationProxy : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IApplicationProxy() - { - m_Commands = new Dictionary() - { - { 0, GetCommonStateGetter }, - { 1, GetSelfController }, - { 2, GetWindowController }, - { 3, GetAudioController }, - { 4, GetDisplayController }, - { 11, GetLibraryAppletCreator }, - { 20, GetApplicationFunctions }, - { 1000, GetDebugFunctions } - }; - } - - public long GetCommonStateGetter(ServiceCtx Context) - { - MakeObject(Context, new ICommonStateGetter()); - - return 0; - } - - public long GetSelfController(ServiceCtx Context) - { - MakeObject(Context, new ISelfController()); - - return 0; - } - - public long GetWindowController(ServiceCtx Context) - { - MakeObject(Context, new IWindowController()); - - return 0; - } - - public long GetAudioController(ServiceCtx Context) - { - MakeObject(Context, new IAudioController()); - - return 0; - } - - public long GetDisplayController(ServiceCtx Context) - { - MakeObject(Context, new IDisplayController()); - - return 0; - } - - public long GetLibraryAppletCreator(ServiceCtx Context) - { - MakeObject(Context, new ILibraryAppletCreator()); - - return 0; - } - - public long GetApplicationFunctions(ServiceCtx Context) - { - MakeObject(Context, new IApplicationFunctions()); - - return 0; - } - - public long GetDebugFunctions(ServiceCtx Context) - { - MakeObject(Context, new IDebugFunctions()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs b/Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs deleted file mode 100644 index c37042fd..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class IAudioController : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IAudioController() - { - m_Commands = new Dictionary() - { - //... - }; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/ICommonStateGetter.cs b/Ryujinx.Core/OsHle/Objects/Am/ICommonStateGetter.cs deleted file mode 100644 index 83d61fa6..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/ICommonStateGetter.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class ICommonStateGetter : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public ICommonStateGetter() - { - m_Commands = new Dictionary() - { - { 0, GetEventHandle }, - { 1, ReceiveMessage }, - { 5, GetOperationMode }, - { 6, GetPerformanceMode }, - { 9, GetCurrentFocusState }, - }; - } - - private enum FocusState - { - InFocus = 1, - OutOfFocus = 2 - } - - private enum OperationMode - { - Handheld = 0, - Docked = 1 - } - - public long GetEventHandle(ServiceCtx Context) - { - Context.ResponseData.Write(0L); - - return 0; - } - - public long ReceiveMessage(ServiceCtx Context) - { - //Program expects 0xF at 0x17ae70 on puyo sdk, - //otherwise runs on a infinite loop until it reads said value. - //What it means is still unknown. - Context.ResponseData.Write(0xfL); - - return 0; //0x680; - } - - public long GetOperationMode(ServiceCtx Context) - { - Context.ResponseData.Write((byte)OperationMode.Handheld); - - return 0; - } - - public long GetPerformanceMode(ServiceCtx Context) - { - Context.ResponseData.Write((byte)0); - - return 0; - } - - public long GetCurrentFocusState(ServiceCtx Context) - { - Context.ResponseData.Write((byte)FocusState.InFocus); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs b/Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs deleted file mode 100644 index d04d8363..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class IDebugFunctions : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IDebugFunctions() - { - m_Commands = new Dictionary() - { - //... - }; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/IDisplayController.cs b/Ryujinx.Core/OsHle/Objects/Am/IDisplayController.cs deleted file mode 100644 index 9eafa70d..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/IDisplayController.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class IDisplayController : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IDisplayController() - { - m_Commands = new Dictionary() - { - //... - }; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/ILibraryAppletCreator.cs b/Ryujinx.Core/OsHle/Objects/Am/ILibraryAppletCreator.cs deleted file mode 100644 index 10e0f4f4..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/ILibraryAppletCreator.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class ILibraryAppletCreator : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public ILibraryAppletCreator() - { - m_Commands = new Dictionary() - { - //... - }; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/IParentalControlService.cs b/Ryujinx.Core/OsHle/Objects/Am/IParentalControlService.cs deleted file mode 100644 index 1feacfa6..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/IParentalControlService.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class IParentalControlService : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IParentalControlService() - { - m_Commands = new Dictionary() - { - //... - }; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs b/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs deleted file mode 100644 index 712874e8..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class ISelfController : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public ISelfController() - { - m_Commands = new Dictionary() - { - { 10, SetScreenShotPermission }, - { 11, SetOperationModeChangedNotification }, - { 12, SetPerformanceModeChangedNotification }, - { 13, SetFocusHandlingMode }, - { 16, SetOutOfFocusSuspendingEnabled } - }; - } - - public long SetScreenShotPermission(ServiceCtx Context) - { - bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; - - return 0; - } - - public long SetOperationModeChangedNotification(ServiceCtx Context) - { - bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; - - return 0; - } - - public long SetPerformanceModeChangedNotification(ServiceCtx Context) - { - bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; - - return 0; - } - - public long SetFocusHandlingMode(ServiceCtx Context) - { - bool Flag1 = Context.RequestData.ReadByte() != 0 ? true : false; - bool Flag2 = Context.RequestData.ReadByte() != 0 ? true : false; - bool Flag3 = Context.RequestData.ReadByte() != 0 ? true : false; - - return 0; - } - - public long SetOutOfFocusSuspendingEnabled(ServiceCtx Context) - { - bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/IStorage.cs b/Ryujinx.Core/OsHle/Objects/Am/IStorage.cs deleted file mode 100644 index b30059ba..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/IStorage.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class IStorage : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public byte[] Data { get; private set; } - - public IStorage(byte[] Data) - { - m_Commands = new Dictionary() - { - { 0, Open } - }; - - this.Data = Data; - } - - public long Open(ServiceCtx Context) - { - MakeObject(Context, new IStorageAccessor(this)); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs b/Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs deleted file mode 100644 index df260cc3..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs +++ /dev/null @@ -1,62 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Ipc; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class IStorageAccessor : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - private IStorage Storage; - - public IStorageAccessor(IStorage Storage) - { - m_Commands = new Dictionary() - { - { 0, GetSize }, - { 11, Read } - }; - - this.Storage = Storage; - } - - public long GetSize(ServiceCtx Context) - { - Context.ResponseData.Write((long)Storage.Data.Length); - - return 0; - } - - public long Read(ServiceCtx Context) - { - long ReadPosition = Context.RequestData.ReadInt64(); - - if (Context.Request.RecvListBuff.Count > 0) - { - long Position = Context.Request.RecvListBuff[0].Position; - short Size = Context.Request.RecvListBuff[0].Size; - - byte[] Data; - - if (Storage.Data.Length > Size) - { - Data = new byte[Size]; - - Buffer.BlockCopy(Storage.Data, 0, Data, 0, Size); - } - else - { - Data = Storage.Data; - } - - AMemoryHelper.WriteBytes(Context.Memory, Position, Data); - } - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs b/Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs deleted file mode 100644 index aa6e961e..00000000 --- a/Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Am -{ - class IWindowController : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IWindowController() - { - m_Commands = new Dictionary() - { - { 1, GetAppletResourceUserId }, - { 10, AcquireForegroundRights } - }; - } - - public long GetAppletResourceUserId(ServiceCtx Context) - { - Context.ResponseData.Write(0L); - - return 0; - } - - public long AcquireForegroundRights(ServiceCtx Context) - { - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs b/Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs deleted file mode 100644 index edd11523..00000000 --- a/Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.IO; - -namespace Ryujinx.Core.OsHle.Objects.Android -{ - struct GbpBuffer - { - public int Magic { get; private set; } - public int Width { get; private set; } - public int Height { get; private set; } - public int Stride { get; private set; } - public int Format { get; private set; } - public int Usage { get; private set; } - - public int Pid { get; private set; } - public int RefCount { get; private set; } - - public int FdsCount { get; private set; } - public int IntsCount { get; private set; } - - public byte[] RawData { get; private set; } - - public int Size => RawData.Length + 10 * 4; - - public GbpBuffer(BinaryReader Reader) - { - Magic = Reader.ReadInt32(); - Width = Reader.ReadInt32(); - Height = Reader.ReadInt32(); - Stride = Reader.ReadInt32(); - Format = Reader.ReadInt32(); - Usage = Reader.ReadInt32(); - - Pid = Reader.ReadInt32(); - RefCount = Reader.ReadInt32(); - - FdsCount = Reader.ReadInt32(); - IntsCount = Reader.ReadInt32(); - - RawData = Reader.ReadBytes((FdsCount + IntsCount) * 4); - } - - public void Write(BinaryWriter Writer) - { - Writer.Write(Magic); - Writer.Write(Width); - Writer.Write(Height); - Writer.Write(Stride); - Writer.Write(Format); - Writer.Write(Usage); - - Writer.Write(Pid); - Writer.Write(RefCount); - - Writer.Write(FdsCount); - Writer.Write(IntsCount); - - Writer.Write(RawData); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs b/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs deleted file mode 100644 index 11069cb2..00000000 --- a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs +++ /dev/null @@ -1,395 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Handles; -using System; -using System.IO; -using System.Collections.Generic; -using System.Text; -using System.Threading; - -using static Ryujinx.Core.OsHle.Objects.Android.Parcel; - -namespace Ryujinx.Core.OsHle.Objects.Android -{ - class NvFlinger : IDisposable - { - private delegate long ServiceProcessParcel(ServiceCtx Context, BinaryReader ParcelReader); - - private Dictionary<(string, int), ServiceProcessParcel> Commands; - - private const int BufferQueueCount = 0x40; - private const int BufferQueueMask = BufferQueueCount - 1; - - [Flags] - private enum HalTransform - { - FlipX = 1 << 0, - FlipY = 1 << 1, - Rotate90 = 1 << 2 - } - - private enum BufferState - { - Free, - Dequeued, - Queued, - Acquired - } - - private struct BufferEntry - { - public BufferState State; - - public HalTransform Transform; - - public GbpBuffer Data; - } - - private BufferEntry[] BufferQueue; - - private ManualResetEvent WaitBufferFree; - - private bool KeepRunning; - - public NvFlinger() - { - Commands = new Dictionary<(string, int), ServiceProcessParcel>() - { - { ("android.gui.IGraphicBufferProducer", 0x1), GbpRequestBuffer }, - { ("android.gui.IGraphicBufferProducer", 0x3), GbpDequeueBuffer }, - { ("android.gui.IGraphicBufferProducer", 0x7), GbpQueueBuffer }, - { ("android.gui.IGraphicBufferProducer", 0x8), GbpCancelBuffer }, - { ("android.gui.IGraphicBufferProducer", 0x9), GbpQuery }, - { ("android.gui.IGraphicBufferProducer", 0xa), GbpConnect }, - { ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer } - }; - - BufferQueue = new BufferEntry[0x40]; - - WaitBufferFree = new ManualResetEvent(false); - - KeepRunning = true; - } - - public long ProcessParcelRequest(ServiceCtx Context, byte[] ParcelData, int Code) - { - using (MemoryStream MS = new MemoryStream(ParcelData)) - { - BinaryReader Reader = new BinaryReader(MS); - - MS.Seek(4, SeekOrigin.Current); - - int StrSize = Reader.ReadInt32(); - - string InterfaceName = Encoding.Unicode.GetString(Reader.ReadBytes(StrSize * 2)); - - long Remainder = MS.Position & 0xf; - - if (Remainder != 0) - { - MS.Seek(0x10 - Remainder, SeekOrigin.Current); - } - - MS.Seek(0x50, SeekOrigin.Begin); - - if (Commands.TryGetValue((InterfaceName, Code), out ServiceProcessParcel ProcReq)) - { - Logging.Debug($"{InterfaceName} {ProcReq.Method.Name}"); - - return ProcReq(Context, Reader); - } - else - { - throw new NotImplementedException($"{InterfaceName} {Code}"); - } - } - } - - private long GbpRequestBuffer(ServiceCtx Context, BinaryReader ParcelReader) - { - int Slot = ParcelReader.ReadInt32(); - - using (MemoryStream MS = new MemoryStream()) - { - BinaryWriter Writer = new BinaryWriter(MS); - - BufferEntry Entry = BufferQueue[Slot]; - - int BufferCount = 1; //? - long BufferSize = Entry.Data.Size; - - Writer.Write(BufferCount); - Writer.Write(BufferSize); - - Entry.Data.Write(Writer); - - Writer.Write(0); - - return MakeReplyParcel(Context, MS.ToArray()); - } - } - - private long GbpDequeueBuffer(ServiceCtx Context, BinaryReader ParcelReader) - { - //TODO: Errors. - int Format = ParcelReader.ReadInt32(); - int Width = ParcelReader.ReadInt32(); - int Height = ParcelReader.ReadInt32(); - int GetTimestamps = ParcelReader.ReadInt32(); - int Usage = ParcelReader.ReadInt32(); - - int Slot = GetFreeSlotBlocking(Width, Height); - - return MakeReplyParcel(Context, Slot, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } - - private long GbpQueueBuffer(ServiceCtx Context, BinaryReader ParcelReader) - { - //TODO: Errors. - int Slot = ParcelReader.ReadInt32(); - int Unknown4 = ParcelReader.ReadInt32(); - int Unknown8 = ParcelReader.ReadInt32(); - int Unknownc = ParcelReader.ReadInt32(); - int Timestamp = ParcelReader.ReadInt32(); - int IsAutoTimestamp = ParcelReader.ReadInt32(); - int CropTop = ParcelReader.ReadInt32(); - int CropLeft = ParcelReader.ReadInt32(); - int CropRight = ParcelReader.ReadInt32(); - int CropBottom = ParcelReader.ReadInt32(); - int ScalingMode = ParcelReader.ReadInt32(); - int Transform = ParcelReader.ReadInt32(); - int StickyTransform = ParcelReader.ReadInt32(); - int Unknown34 = ParcelReader.ReadInt32(); - int Unknown38 = ParcelReader.ReadInt32(); - int IsFenceValid = ParcelReader.ReadInt32(); - int Fence0Id = ParcelReader.ReadInt32(); - int Fence0Value = ParcelReader.ReadInt32(); - int Fence1Id = ParcelReader.ReadInt32(); - int Fence1Value = ParcelReader.ReadInt32(); - - BufferQueue[Slot].Transform = (HalTransform)Transform; - - BufferQueue[Slot].State = BufferState.Queued; - - SendFrameBuffer(Context, Slot); - - return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); - } - - private long GbpCancelBuffer(ServiceCtx Context, BinaryReader ParcelReader) - { - //TODO: Errors. - int Slot = ParcelReader.ReadInt32(); - - BufferQueue[Slot].State = BufferState.Free; - - return MakeReplyParcel(Context, 0); - } - - private long GbpQuery(ServiceCtx Context, BinaryReader ParcelReader) - { - return MakeReplyParcel(Context, 0, 0); - } - - private long GbpConnect(ServiceCtx Context, BinaryReader ParcelReader) - { - return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); - } - - private long GbpPreallocBuffer(ServiceCtx Context, BinaryReader ParcelReader) - { - int Slot = ParcelReader.ReadInt32(); - - int BufferCount = ParcelReader.ReadInt32(); - long BufferSize = ParcelReader.ReadInt64(); - - BufferQueue[Slot].State = BufferState.Free; - - BufferQueue[Slot].Data = new GbpBuffer(ParcelReader); - - return MakeReplyParcel(Context, 0); - } - - private long MakeReplyParcel(ServiceCtx Context, params int[] Ints) - { - using (MemoryStream MS = new MemoryStream()) - { - BinaryWriter Writer = new BinaryWriter(MS); - - foreach (int Int in Ints) - { - Writer.Write(Int); - } - - return MakeReplyParcel(Context, MS.ToArray()); - } - } - - private long MakeReplyParcel(ServiceCtx Context, byte[] Data) - { - long ReplyPos = Context.Request.ReceiveBuff[0].Position; - long ReplySize = Context.Request.ReceiveBuff[0].Size; - - byte[] Reply = MakeParcel(Data, new byte[0]); - - AMemoryHelper.WriteBytes(Context.Memory, ReplyPos, Reply); - - return 0; - } - - private unsafe void SendFrameBuffer(ServiceCtx Context, int Slot) - { - int FbWidth = BufferQueue[Slot].Data.Width; - int FbHeight = BufferQueue[Slot].Data.Height; - - int FbSize = FbWidth * FbHeight * 4; - - HNvMap NvMap = GetNvMap(Context, Slot); - - if (FbSize < 0 || NvMap.Address < 0 || NvMap.Address + FbSize > AMemoryMgr.AddrSize) - { - Logging.Error($"Frame buffer address {NvMap.Address:x16} is invalid!"); - - BufferQueue[Slot].State = BufferState.Free; - - WaitBufferFree.Set(); - - return; - } - - BufferQueue[Slot].State = BufferState.Acquired; - - float ScaleX = 1; - float ScaleY = 1; - float Rotate = 0; - - if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX)) - { - ScaleX = -1; - } - - if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY)) - { - ScaleY = -1; - } - - if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90)) - { - Rotate = MathF.PI * 0.5f; - } - - byte* Fb = (byte*)Context.Ns.Ram + NvMap.Address; - - Context.Ns.Gpu.Renderer.QueueAction(delegate() - { - Context.Ns.Gpu.Renderer.SetFrameBuffer( - Fb, - FbWidth, - FbHeight, - ScaleX, - ScaleY, - Rotate); - - BufferQueue[Slot].State = BufferState.Free; - - lock (WaitBufferFree) - { - WaitBufferFree.Set(); - } - }); - } - - private HNvMap GetNvMap(ServiceCtx Context, int Slot) - { - int NvMapHandle = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x4c); - - if (!BitConverter.IsLittleEndian) - { - byte[] RawValue = BitConverter.GetBytes(NvMapHandle); - - Array.Reverse(RawValue); - - NvMapHandle = BitConverter.ToInt32(RawValue, 0); - } - - return Context.Ns.Os.Handles.GetData(NvMapHandle); - } - - private int GetFreeSlotBlocking(int Width, int Height) - { - int Slot; - - do - { - lock (WaitBufferFree) - { - if ((Slot = GetFreeSlot(Width, Height)) != -1) - { - break; - } - - Logging.Debug("Waiting for a free BufferQueue slot..."); - - if (!KeepRunning) - { - break; - } - - WaitBufferFree.Reset(); - } - - WaitBufferFree.WaitOne(); - } - while (KeepRunning); - - Logging.Debug($"Found free BufferQueue slot {Slot}!"); - - return Slot; - } - - private int GetFreeSlot(int Width, int Height) - { - lock (BufferQueue) - { - for (int Slot = 0; Slot < BufferQueue.Length; Slot++) - { - if (BufferQueue[Slot].State != BufferState.Free) - { - continue; - } - - GbpBuffer Data = BufferQueue[Slot].Data; - - if (Data.Width == Width && - Data.Height == Height) - { - BufferQueue[Slot].State = BufferState.Dequeued; - - return Slot; - } - } - } - - return -1; - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - lock (WaitBufferFree) - { - KeepRunning = false; - - WaitBufferFree.Set(); - } - - WaitBufferFree.Dispose(); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Android/Parcel.cs b/Ryujinx.Core/OsHle/Objects/Android/Parcel.cs deleted file mode 100644 index cd7179e1..00000000 --- a/Ryujinx.Core/OsHle/Objects/Android/Parcel.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.IO; - -namespace Ryujinx.Core.OsHle.Objects.Android -{ - static class Parcel - { - public static byte[] GetParcelData(byte[] Parcel) - { - if (Parcel == null) - { - throw new ArgumentNullException(nameof(Parcel)); - } - - using (MemoryStream MS = new MemoryStream(Parcel)) - { - BinaryReader Reader = new BinaryReader(MS); - - int DataSize = Reader.ReadInt32(); - int DataOffset = Reader.ReadInt32(); - int ObjsSize = Reader.ReadInt32(); - int ObjsOffset = Reader.ReadInt32(); - - MS.Seek(DataOffset - 0x10, SeekOrigin.Current); - - return Reader.ReadBytes(DataSize); - } - } - - public static byte[] MakeParcel(byte[] Data, byte[] Objs) - { - if (Data == null) - { - throw new ArgumentNullException(nameof(Data)); - } - - if (Objs == null) - { - throw new ArgumentNullException(nameof(Objs)); - } - - using (MemoryStream MS = new MemoryStream()) - { - BinaryWriter Writer = new BinaryWriter(MS); - - Writer.Write(Data.Length); - Writer.Write(0x10); - Writer.Write(Objs.Length); - Writer.Write(Data.Length + 0x10); - - Writer.Write(Data); - Writer.Write(Objs); - - return MS.ToArray(); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Apm/ISession.cs b/Ryujinx.Core/OsHle/Objects/Apm/ISession.cs deleted file mode 100644 index 3ab33005..00000000 --- a/Ryujinx.Core/OsHle/Objects/Apm/ISession.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Apm -{ - class ISession : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public ISession() - { - m_Commands = new Dictionary() - { - { 0, SetPerformanceConfiguration } - }; - } - - public long SetPerformanceConfiguration(ServiceCtx Context) - { - int PerfMode = Context.RequestData.ReadInt32(); - int PerfConfig = Context.RequestData.ReadInt32(); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs deleted file mode 100644 index 061c6376..00000000 --- a/Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs +++ /dev/null @@ -1,180 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Ipc; -using OpenTK.Audio; -using OpenTK.Audio.OpenAL; -using System; -using System.Collections.Generic; -using System.IO; - -namespace Ryujinx.Core.OsHle.Objects.Aud -{ - class IAudioOut : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IAudioOut() - { - m_Commands = new Dictionary() - { - { 0, GetAudioOutState }, - { 1, StartAudioOut }, - { 2, StopAudioOut }, - { 3, AppendAudioOutBuffer }, - { 4, RegisterBufferEvent }, - { 5, GetReleasedAudioOutBuffer }, - { 6, ContainsAudioOutBuffer }, - { 7, AppendAudioOutBuffer_ex }, - { 8, GetReleasedAudioOutBuffer_ex } - }; - } - - enum AudioOutState - { - Started, - Stopped - }; - - //IAudioOut - private AudioOutState State = AudioOutState.Stopped; - private Queue KeysQueue = new Queue(); - - //OpenAL - private bool OpenALInstalled = true; - private AudioContext AudioCtx; - private int Source; - private int Buffer; - - //Return State of IAudioOut - public long GetAudioOutState(ServiceCtx Context) - { - Context.ResponseData.Write((int)State); - - return 0; - } - - public long StartAudioOut(ServiceCtx Context) - { - if (State == AudioOutState.Stopped) - { - State = AudioOutState.Started; - - try - { - AudioCtx = new AudioContext(); //Create the audio context - } - catch (Exception) - { - Logging.Warn("OpenAL Error! PS: Install OpenAL Core SDK!"); - OpenALInstalled = false; - } - - if (OpenALInstalled) AL.Listener(ALListenerf.Gain, (float)8.0); //Add more gain to it - } - - return 0; - } - - public long StopAudioOut(ServiceCtx Context) - { - if (State == AudioOutState.Started) - { - if (OpenALInstalled) - { - if (AudioCtx == null) //Needed to call the instance of AudioContext() - return 0; - - AL.SourceStop(Source); - AL.DeleteSource(Source); - } - State = AudioOutState.Stopped; - } - - return 0; - } - - public long AppendAudioOutBuffer(ServiceCtx Context) - { - long BufferId = Context.RequestData.ReadInt64(); - - KeysQueue.Enqueue(BufferId); - - byte[] AudioOutBuffer = AMemoryHelper.ReadBytes(Context.Memory, Context.Request.SendBuff[0].Position, sizeof(long) * 5); - using (MemoryStream MS = new MemoryStream(AudioOutBuffer)) - { - BinaryReader Reader = new BinaryReader(MS); - long PointerNextBuffer = Reader.ReadInt64(); - long PointerSampleBuffer = Reader.ReadInt64(); - long CapacitySampleBuffer = Reader.ReadInt64(); - long SizeDataInSampleBuffer = Reader.ReadInt64(); - long OffsetDataInSampleBuffer = Reader.ReadInt64(); - - byte[] AudioSampleBuffer = AMemoryHelper.ReadBytes(Context.Memory, PointerSampleBuffer + OffsetDataInSampleBuffer, (int)SizeDataInSampleBuffer); - - if (OpenALInstalled) - { - if (AudioCtx == null) //Needed to call the instance of AudioContext() - return 0; - - Buffer = AL.GenBuffer(); - AL.BufferData(Buffer, ALFormat.Stereo16, AudioSampleBuffer, AudioSampleBuffer.Length, 48000); - - Source = AL.GenSource(); - AL.SourceQueueBuffer(Source, Buffer); - } - } - - return 0; - } - - public long RegisterBufferEvent(ServiceCtx Context) - { - int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); - - Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); - - return 0; - } - - public long GetReleasedAudioOutBuffer(ServiceCtx Context) - { - long TempKey = 0; - - if (KeysQueue.Count > 0) TempKey = KeysQueue.Dequeue(); - - AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, BitConverter.GetBytes(TempKey)); - - int ReleasedBuffersCount = 1; - Context.ResponseData.Write(ReleasedBuffersCount); - - if (OpenALInstalled) - { - if (AudioCtx == null) //Needed to call the instance of AudioContext() - return 0; - - AL.SourcePlay(Source); - int[] FreeBuffers = AL.SourceUnqueueBuffers(Source, 1); - AL.DeleteBuffers(FreeBuffers); - } - - return 0; - } - - public long ContainsAudioOutBuffer(ServiceCtx Context) - { - return 0; - } - - public long AppendAudioOutBuffer_ex(ServiceCtx Context) - { - return 0; - } - - public long GetReleasedAudioOutBuffer_ex(ServiceCtx Context) - { - return 0; - } - } -} diff --git a/Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs b/Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs deleted file mode 100644 index 05356477..00000000 --- a/Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Aud -{ - class IAudioRenderer : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IAudioRenderer() - { - m_Commands = new Dictionary() - { - { 4, RequestUpdateAudioRenderer }, - { 5, StartAudioRenderer }, - { 6, StopAudioRenderer }, - { 7, QuerySystemEvent } - }; - } - - public long RequestUpdateAudioRenderer(ServiceCtx Context) - { - //(buffer) -> (buffer, buffer) - - long Position = Context.Request.ReceiveBuff[0].Position; - - //0x40 bytes header - Context.Memory.WriteInt32(Position + 0x4, 0xb0); //Behavior Out State Size? (note: this is the last section) - Context.Memory.WriteInt32(Position + 0x8, 0x18e0); //Memory Pool Out State Size? - Context.Memory.WriteInt32(Position + 0xc, 0x600); //Voice Out State Size? - Context.Memory.WriteInt32(Position + 0x14, 0xe0); //Effect Out State Size? - Context.Memory.WriteInt32(Position + 0x1c, 0x20); //Sink Out State Size? - Context.Memory.WriteInt32(Position + 0x20, 0x10); //Performance Out State Size? - Context.Memory.WriteInt32(Position + 0x3c, 0x20e0); //Total Size (including 0x40 bytes header) - - for (int Offset = 0x40; Offset < 0x40 + 0x18e0; Offset += 0x10) - { - Context.Memory.WriteInt32(Position + Offset, 5); - } - - return 0; - } - - public long StartAudioRenderer(ServiceCtx Context) - { - return 0; - } - - public long StopAudioRenderer(ServiceCtx Context) - { - return 0; - } - - public long QuerySystemEvent(ServiceCtx Context) - { - int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); - - Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/ErrorCode.cs b/Ryujinx.Core/OsHle/Objects/ErrorCode.cs deleted file mode 100644 index 659ed8b9..00000000 --- a/Ryujinx.Core/OsHle/Objects/ErrorCode.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Core.OsHle.Objects -{ - static class ErrorCode - { - public static long MakeError(ErrorModule Module, int Code) - { - return (int)Module | (Code << 9); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/ErrorModule.cs b/Ryujinx.Core/OsHle/Objects/ErrorModule.cs deleted file mode 100644 index 0221031b..00000000 --- a/Ryujinx.Core/OsHle/Objects/ErrorModule.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.Core.OsHle.Objects -{ - enum ErrorModule - { - Fs = 2, - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Friend/IFriendService.cs b/Ryujinx.Core/OsHle/Objects/Friend/IFriendService.cs deleted file mode 100644 index e98e27ca..00000000 --- a/Ryujinx.Core/OsHle/Objects/Friend/IFriendService.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Friend -{ - class IFriendService : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IFriendService() - { - m_Commands = new Dictionary() - { - //... - }; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs deleted file mode 100644 index d9aa60ae..00000000 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Core.OsHle.Objects.FspSrv -{ - static class FsErr - { - public const int PathDoesNotExist = 1; - public const int PathAlreadyExists = 2; - public const int PathAlreadyInUse = 7; - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs deleted file mode 100644 index 785b1ba3..00000000 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs +++ /dev/null @@ -1,117 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Ipc; -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; - -namespace Ryujinx.Core.OsHle.Objects.FspSrv -{ - class IDirectory : IIpcInterface, IDisposable - { - private const int DirectoryEntrySize = 0x310; - - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - private List DirectoryEntries; - - private int CurrentItemIndex; - - public event EventHandler Disposed; - - public string HostPath { get; private set; } - - public IDirectory(string HostPath, int Flags) - { - m_Commands = new Dictionary() - { - { 0, Read }, - { 1, GetEntryCount } - }; - - this.HostPath = HostPath; - - DirectoryEntries = new List(); - - if ((Flags & 1) != 0) - { - DirectoryEntries.AddRange(Directory.GetDirectories(HostPath)); - } - - if ((Flags & 2) != 0) - { - DirectoryEntries.AddRange(Directory.GetFiles(HostPath)); - } - - CurrentItemIndex = 0; - } - - public long Read(ServiceCtx Context) - { - long BufferPosition = Context.Request.ReceiveBuff[0].Position; - long BufferLen = Context.Request.ReceiveBuff[0].Size; - - int MaxReadCount = (int)(BufferLen / DirectoryEntrySize); - - int Count = Math.Min(DirectoryEntries.Count - CurrentItemIndex, MaxReadCount); - - for (int Index = 0; Index < Count; Index++) - { - long Position = BufferPosition + Index * DirectoryEntrySize; - - WriteDirectoryEntry(Context, Position, DirectoryEntries[CurrentItemIndex++]); - } - - Context.ResponseData.Write((long)Count); - - return 0; - } - - private void WriteDirectoryEntry(ServiceCtx Context, long Position, string FullPath) - { - for (int Offset = 0; Offset < 0x300; Offset += 8) - { - Context.Memory.WriteInt64(Position + Offset, 0); - } - - byte[] NameBuffer = Encoding.UTF8.GetBytes(Path.GetFileName(FullPath)); - - AMemoryHelper.WriteBytes(Context.Memory, Position, NameBuffer); - - int Type = 0; - long Size = 0; - - if (File.Exists(FullPath)) - { - Type = 1; - Size = new FileInfo(FullPath).Length; - } - - Context.Memory.WriteInt32(Position + 0x300, 0); //Padding? - Context.Memory.WriteInt32(Position + 0x304, Type); - Context.Memory.WriteInt64(Position + 0x308, Size); - } - - public long GetEntryCount(ServiceCtx Context) - { - Context.ResponseData.Write((long)DirectoryEntries.Count); - - return 0; - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - Disposed?.Invoke(this, EventArgs.Empty); - } - } - } -} diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs deleted file mode 100644 index 82706f60..00000000 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs +++ /dev/null @@ -1,111 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Ipc; -using System; -using System.Collections.Generic; -using System.IO; - -namespace Ryujinx.Core.OsHle.Objects.FspSrv -{ - class IFile : IIpcInterface, IDisposable - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - private Stream BaseStream; - - public event EventHandler Disposed; - - public string HostPath { get; private set; } - - public IFile(Stream BaseStream, string HostPath) - { - m_Commands = new Dictionary() - { - { 0, Read }, - { 1, Write }, - { 2, Flush }, - { 3, SetSize }, - { 4, GetSize } - }; - - this.BaseStream = BaseStream; - this.HostPath = HostPath; - } - - public long Read(ServiceCtx Context) - { - long Position = Context.Request.ReceiveBuff[0].Position; - - long Zero = Context.RequestData.ReadInt64(); - long Offset = Context.RequestData.ReadInt64(); - long Size = Context.RequestData.ReadInt64(); - - byte[] Data = new byte[Size]; - - BaseStream.Seek(Offset, SeekOrigin.Begin); - - int ReadSize = BaseStream.Read(Data, 0, (int)Size); - - AMemoryHelper.WriteBytes(Context.Memory, Position, Data); - - Context.ResponseData.Write((long)ReadSize); - - return 0; - } - - public long Write(ServiceCtx Context) - { - long Position = Context.Request.SendBuff[0].Position; - - long Zero = Context.RequestData.ReadInt64(); - long Offset = Context.RequestData.ReadInt64(); - long Size = Context.RequestData.ReadInt64(); - - byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, Position, (int)Size); - - BaseStream.Seek(Offset, SeekOrigin.Begin); - BaseStream.Write(Data, 0, (int)Size); - - return 0; - } - - public long Flush(ServiceCtx Context) - { - BaseStream.Flush(); - - return 0; - } - - public long SetSize(ServiceCtx Context) - { - long Size = Context.RequestData.ReadInt64(); - - BaseStream.SetLength(Size); - - return 0; - } - - public long GetSize(ServiceCtx Context) - { - Context.ResponseData.Write(BaseStream.Length); - - return 0; - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && BaseStream != null) - { - BaseStream.Dispose(); - - Disposed?.Invoke(this, EventArgs.Empty); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs deleted file mode 100644 index 6b86a473..00000000 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs +++ /dev/null @@ -1,383 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Ipc; -using System; -using System.Collections.Generic; -using System.IO; - -using static Ryujinx.Core.OsHle.Objects.ErrorCode; -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Objects.FspSrv -{ - class IFileSystem : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - private HashSet OpenPaths; - - private string Path; - - public IFileSystem(string Path) - { - m_Commands = new Dictionary() - { - { 0, CreateFile }, - { 1, DeleteFile }, - { 2, CreateDirectory }, - { 3, DeleteDirectory }, - { 4, DeleteDirectoryRecursively }, - { 5, RenameFile }, - { 6, RenameDirectory }, - { 7, GetEntryType }, - { 8, OpenFile }, - { 9, OpenDirectory }, - { 10, Commit }, - { 11, GetFreeSpaceSize }, - { 12, GetTotalSpaceSize }, - //{ 13, CleanDirectoryRecursively }, - //{ 14, GetFileTimeStampRaw } - }; - - OpenPaths = new HashSet(); - - this.Path = Path; - } - - public long CreateFile(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - - long Mode = Context.RequestData.ReadInt64(); - int Size = Context.RequestData.ReadInt32(); - - string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - - if (FileName == null) - { - return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); - } - - if (File.Exists(FileName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); - } - - if (IsPathAlreadyInUse(FileName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); - } - - using (FileStream NewFile = File.Create(FileName)) - { - NewFile.SetLength(Size); - } - - return 0; - } - - public long DeleteFile(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - - string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - - if (!File.Exists(FileName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); - } - - if (IsPathAlreadyInUse(FileName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); - } - - File.Delete(FileName); - - return 0; - } - - public long CreateDirectory(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - - string DirName = Context.Ns.VFs.GetFullPath(Path, Name); - - if (DirName == null) - { - return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); - } - - if (Directory.Exists(DirName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); - } - - if (IsPathAlreadyInUse(DirName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); - } - - Directory.CreateDirectory(DirName); - - return 0; - } - - public long DeleteDirectory(ServiceCtx Context) - { - return DeleteDirectory(Context, false); - } - - public long DeleteDirectoryRecursively(ServiceCtx Context) - { - return DeleteDirectory(Context, true); - } - - private long DeleteDirectory(ServiceCtx Context, bool Recursive) - { - long Position = Context.Request.PtrBuff[0].Position; - - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - - string DirName = Context.Ns.VFs.GetFullPath(Path, Name); - - if (!Directory.Exists(DirName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); - } - - if (IsPathAlreadyInUse(DirName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); - } - - Directory.Delete(DirName, Recursive); - - return 0; - } - - public long RenameFile(ServiceCtx Context) - { - long OldPosition = Context.Request.PtrBuff[0].Position; - long NewPosition = Context.Request.PtrBuff[0].Position; - - string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); - string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); - - string OldFileName = Context.Ns.VFs.GetFullPath(Path, OldName); - string NewFileName = Context.Ns.VFs.GetFullPath(Path, NewName); - - if (!File.Exists(OldFileName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); - } - - if (File.Exists(NewFileName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); - } - - if (IsPathAlreadyInUse(OldFileName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); - } - - File.Move(OldFileName, NewFileName); - - return 0; - } - - public long RenameDirectory(ServiceCtx Context) - { - long OldPosition = Context.Request.PtrBuff[0].Position; - long NewPosition = Context.Request.PtrBuff[0].Position; - - string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); - string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); - - string OldDirName = Context.Ns.VFs.GetFullPath(Path, OldName); - string NewDirName = Context.Ns.VFs.GetFullPath(Path, NewName); - - if (!Directory.Exists(OldDirName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); - } - - if (Directory.Exists(NewDirName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); - } - - if (IsPathAlreadyInUse(OldDirName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); - } - - Directory.Move(OldDirName, NewDirName); - - return 0; - } - - public long GetEntryType(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - - string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - - if (File.Exists(FileName)) - { - Context.ResponseData.Write(1); - } - else if (Directory.Exists(FileName)) - { - Context.ResponseData.Write(0); - } - else - { - Context.ResponseData.Write(0); - - return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); - } - - return 0; - } - - public long OpenFile(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - int FilterFlags = Context.RequestData.ReadInt32(); - - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - - string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - - if (!File.Exists(FileName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); - } - - if (IsPathAlreadyInUse(FileName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); - } - - FileStream Stream = new FileStream(FileName, FileMode.Open); - - IFile FileInterface = new IFile(Stream, FileName); - - FileInterface.Disposed += RemoveFileInUse; - - lock (OpenPaths) - { - OpenPaths.Add(FileName); - } - - MakeObject(Context, FileInterface); - - return 0; - } - - public long OpenDirectory(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - int FilterFlags = Context.RequestData.ReadInt32(); - - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - - string DirName = Context.Ns.VFs.GetFullPath(Path, Name); - - if (!Directory.Exists(DirName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); - } - - if (IsPathAlreadyInUse(DirName)) - { - return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); - } - - IDirectory DirInterface = new IDirectory(DirName, FilterFlags); - - DirInterface.Disposed += RemoveDirectoryInUse; - - lock (OpenPaths) - { - OpenPaths.Add(DirName); - } - - MakeObject(Context, DirInterface); - - return 0; - } - - public long Commit(ServiceCtx Context) - { - return 0; - } - - public long GetFreeSpaceSize(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - - Context.ResponseData.Write(Context.Ns.VFs.GetDrive().AvailableFreeSpace); - - return 0; - } - - public long GetTotalSpaceSize(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - - Context.ResponseData.Write(Context.Ns.VFs.GetDrive().TotalSize); - - return 0; - } - - private bool IsPathAlreadyInUse(string Path) - { - lock (OpenPaths) - { - return OpenPaths.Contains(Path); - } - } - - private void RemoveFileInUse(object sender, EventArgs e) - { - IFile FileInterface = (IFile)sender; - - lock (OpenPaths) - { - FileInterface.Disposed -= RemoveFileInUse; - - OpenPaths.Remove(FileInterface.HostPath); - } - } - - private void RemoveDirectoryInUse(object sender, EventArgs e) - { - IDirectory DirInterface = (IDirectory)sender; - - lock (OpenPaths) - { - DirInterface.Disposed -= RemoveDirectoryInUse; - - OpenPaths.Remove(DirInterface.HostPath); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs deleted file mode 100644 index 4eca37e8..00000000 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs +++ /dev/null @@ -1,52 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; -using System.IO; - -namespace Ryujinx.Core.OsHle.Objects.FspSrv -{ - class IStorage : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - private Stream BaseStream; - - public IStorage(Stream BaseStream) - { - m_Commands = new Dictionary() - { - { 0, Read } - }; - - this.BaseStream = BaseStream; - } - - public long Read(ServiceCtx Context) - { - long Offset = Context.RequestData.ReadInt64(); - long Size = Context.RequestData.ReadInt64(); - - if (Context.Request.ReceiveBuff.Count > 0) - { - IpcBuffDesc BuffDesc = Context.Request.ReceiveBuff[0]; - - //Use smaller length to avoid overflows. - if (Size > BuffDesc.Size) - { - Size = BuffDesc.Size; - } - - byte[] Data = new byte[Size]; - - BaseStream.Seek(Offset, SeekOrigin.Begin); - BaseStream.Read(Data, 0, Data.Length); - - AMemoryHelper.WriteBytes(Context.Memory, BuffDesc.Position, Data); - } - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs b/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs deleted file mode 100644 index aae3c38d..00000000 --- a/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Hid -{ - class IActiveApplicationDeviceList : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IActiveApplicationDeviceList() - { - m_Commands = new Dictionary() { }; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs b/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs deleted file mode 100644 index 7d56d04b..00000000 --- a/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Hid -{ - class IAppletResource : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - private HSharedMem Handle; - - public IAppletResource(HSharedMem Handle) - { - m_Commands = new Dictionary() - { - { 0, GetSharedMemoryHandle } - }; - - this.Handle = Handle; - } - - public static long GetSharedMemoryHandle(ServiceCtx Context) - { - Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Context.Ns.Os.HidHandle); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/IIpcInterface.cs b/Ryujinx.Core/OsHle/Objects/IIpcInterface.cs deleted file mode 100644 index c57a0974..00000000 --- a/Ryujinx.Core/OsHle/Objects/IIpcInterface.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects -{ - interface IIpcInterface - { - IReadOnlyDictionary Commands { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/ObjHelper.cs b/Ryujinx.Core/OsHle/Objects/ObjHelper.cs deleted file mode 100644 index a151a287..00000000 --- a/Ryujinx.Core/OsHle/Objects/ObjHelper.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Ipc; - -namespace Ryujinx.Core.OsHle.Objects -{ - static class ObjHelper - { - public static void MakeObject(ServiceCtx Context, object Obj) - { - if (Context.Session is HDomain Dom) - { - Context.Response.ResponseObjIds.Add(Dom.GenerateObjectId(Obj)); - } - else - { - HSessionObj HndData = new HSessionObj(Context.Session, Obj); - - int VHandle = Context.Ns.Os.Handles.GenerateId(HndData); - - Context.Response.HandleDesc = IpcHandleDesc.MakeMove(VHandle); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs b/Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs deleted file mode 100644 index 1116b849..00000000 --- a/Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Time -{ - class ISteadyClock : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public ISteadyClock() - { - m_Commands = new Dictionary() - { - //... - }; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs b/Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs deleted file mode 100644 index 3aa70691..00000000 --- a/Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Time -{ - class ISystemClock : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - private static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - private SystemClockType ClockType; - - public ISystemClock(SystemClockType ClockType) - { - m_Commands = new Dictionary() - { - { 0, GetCurrentTime } - }; - - this.ClockType = ClockType; - } - - public long GetCurrentTime(ServiceCtx Context) - { - DateTime CurrentTime = DateTime.Now; - - if (ClockType == SystemClockType.User || - ClockType == SystemClockType.Network) - { - CurrentTime = CurrentTime.ToUniversalTime(); - } - - Context.ResponseData.Write((long)(DateTime.Now - Epoch).TotalSeconds); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Time/ITimeZoneService.cs b/Ryujinx.Core/OsHle/Objects/Time/ITimeZoneService.cs deleted file mode 100644 index c083628b..00000000 --- a/Ryujinx.Core/OsHle/Objects/Time/ITimeZoneService.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Time -{ - class ITimeZoneService : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public ITimeZoneService() - { - m_Commands = new Dictionary() - { - //... - }; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs b/Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs deleted file mode 100644 index f447ca1c..00000000 --- a/Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Core.OsHle.Objects.Time -{ - enum SystemClockType - { - User, - Network, - Local - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Vi/IApplicationDisplayService.cs b/Ryujinx.Core/OsHle/Objects/Vi/IApplicationDisplayService.cs deleted file mode 100644 index b3ec0e90..00000000 --- a/Ryujinx.Core/OsHle/Objects/Vi/IApplicationDisplayService.cs +++ /dev/null @@ -1,176 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; -using System.IO; - -using static Ryujinx.Core.OsHle.Objects.Android.Parcel; -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Objects.Vi -{ - class IApplicationDisplayService : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IApplicationDisplayService() - { - m_Commands = new Dictionary() - { - { 100, GetRelayService }, - { 101, GetSystemDisplayService }, - { 102, GetManagerDisplayService }, - { 103, GetIndirectDisplayTransactionService }, - { 1010, OpenDisplay }, - { 2020, OpenLayer }, - { 2030, CreateStrayLayer }, - { 2101, SetLayerScalingMode }, - { 5202, GetDisplayVSyncEvent } - }; - } - - public long GetRelayService(ServiceCtx Context) - { - MakeObject(Context, new IHOSBinderDriver()); - - return 0; - } - - public long GetSystemDisplayService(ServiceCtx Context) - { - MakeObject(Context, new ISystemDisplayService()); - - return 0; - } - - public long GetManagerDisplayService(ServiceCtx Context) - { - MakeObject(Context, new IManagerDisplayService()); - - return 0; - } - - public long GetIndirectDisplayTransactionService(ServiceCtx Context) - { - MakeObject(Context, new IHOSBinderDriver()); - - return 0; - } - - public long OpenDisplay(ServiceCtx Context) - { - string Name = GetDisplayName(Context); - - long DisplayId = Context.Ns.Os.Displays.GenerateId(new Display(Name)); - - Context.ResponseData.Write(DisplayId); - - return 0; - } - - public long OpenLayer(ServiceCtx Context) - { - long LayerId = Context.RequestData.ReadInt64(); - long UserId = Context.RequestData.ReadInt64(); - - long ParcelPtr = Context.Request.ReceiveBuff[0].Position; - - byte[] Parcel = MakeIGraphicsBufferProducer(ParcelPtr); - - AMemoryHelper.WriteBytes(Context.Memory, ParcelPtr, Parcel); - - Context.ResponseData.Write((long)Parcel.Length); - - return 0; - } - - public long CreateStrayLayer(ServiceCtx Context) - { - long LayerFlags = Context.RequestData.ReadInt64(); - long DisplayId = Context.RequestData.ReadInt64(); - - long ParcelPtr = Context.Request.ReceiveBuff[0].Position; - - Display Disp = Context.Ns.Os.Displays.GetData((int)DisplayId); - - byte[] Parcel = MakeIGraphicsBufferProducer(ParcelPtr); - - AMemoryHelper.WriteBytes(Context.Memory, ParcelPtr, Parcel); - - Context.ResponseData.Write(0L); - Context.ResponseData.Write((long)Parcel.Length); - - return 0; - } - - public long SetLayerScalingMode(ServiceCtx Context) - { - int ScalingMode = Context.RequestData.ReadInt32(); - long Unknown = Context.RequestData.ReadInt64(); - - return 0; - } - - public long GetDisplayVSyncEvent(ServiceCtx Context) - { - string Name = GetDisplayName(Context); - - int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); - - Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); - - return 0; - } - - private byte[] MakeIGraphicsBufferProducer(long BasePtr) - { - long Id = 0x20; - long CookiePtr = 0L; - - using (MemoryStream MS = new MemoryStream()) - { - BinaryWriter Writer = new BinaryWriter(MS); - - //flat_binder_object (size is 0x28) - Writer.Write(2); //Type (BINDER_TYPE_WEAK_BINDER) - Writer.Write(0); //Flags - Writer.Write((int)(Id >> 0)); - Writer.Write((int)(Id >> 32)); - Writer.Write((int)(CookiePtr >> 0)); - Writer.Write((int)(CookiePtr >> 32)); - Writer.Write((byte)'d'); - Writer.Write((byte)'i'); - Writer.Write((byte)'s'); - Writer.Write((byte)'p'); - Writer.Write((byte)'d'); - Writer.Write((byte)'r'); - Writer.Write((byte)'v'); - Writer.Write((byte)'\0'); - Writer.Write(0L); //Pad - - return MakeParcel(MS.ToArray(), new byte[] { 0, 0, 0, 0 }); - } - } - - private string GetDisplayName(ServiceCtx Context) - { - string Name = string.Empty; - - for (int Index = 0; Index < 8 && - Context.RequestData.BaseStream.Position < - Context.RequestData.BaseStream.Length; Index++) - { - byte Chr = Context.RequestData.ReadByte(); - - if (Chr >= 0x20 && Chr < 0x7f) - { - Name += (char)Chr; - } - } - - return Name; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs deleted file mode 100644 index bbea3368..00000000 --- a/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs +++ /dev/null @@ -1,76 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Ipc; -using Ryujinx.Core.OsHle.Objects.Android; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Vi -{ - class IHOSBinderDriver : IIpcInterface, IDisposable - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - private NvFlinger Flinger; - - public IHOSBinderDriver() - { - m_Commands = new Dictionary() - { - { 0, TransactParcel }, - { 1, AdjustRefcount }, - { 2, GetNativeHandle } - }; - - Flinger = new NvFlinger(); - } - - public long TransactParcel(ServiceCtx Context) - { - int Id = Context.RequestData.ReadInt32(); - int Code = Context.RequestData.ReadInt32(); - - long DataPos = Context.Request.SendBuff[0].Position; - long DataSize = Context.Request.SendBuff[0].Size; - - byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, DataPos, (int)DataSize); - - Data = Parcel.GetParcelData(Data); - - return Flinger.ProcessParcelRequest(Context, Data, Code); - } - - public long AdjustRefcount(ServiceCtx Context) - { - int Id = Context.RequestData.ReadInt32(); - int AddVal = Context.RequestData.ReadInt32(); - int Type = Context.RequestData.ReadInt32(); - - return 0; - } - - public long GetNativeHandle(ServiceCtx Context) - { - int Id = Context.RequestData.ReadInt32(); - uint Unk = Context.RequestData.ReadUInt32(); - - Context.Response.HandleDesc = IpcHandleDesc.MakeMove(0xbadcafe); - - return 0; - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - Flinger.Dispose(); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Vi/IManagerDisplayService.cs b/Ryujinx.Core/OsHle/Objects/Vi/IManagerDisplayService.cs deleted file mode 100644 index f1b3cdd0..00000000 --- a/Ryujinx.Core/OsHle/Objects/Vi/IManagerDisplayService.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Vi -{ - class IManagerDisplayService : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public IManagerDisplayService() - { - m_Commands = new Dictionary() - { - { 2010, CreateManagedLayer }, - { 6000, AddToLayerStack } - }; - } - - public static long CreateManagedLayer(ServiceCtx Context) - { - Context.ResponseData.Write(0L); //LayerId - - return 0; - } - - public static long AddToLayerStack(ServiceCtx Context) - { - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Vi/ISystemDisplayService.cs b/Ryujinx.Core/OsHle/Objects/Vi/ISystemDisplayService.cs deleted file mode 100644 index 4c83c25f..00000000 --- a/Ryujinx.Core/OsHle/Objects/Vi/ISystemDisplayService.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Objects.Vi -{ - class ISystemDisplayService : IIpcInterface - { - private Dictionary m_Commands; - - public IReadOnlyDictionary Commands => m_Commands; - - public ISystemDisplayService() - { - m_Commands = new Dictionary() - { - { 2205, SetLayerZ } - }; - } - - public static long SetLayerZ(ServiceCtx Context) - { - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceAcc.cs b/Ryujinx.Core/OsHle/Services/ServiceAcc.cs deleted file mode 100644 index f25113e5..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceAcc.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Acc; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long AccU0ListOpenUsers(ServiceCtx Context) - { - return 0; - } - - public static long AccU0GetProfile(ServiceCtx Context) - { - MakeObject(Context, new IProfile()); - - return 0; - } - - public static long AccU0InitializeApplicationInfo(ServiceCtx Context) - { - return 0; - } - - public static long AccU0GetBaasAccountManagerForApplication(ServiceCtx Context) - { - MakeObject(Context, new IManagerForApplication()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceApm.cs b/Ryujinx.Core/OsHle/Services/ServiceApm.cs deleted file mode 100644 index e1bc0d34..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceApm.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Apm; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long ApmOpenSession(ServiceCtx Context) - { - MakeObject(Context, new ISession()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs b/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs deleted file mode 100644 index bbb2484b..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Am; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long AppletOpenApplicationProxy(ServiceCtx Context) - { - MakeObject(Context, new IApplicationProxy()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceAud.cs b/Ryujinx.Core/OsHle/Services/ServiceAud.cs deleted file mode 100644 index a8ba7dc0..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceAud.cs +++ /dev/null @@ -1,71 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Objects.Aud; -using System.Text; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long AudOutListAudioOuts(ServiceCtx Context) - { - long Position = Context.Request.ReceiveBuff[0].Position; - - AMemoryHelper.WriteBytes(Context.Memory, Position, Encoding.ASCII.GetBytes("iface")); - - Context.ResponseData.Write(1); - - return 0; - } - - public static long AudOutOpenAudioOut(ServiceCtx Context) - { - MakeObject(Context, new IAudioOut()); - - Context.ResponseData.Write(48000); //Sample Rate - Context.ResponseData.Write(2); //Channel Count - Context.ResponseData.Write(2); //PCM Format - /* - 0 - Invalid - 1 - INT8 - 2 - INT16 - 3 - INT24 - 4 - INT32 - 5 - PCM Float - 6 - ADPCM - */ - Context.ResponseData.Write(0); //Unknown - - return 0; - } - - public static long AudRenOpenAudioRenderer(ServiceCtx Context) - { - MakeObject(Context, new IAudioRenderer()); - - return 0; - } - - public static long AudRenGetAudioRendererWorkBufferSize(ServiceCtx Context) - { - int SampleRate = Context.RequestData.ReadInt32(); - int Unknown4 = Context.RequestData.ReadInt32(); - int Unknown8 = Context.RequestData.ReadInt32(); - int UnknownC = Context.RequestData.ReadInt32(); - int Unknown10 = Context.RequestData.ReadInt32(); - int Unknown14 = Context.RequestData.ReadInt32(); - int Unknown18 = Context.RequestData.ReadInt32(); - int Unknown1c = Context.RequestData.ReadInt32(); - int Unknown20 = Context.RequestData.ReadInt32(); - int Unknown24 = Context.RequestData.ReadInt32(); - int Unknown28 = Context.RequestData.ReadInt32(); - int Unknown2c = Context.RequestData.ReadInt32(); - int Rev1Magic = Context.RequestData.ReadInt32(); - - Context.ResponseData.Write(0x400L); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceFriend.cs b/Ryujinx.Core/OsHle/Services/ServiceFriend.cs deleted file mode 100644 index d1229bd4..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceFriend.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Friend; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long FriendCreateFriendService(ServiceCtx Context) - { - MakeObject(Context, new IFriendService()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs b/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs deleted file mode 100644 index 3fe41cf0..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.FspSrv; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long FspSrvInitialize(ServiceCtx Context) - { - return 0; - } - - public static long FspSrvMountSdCard(ServiceCtx Context) - { - MakeObject(Context, new IFileSystem(Context.Ns.VFs.GetSdCardPath())); - - return 0; - } - - public static long FspSrvMountSaveData(ServiceCtx Context) - { - MakeObject(Context, new IFileSystem(Context.Ns.VFs.GetGameSavesPath())); - - return 0; - } - - public static long FspSrvOpenDataStorageByCurrentProcess(ServiceCtx Context) - { - MakeObject(Context, new IStorage(Context.Ns.VFs.RomFs)); - - return 0; - } - - public static long FspSrvOpenRomStorage(ServiceCtx Context) - { - MakeObject(Context, new IStorage(Context.Ns.VFs.RomFs)); - - return 0; - } - - public static long FspSrvGetGlobalAccessLogMode(ServiceCtx Context) - { - Context.ResponseData.Write(0); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/ServiceHid.cs deleted file mode 100644 index aed3e959..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceHid.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Objects.Hid; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long HidCreateAppletResource(ServiceCtx Context) - { - HSharedMem HidHndData = Context.Ns.Os.Handles.GetData(Context.Ns.Os.HidHandle); - - MakeObject(Context, new IAppletResource(HidHndData)); - - return 0; - } - - public static long HidActivateTouchScreen(ServiceCtx Context) - { - long Unknown = Context.RequestData.ReadInt64(); - - return 0; - } - - public static long HidGetSupportedNpadStyleSet(ServiceCtx Context) - { - Context.ResponseData.Write(0); - - return 0; - } - - public static long HidSetSupportedNpadStyleSet(ServiceCtx Context) - { - long Unknown0 = Context.RequestData.ReadInt64(); - long Unknown8 = Context.RequestData.ReadInt64(); - - return 0; - } - - public static long HidSetSupportedNpadIdType(ServiceCtx Context) - { - long Unknown = Context.RequestData.ReadInt64(); - - return 0; - } - - public static long HidActivateNpad(ServiceCtx Context) - { - long Unknown = Context.RequestData.ReadInt64(); - - return 0; - } - - public static long HidSetNpadJoyHoldType(ServiceCtx Context) - { - long Unknown0 = Context.RequestData.ReadInt64(); - long Unknown8 = Context.RequestData.ReadInt64(); - - return 0; - } - - public static long HidGetNpadJoyHoldType(ServiceCtx Context) - { - Context.ResponseData.Write(0L); - - return 0; - } - - public static long HidCreateActiveVibrationDeviceList(ServiceCtx Context) - { - MakeObject(Context, new IActiveApplicationDeviceList()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceLm.cs b/Ryujinx.Core/OsHle/Services/ServiceLm.cs deleted file mode 100644 index 1fdde552..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceLm.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long LmInitialize(ServiceCtx Context) - { - Context.Session.Initialize(); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs deleted file mode 100644 index 6c5fdaed..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs +++ /dev/null @@ -1,610 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Ipc; -using Ryujinx.Core.OsHle.Utilities; -using Ryujinx.Graphics.Gpu; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - private delegate long ServiceProcessRequest(ServiceCtx Context); - - private static Dictionary<(string, int), ServiceProcessRequest> IoctlCmds = - new Dictionary<(string, int), ServiceProcessRequest>() - { - { ("/dev/nvhost-as-gpu", 0x4101), NvGpuAsIoctlBindChannel }, - { ("/dev/nvhost-as-gpu", 0x4102), NvGpuAsIoctlAllocSpace }, - { ("/dev/nvhost-as-gpu", 0x4106), NvGpuAsIoctlMapBufferEx }, - { ("/dev/nvhost-as-gpu", 0x4108), NvGpuAsIoctlGetVaRegions }, - { ("/dev/nvhost-as-gpu", 0x4109), NvGpuAsIoctlInitializeEx }, - { ("/dev/nvhost-ctrl", 0x001b), NvHostIoctlCtrlGetConfig }, - { ("/dev/nvhost-ctrl", 0x001d), NvHostIoctlCtrlEventWait }, - { ("/dev/nvhost-ctrl-gpu", 0x4701), NvGpuIoctlZcullGetCtxSize }, - { ("/dev/nvhost-ctrl-gpu", 0x4702), NvGpuIoctlZcullGetInfo }, - { ("/dev/nvhost-ctrl-gpu", 0x4705), NvGpuIoctlGetCharacteristics }, - { ("/dev/nvhost-ctrl-gpu", 0x4706), NvGpuIoctlGetTpcMasks }, - { ("/dev/nvhost-ctrl-gpu", 0x4714), NvGpuIoctlZbcGetActiveSlotMask }, - { ("/dev/nvhost-gpu", 0x4714), NvMapIoctlChannelSetUserData }, - { ("/dev/nvhost-gpu", 0x4801), NvMapIoctlChannelSetNvMap }, - { ("/dev/nvhost-gpu", 0x4808), NvMapIoctlChannelSubmitGpFifo }, - { ("/dev/nvhost-gpu", 0x4809), NvMapIoctlChannelAllocObjCtx }, - { ("/dev/nvhost-gpu", 0x480b), NvMapIoctlChannelZcullBind }, - { ("/dev/nvhost-gpu", 0x480c), NvMapIoctlChannelSetErrorNotifier }, - { ("/dev/nvhost-gpu", 0x480d), NvMapIoctlChannelSetPriority }, - { ("/dev/nvhost-gpu", 0x481a), NvMapIoctlChannelAllocGpFifoEx2 }, - { ("/dev/nvmap", 0x0101), NvMapIocCreate }, - { ("/dev/nvmap", 0x0103), NvMapIocFromId }, - { ("/dev/nvmap", 0x0104), NvMapIocAlloc }, - { ("/dev/nvmap", 0x0109), NvMapIocParam }, - { ("/dev/nvmap", 0x010e), NvMapIocGetId }, - }; - - public static long NvDrvOpen(ServiceCtx Context) - { - long NamePtr = Context.Request.SendBuff[0].Position; - - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, NamePtr); - - int Fd = Context.Ns.Os.Fds.GenerateId(new FileDesc(Name)); - - Context.ResponseData.Write(Fd); - Context.ResponseData.Write(0); - - return 0; - } - - public static long NvDrvIoctl(ServiceCtx Context) - { - int Fd = Context.RequestData.ReadInt32(); - int Cmd = Context.RequestData.ReadInt32() & 0xffff; - - FileDesc FdData = Context.Ns.Os.Fds.GetData(Fd); - - long Position = Context.Request.PtrBuff[0].Position; - - Context.ResponseData.Write(0); - - if (IoctlCmds.TryGetValue((FdData.Name, Cmd), out ServiceProcessRequest ProcReq)) - { - return ProcReq(Context); - } - else - { - throw new NotImplementedException($"{FdData.Name} {Cmd:x4}"); - } - } - - public static long NvDrvClose(ServiceCtx Context) - { - int Fd = Context.RequestData.ReadInt32(); - - Context.Ns.Os.Fds.Delete(Fd); - - Context.ResponseData.Write(0); - - return 0; - } - - public static long NvDrvInitialize(ServiceCtx Context) - { - long TransferMemSize = Context.RequestData.ReadInt64(); - int TransferMemHandle = Context.Request.HandleDesc.ToCopy[0]; - - Context.ResponseData.Write(0); - - return 0; - } - - public static long NvDrvQueryEvent(ServiceCtx Context) - { - int Fd = Context.RequestData.ReadInt32(); - int EventId = Context.RequestData.ReadInt32(); - - Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(0xcafe); - - Context.ResponseData.Write(0); - - return 0; - } - - public static long NvDrvSetClientPid(ServiceCtx Context) - { - long Pid = Context.RequestData.ReadInt64(); - - Context.ResponseData.Write(0); - - return 0; - } - - private static long NvGpuAsIoctlBindChannel(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - int Fd = Context.Memory.ReadInt32(Position); - - return 0; - } - - private static long NvGpuAsIoctlAllocSpace(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - - int Pages = Reader.ReadInt32(); - int PageSize = Reader.ReadInt32(); - int Flags = Reader.ReadInt32(); - int Padding = Reader.ReadInt32(); - long Align = Reader.ReadInt64(); - - if ((Flags & 1) != 0) - { - Align = Context.Ns.Gpu.ReserveMemory(Align, (long)Pages * PageSize, 1); - } - else - { - Align = Context.Ns.Gpu.ReserveMemory((long)Pages * PageSize, Align); - } - - Context.Memory.WriteInt64(Position + 0x10, Align); - - return 0; - } - - private static long NvGpuAsIoctlMapBufferEx(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - - int Flags = Reader.ReadInt32(); - int Kind = Reader.ReadInt32(); - int Handle = Reader.ReadInt32(); - int PageSize = Reader.ReadInt32(); - long BuffAddr = Reader.ReadInt64(); - long MapSize = Reader.ReadInt64(); - long Offset = Reader.ReadInt64(); - - HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); - - if (NvMap != null) - { - if ((Flags & 1) != 0) - { - Offset = Context.Ns.Gpu.MapMemory(NvMap.Address, Offset, NvMap.Size); - } - else - { - Offset = Context.Ns.Gpu.MapMemory(NvMap.Address, NvMap.Size); - } - } - - Context.Memory.WriteInt64(Position + 0x20, Offset); - - return 0; - } - - private static long NvGpuAsIoctlGetVaRegions(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - MemWriter Writer = new MemWriter(Context.Memory, Position); - - long Unused = Reader.ReadInt64(); - int BuffSize = Reader.ReadInt32(); - int Padding = Reader.ReadInt32(); - - BuffSize = 0x30; - - Writer.WriteInt64(Unused); - Writer.WriteInt32(BuffSize); - Writer.WriteInt32(Padding); - - Writer.WriteInt64(0); - Writer.WriteInt32(0); - Writer.WriteInt32(0); - Writer.WriteInt64(0); - - Writer.WriteInt64(0); - Writer.WriteInt32(0); - Writer.WriteInt32(0); - Writer.WriteInt64(0); - - return 0; - } - - private static long NvGpuAsIoctlInitializeEx(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - - int BigPageSize = Reader.ReadInt32(); - int AsFd = Reader.ReadInt32(); - int Flags = Reader.ReadInt32(); - int Reserved = Reader.ReadInt32(); - long Unknown10 = Reader.ReadInt64(); - long Unknown18 = Reader.ReadInt64(); - long Unknown20 = Reader.ReadInt64(); - - return 0; - } - - private static long NvHostIoctlCtrlGetConfig(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - MemWriter Writer = new MemWriter(Context.Memory, Position + 0x82); - - for (int Index = 0; Index < 0x101; Index++) - { - Writer.WriteByte(0); - } - - return 0; - } - - private static long NvHostIoctlCtrlEventWait(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - - int SyncPtId = Reader.ReadInt32(); - int Threshold = Reader.ReadInt32(); - int Timeout = Reader.ReadInt32(); - int Value = Reader.ReadInt32(); - - Context.Memory.WriteInt32(Position + 0xc, 0xcafe); - - return 0; - } - - private static long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - Context.Memory.WriteInt32(Position, 1); - - return 0; - } - - private static long NvGpuIoctlZcullGetInfo(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemWriter Writer = new MemWriter(Context.Memory, Position); - - Writer.WriteInt32(0); - Writer.WriteInt32(0); - Writer.WriteInt32(0); - Writer.WriteInt32(0); - Writer.WriteInt32(0); - Writer.WriteInt32(0); - Writer.WriteInt32(0); - Writer.WriteInt32(0); - Writer.WriteInt32(0); - Writer.WriteInt32(0); - - return 0; - } - - private static long NvGpuIoctlGetCharacteristics(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - MemWriter Writer = new MemWriter(Context.Memory, Position); - - //Note: We should just ignore the BuffAddr, because official code - //does __memcpy_device from Position + 0x10 to BuffAddr. - long BuffSize = Reader.ReadInt64(); - long BuffAddr = Reader.ReadInt64(); - - BuffSize = 0xa0; - - Writer.WriteInt64(BuffSize); - Writer.WriteInt64(BuffAddr); - Writer.WriteInt32(0x120); //NVGPU_GPU_ARCH_GM200 - Writer.WriteInt32(0xb); //NVGPU_GPU_IMPL_GM20B - Writer.WriteInt32(0xa1); - Writer.WriteInt32(1); - Writer.WriteInt64(0x40000); - Writer.WriteInt64(0); - Writer.WriteInt32(2); - Writer.WriteInt32(0x20); //NVGPU_GPU_BUS_TYPE_AXI - Writer.WriteInt32(0x20000); - Writer.WriteInt32(0x20000); - Writer.WriteInt32(0x1b); - Writer.WriteInt32(0x30000); - Writer.WriteInt32(1); - Writer.WriteInt32(0x503); - Writer.WriteInt32(0x503); - Writer.WriteInt32(0x80); - Writer.WriteInt32(0x28); - Writer.WriteInt32(0); - Writer.WriteInt64(0x55); - Writer.WriteInt32(0x902d); //FERMI_TWOD_A - Writer.WriteInt32(0xb197); //MAXWELL_B - Writer.WriteInt32(0xb1c0); //MAXWELL_COMPUTE_B - Writer.WriteInt32(0xb06f); //MAXWELL_CHANNEL_GPFIFO_A - Writer.WriteInt32(0xa140); //KEPLER_INLINE_TO_MEMORY_B - Writer.WriteInt32(0xb0b5); //MAXWELL_DMA_COPY_A - Writer.WriteInt32(1); - Writer.WriteInt32(0); - Writer.WriteInt32(2); - Writer.WriteInt32(1); - Writer.WriteInt32(0); - Writer.WriteInt32(1); - Writer.WriteInt32(0x21d70); - Writer.WriteInt32(0); - Writer.WriteByte((byte)'g'); - Writer.WriteByte((byte)'m'); - Writer.WriteByte((byte)'2'); - Writer.WriteByte((byte)'0'); - Writer.WriteByte((byte)'b'); - Writer.WriteByte((byte)'\0'); - Writer.WriteByte((byte)'\0'); - Writer.WriteByte((byte)'\0'); - Writer.WriteInt64(0); - - return 0; - } - - private static long NvGpuIoctlGetTpcMasks(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - - int MaskBuffSize = Reader.ReadInt32(); - int Reserved = Reader.ReadInt32(); - long MaskBuffAddr = Reader.ReadInt64(); - long Unknown = Reader.ReadInt64(); - - return 0; - } - - private static long NvGpuIoctlZbcGetActiveSlotMask(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - Context.Memory.WriteInt32(Position + 0, 7); - Context.Memory.WriteInt32(Position + 4, 1); - - return 0; - } - - private static long NvMapIoctlChannelSetUserData(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - return 0; - } - - private static long NvMapIoctlChannelSetNvMap(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - int Fd = Context.Memory.ReadInt32(Position); - - return 0; - } - - private static long NvMapIoctlChannelSubmitGpFifo(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - MemWriter Writer = new MemWriter(Context.Memory, Position + 0x10); - - long GpFifo = Reader.ReadInt64(); - int Count = Reader.ReadInt32(); - int Flags = Reader.ReadInt32(); - int FenceId = Reader.ReadInt32(); - int FenceVal = Reader.ReadInt32(); - - for (int Index = 0; Index < Count; Index++) - { - long GpFifoHdr = Reader.ReadInt64(); - - long GpuAddr = GpFifoHdr & 0xffffffffff; - - int Size = (int)(GpFifoHdr >> 40) & 0x7ffffc; - - long CpuAddr = Context.Ns.Gpu.GetCpuAddr(GpuAddr); - - if (CpuAddr != -1) - { - byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, CpuAddr, Size); - - NsGpuPBEntry[] PushBuffer = NsGpuPBEntry.DecodePushBuffer(Data); - - Context.Ns.Gpu.ProcessPushBuffer(PushBuffer, Context.Memory); - } - } - - Writer.WriteInt32(0); - Writer.WriteInt32(0); - - return 0; - } - - private static long NvMapIoctlChannelAllocObjCtx(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - int ClassNum = Context.Memory.ReadInt32(Position + 0); - int Flags = Context.Memory.ReadInt32(Position + 4); - - Context.Memory.WriteInt32(Position + 8, 0); - - return 0; - } - - private static long NvMapIoctlChannelZcullBind(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - - long GpuVa = Reader.ReadInt64(); - int Mode = Reader.ReadInt32(); - int Padding = Reader.ReadInt32(); - - return 0; - } - - private static long NvMapIoctlChannelSetErrorNotifier(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - - long Offset = Reader.ReadInt64(); - long Size = Reader.ReadInt64(); - int Mem = Reader.ReadInt32(); - int Padding = Reader.ReadInt32(); - - return 0; - } - - private static long NvMapIoctlChannelSetPriority(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - int Priority = Context.Memory.ReadInt32(Position); - - return 0; - } - - private static long NvMapIoctlChannelAllocGpFifoEx2(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - - MemReader Reader = new MemReader(Context.Memory, Position); - MemWriter Writer = new MemWriter(Context.Memory, Position + 0xc); - - int Count = Reader.ReadInt32(); - int Flags = Reader.ReadInt32(); - int Unknown8 = Reader.ReadInt32(); - long Fence = Reader.ReadInt64(); - int Unknown14 = Reader.ReadInt32(); - int Unknown18 = Reader.ReadInt32(); - - Writer.WriteInt32(0); - Writer.WriteInt32(0); - - return 0; - } - - private static long NvMapIocCreate(ServiceCtx Context) - { - long Position = Context.Request.GetSendBuffPtr(); - - int Size = Context.Memory.ReadInt32(Position); - - int Id = Context.Ns.Os.NvMapIds.GenerateId(); - - int Handle = Context.Ns.Os.Handles.GenerateId(new HNvMap(Id, Size)); - - Context.Memory.WriteInt32(Position + 4, Handle); - - return 0; - } - - private static long NvMapIocFromId(ServiceCtx Context) - { - long Position = Context.Request.GetSendBuffPtr(); - - int Id = Context.Memory.ReadInt32(Position); - - int Handle = -1; - - foreach (KeyValuePair KV in Context.Ns.Os.Handles) - { - if (KV.Value is HNvMap NvMap && NvMap.Id == Id) - { - Handle = KV.Key; - - break; - } - } - - Context.Memory.WriteInt32(Position + 4, Handle); - - return 0; - } - - private static long NvMapIocAlloc(ServiceCtx Context) - { - long Position = Context.Request.GetSendBuffPtr(); - - MemReader Reader = new MemReader(Context.Memory, Position); - - int Handle = Reader.ReadInt32(); - int HeapMask = Reader.ReadInt32(); - int Flags = Reader.ReadInt32(); - int Align = Reader.ReadInt32(); - byte Kind = (byte)Reader.ReadInt64(); - long Addr = Reader.ReadInt64(); - - HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); - - if (NvMap != null) - { - NvMap.Address = Addr; - NvMap.Align = Align; - NvMap.Kind = Kind; - } - - Logging.Debug($"NvMapIocAlloc at {NvMap.Address:x16}"); - - return 0; - } - - private static long NvMapIocParam(ServiceCtx Context) - { - long Position = Context.Request.GetSendBuffPtr(); - - MemReader Reader = new MemReader(Context.Memory, Position); - - int Handle = Reader.ReadInt32(); - int Param = Reader.ReadInt32(); - - HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); - - int Response = 0; - - switch (Param) - { - case 1: Response = NvMap.Size; break; - case 2: Response = NvMap.Align; break; - case 4: Response = 0x40000000; break; - case 5: Response = NvMap.Kind; break; - } - - Context.Memory.WriteInt32(Position + 8, Response); - - return 0; - } - - private static long NvMapIocGetId(ServiceCtx Context) - { - long Position = Context.Request.GetSendBuffPtr(); - - int Handle = Context.Memory.ReadInt32(Position + 4); - - HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); - - Context.Memory.WriteInt32(Position, NvMap.Id); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServicePctl.cs b/Ryujinx.Core/OsHle/Services/ServicePctl.cs deleted file mode 100644 index 9c4406bb..00000000 --- a/Ryujinx.Core/OsHle/Services/ServicePctl.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Am; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long PctlCreateService(ServiceCtx Context) - { - MakeObject(Context, new IParentalControlService()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServicePl.cs b/Ryujinx.Core/OsHle/Services/ServicePl.cs deleted file mode 100644 index 21e6741c..00000000 --- a/Ryujinx.Core/OsHle/Services/ServicePl.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long PlGetLoadState(ServiceCtx Context) - { - Context.ResponseData.Write(1); //Loaded - - return 0; - } - - public static long PlGetFontSize(ServiceCtx Context) - { - Context.ResponseData.Write(Horizon.FontSize); - - return 0; - } - - public static long PlGetSharedMemoryAddressOffset(ServiceCtx Context) - { - Context.ResponseData.Write(0); - - return 0; - } - - public static long PlGetSharedMemoryNativeHandle(ServiceCtx Context) - { - Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Context.Ns.Os.FontHandle); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceSet.cs b/Ryujinx.Core/OsHle/Services/ServiceSet.cs deleted file mode 100644 index 83ea5b2c..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceSet.cs +++ /dev/null @@ -1,32 +0,0 @@ -using ChocolArm64.Memory; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - private const int LangCodesCount = 13; - - public static long SetGetAvailableLanguageCodes(ServiceCtx Context) - { - int PtrBuffSize = Context.RequestData.ReadInt32(); - - if (Context.Request.RecvListBuff.Count > 0) - { - long Position = Context.Request.RecvListBuff[0].Position; - short Size = Context.Request.RecvListBuff[0].Size; - - //This should return an array of ints with values matching the LanguageCode enum. - byte[] Data = new byte[Size]; - - Data[0] = 0; - Data[1] = 1; - - AMemoryHelper.WriteBytes(Context.Memory, Position, Data); - } - - Context.ResponseData.Write(LangCodesCount); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceSm.cs b/Ryujinx.Core/OsHle/Services/ServiceSm.cs deleted file mode 100644 index 58abed24..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceSm.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Ipc; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - private const int SmNotInitialized = 0x415; - - public static long SmInitialize(ServiceCtx Context) - { - Context.Session.Initialize(); - - return 0; - } - - public static long SmGetService(ServiceCtx Context) - { - //Only for kernel version > 3.0.0. - if (!Context.Session.IsInitialized) - { - //return SmNotInitialized; - } - - string Name = string.Empty; - - for (int Index = 0; Index < 8 && - Context.RequestData.BaseStream.Position < - Context.RequestData.BaseStream.Length; Index++) - { - byte Chr = Context.RequestData.ReadByte(); - - if (Chr >= 0x20 && Chr < 0x7f) - { - Name += (char)Chr; - } - } - - HSession Session = new HSession(Name); - - int Handle = Context.Ns.Os.Handles.GenerateId(Session); - - Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceTime.cs b/Ryujinx.Core/OsHle/Services/ServiceTime.cs deleted file mode 100644 index a5fddcba..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceTime.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Time; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long TimeGetStandardUserSystemClock(ServiceCtx Context) - { - MakeObject(Context, new ISystemClock(SystemClockType.User)); - - return 0; - } - - public static long TimeGetStandardNetworkSystemClock(ServiceCtx Context) - { - MakeObject(Context, new ISystemClock(SystemClockType.Network)); - - return 0; - } - - public static long TimeGetStandardSteadyClock(ServiceCtx Context) - { - MakeObject(Context, new ISteadyClock()); - - return 0; - } - - public static long TimeGetTimeZoneService(ServiceCtx Context) - { - MakeObject(Context, new ITimeZoneService()); - - return 0; - } - - public static long TimeGetStandardLocalSystemClock(ServiceCtx Context) - { - MakeObject(Context, new ISystemClock(SystemClockType.Local)); - - return 0; - } - - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceVi.cs b/Ryujinx.Core/OsHle/Services/ServiceVi.cs deleted file mode 100644 index 75cdc31b..00000000 --- a/Ryujinx.Core/OsHle/Services/ServiceVi.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Vi; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long ViGetDisplayService(ServiceCtx Context) - { - int Unknown = Context.RequestData.ReadInt32(); - - MakeObject(Context, new IApplicationDisplayService()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index a69d3b40..3b9142c7 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -3,6 +3,7 @@ using ChocolArm64.State; using Ryujinx.Core.OsHle.Exceptions; using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; +using Ryujinx.Core.OsHle.IpcServices; using System; using System.Threading; @@ -61,7 +62,7 @@ namespace Ryujinx.Core.OsHle.Svc //TODO: Validate that app has perms to access the service, and that the service //actually exists, return error codes otherwise. - HSession Session = new HSession(Name); + HSession Session = new HSession(ServiceFactory.MakeService(Name)); ThreadState.X1 = (ulong)Ns.Os.Handles.GenerateId(Session); ThreadState.X0 = (int)SvcResult.Success; -- cgit v1.2.3