2018-09-08 19:33:27 +01:00
|
|
|
using LibHac;
|
2020-04-30 05:58:19 +01:00
|
|
|
using LibHac.Bcat;
|
2019-06-01 01:31:10 +01:00
|
|
|
using LibHac.Fs;
|
2019-10-17 07:17:44 +01:00
|
|
|
using LibHac.FsSystem;
|
2021-02-26 00:11:56 +00:00
|
|
|
using Ryujinx.Audio;
|
|
|
|
using Ryujinx.Audio.Input;
|
|
|
|
using Ryujinx.Audio.Integration;
|
|
|
|
using Ryujinx.Audio.Output;
|
2020-08-18 02:49:37 +01:00
|
|
|
using Ryujinx.Audio.Renderer.Device;
|
|
|
|
using Ryujinx.Audio.Renderer.Server;
|
2020-04-23 12:59:11 +01:00
|
|
|
using Ryujinx.Common;
|
2021-03-18 23:09:33 +00:00
|
|
|
using Ryujinx.Common.Logging;
|
2020-04-17 00:18:54 +01:00
|
|
|
using Ryujinx.Configuration;
|
2018-11-18 19:37:41 +00:00
|
|
|
using Ryujinx.HLE.FileSystem.Content;
|
2018-08-17 00:47:36 +01:00
|
|
|
using Ryujinx.HLE.HOS.Font;
|
2020-05-04 04:41:29 +01:00
|
|
|
using Ryujinx.HLE.HOS.Kernel;
|
2018-12-18 05:33:36 +00:00
|
|
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
2020-12-02 12:14:44 +00:00
|
|
|
using Ryujinx.HLE.HOS.Services;
|
2021-04-13 02:16:43 +01:00
|
|
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
2020-04-23 12:59:11 +01:00
|
|
|
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy;
|
2020-11-08 20:00:54 +00:00
|
|
|
using Ryujinx.HLE.HOS.Services.Apm;
|
2020-04-30 05:58:19 +01:00
|
|
|
using Ryujinx.HLE.HOS.Services.Arp;
|
2020-08-18 02:49:37 +01:00
|
|
|
using Ryujinx.HLE.HOS.Services.Audio.AudioRenderer;
|
2021-03-26 00:16:08 +00:00
|
|
|
using Ryujinx.HLE.HOS.Services.Caps;
|
2020-03-01 22:56:02 +00:00
|
|
|
using Ryujinx.HLE.HOS.Services.Mii;
|
2021-03-18 20:40:20 +00:00
|
|
|
using Ryujinx.HLE.HOS.Services.Nfc.Nfp.UserManager;
|
2020-04-23 12:59:11 +01:00
|
|
|
using Ryujinx.HLE.HOS.Services.Nv;
|
2020-04-19 02:25:57 +01:00
|
|
|
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl;
|
2019-10-08 04:48:49 +01:00
|
|
|
using Ryujinx.HLE.HOS.Services.Pcv.Bpc;
|
2019-09-19 01:45:11 +01:00
|
|
|
using Ryujinx.HLE.HOS.Services.Settings;
|
2019-01-18 22:26:39 +00:00
|
|
|
using Ryujinx.HLE.HOS.Services.Sm;
|
2020-04-19 02:25:57 +01:00
|
|
|
using Ryujinx.HLE.HOS.Services.SurfaceFlinger;
|
2019-07-14 21:50:11 +01:00
|
|
|
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
2018-08-17 00:47:36 +01:00
|
|
|
using Ryujinx.HLE.HOS.SystemState;
|
2018-06-11 01:46:42 +01:00
|
|
|
using Ryujinx.HLE.Loaders.Executables;
|
2019-10-08 04:48:49 +01:00
|
|
|
using Ryujinx.HLE.Utilities;
|
2018-02-20 20:09:23 +00:00
|
|
|
using System;
|
2021-03-18 20:40:20 +00:00
|
|
|
using System.Collections.Generic;
|
2018-02-04 23:08:20 +00:00
|
|
|
using System.IO;
|
2020-12-17 00:44:06 +00:00
|
|
|
using System.Linq;
|
2020-09-22 05:50:40 +01:00
|
|
|
using System.Threading;
|
2020-01-12 11:15:17 +00:00
|
|
|
|
2018-08-17 00:47:36 +01:00
|
|
|
namespace Ryujinx.HLE.HOS
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
2020-05-04 04:41:29 +01:00
|
|
|
using TimeServiceManager = Services.Time.TimeManager;
|
|
|
|
|
2018-03-12 04:04:52 +00:00
|
|
|
public class Horizon : IDisposable
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
|
|
|
internal const int HidSize = 0x40000;
|
2018-08-15 19:59:51 +01:00
|
|
|
internal const int FontSize = 0x1100000;
|
2019-04-20 03:23:13 +01:00
|
|
|
internal const int IirsSize = 0x8000;
|
2019-06-17 00:56:46 +01:00
|
|
|
internal const int TimeSize = 0x1000;
|
2018-02-04 23:08:20 +00:00
|
|
|
|
2020-05-04 04:41:29 +01:00
|
|
|
internal KernelContext KernelContext { get; }
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-05 00:52:39 +00:00
|
|
|
internal Switch Device { get; private set; }
|
2018-02-04 23:08:20 +00:00
|
|
|
|
2020-04-22 05:10:27 +01:00
|
|
|
internal SurfaceFlinger SurfaceFlinger { get; private set; }
|
2021-02-26 00:11:56 +00:00
|
|
|
internal AudioManager AudioManager { get; private set; }
|
|
|
|
internal AudioOutputManager AudioOutputManager { get; private set; }
|
|
|
|
internal AudioInputManager AudioInputManager { get; private set; }
|
2020-08-18 02:49:37 +01:00
|
|
|
internal AudioRendererManager AudioRendererManager { get; private set; }
|
|
|
|
internal VirtualDeviceSessionRegistry AudioDeviceSessionRegistry { get; private set; }
|
2020-04-22 05:10:27 +01:00
|
|
|
|
2018-12-05 00:52:39 +00:00
|
|
|
public SystemStateMgr State { get; private set; }
|
2018-04-24 21:14:26 +01:00
|
|
|
|
2020-11-08 20:00:54 +00:00
|
|
|
internal PerformanceState PerformanceState { get; private set; }
|
|
|
|
|
2018-12-05 00:52:39 +00:00
|
|
|
internal AppletStateMgr AppletState { get; private set; }
|
2018-09-19 00:36:43 +01:00
|
|
|
|
2021-03-18 20:40:20 +00:00
|
|
|
internal List<NfpDevice> NfpDevices { get; private set; }
|
|
|
|
|
2020-12-02 12:14:44 +00:00
|
|
|
internal ServerBase BsdServer { get; private set; }
|
|
|
|
internal ServerBase AudRenServer { get; private set; }
|
|
|
|
internal ServerBase AudOutServer { get; private set; }
|
|
|
|
internal ServerBase HidServer { get; private set; }
|
|
|
|
internal ServerBase NvDrvServer { get; private set; }
|
|
|
|
internal ServerBase TimeServer { get; private set; }
|
|
|
|
internal ServerBase ViServer { get; private set; }
|
|
|
|
internal ServerBase ViServerM { get; private set; }
|
|
|
|
internal ServerBase ViServerS { get; private set; }
|
|
|
|
|
2018-12-05 00:52:39 +00:00
|
|
|
internal KSharedMemory HidSharedMem { get; private set; }
|
|
|
|
internal KSharedMemory FontSharedMem { get; private set; }
|
2019-04-20 03:23:13 +01:00
|
|
|
internal KSharedMemory IirsSharedMem { get; private set; }
|
2018-12-05 00:52:39 +00:00
|
|
|
internal SharedFontManager Font { get; private set; }
|
2018-03-19 18:58:46 +00:00
|
|
|
|
2021-04-13 02:16:43 +01:00
|
|
|
internal AccountManager AccountManager { get; private set; }
|
2018-12-05 00:52:39 +00:00
|
|
|
internal ContentManager ContentManager { get; private set; }
|
2021-03-26 00:16:08 +00:00
|
|
|
internal CaptureManager CaptureManager { get; private set; }
|
2018-11-18 19:37:41 +00:00
|
|
|
|
2018-12-05 00:52:39 +00:00
|
|
|
internal KEvent VsyncEvent { get; private set; }
|
2018-02-17 21:36:08 +00:00
|
|
|
|
2020-04-23 12:59:11 +01:00
|
|
|
internal KEvent DisplayResolutionChangeEvent { get; private set; }
|
|
|
|
|
2020-01-21 22:23:11 +00:00
|
|
|
public Keyset KeySet => Device.FileSystem.KeySet;
|
2018-09-08 19:33:27 +01:00
|
|
|
|
2020-02-06 11:38:24 +00:00
|
|
|
private bool _isDisposed;
|
2018-09-19 00:36:43 +01:00
|
|
|
|
2020-06-16 19:28:02 +01:00
|
|
|
public bool EnablePtc { get; set; }
|
2020-04-12 22:02:37 +01:00
|
|
|
|
2018-10-31 02:34:27 +00:00
|
|
|
public IntegrityCheckLevel FsIntegrityCheckLevel { get; set; }
|
2018-10-06 16:11:47 +01:00
|
|
|
|
2019-06-16 02:31:18 +01:00
|
|
|
public int GlobalAccessLogMode { get; set; }
|
|
|
|
|
2020-05-03 23:54:50 +01:00
|
|
|
internal ulong HidBaseAddress { get; private set; }
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2020-04-19 02:25:57 +01:00
|
|
|
internal NvHostSyncpt HostSyncpoint { get; private set; }
|
|
|
|
|
2020-04-30 05:58:19 +01:00
|
|
|
internal LibHac.Horizon LibHacHorizonServer { get; private set; }
|
|
|
|
internal HorizonClient LibHacHorizonClient { get; private set; }
|
|
|
|
|
2021-04-13 02:16:43 +01:00
|
|
|
public Horizon(Switch device, ContentManager contentManager, AccountManager accountManager, MemoryConfiguration memoryConfiguration)
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
2021-04-04 13:06:59 +01:00
|
|
|
KernelContext = new KernelContext(
|
|
|
|
device,
|
|
|
|
device.Memory,
|
|
|
|
memoryConfiguration.ToKernelMemorySize(),
|
|
|
|
memoryConfiguration.ToKernelMemoryArrange());
|
2020-05-04 04:41:29 +01:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
Device = device;
|
2018-02-04 23:08:20 +00:00
|
|
|
|
2018-08-17 00:47:36 +01:00
|
|
|
State = new SystemStateMgr();
|
2018-04-24 21:14:26 +01:00
|
|
|
|
2020-11-08 20:00:54 +00:00
|
|
|
PerformanceState = new PerformanceState();
|
|
|
|
|
2021-03-18 20:40:20 +00:00
|
|
|
NfpDevices = new List<NfpDevice>();
|
|
|
|
|
2019-07-02 03:39:22 +01:00
|
|
|
// Note: This is not really correct, but with HLE of services, the only memory
|
|
|
|
// region used that is used is Application, so we can use the other ones for anything.
|
2020-05-04 04:41:29 +01:00
|
|
|
KMemoryRegionManager region = KernelContext.MemoryRegions[(int)MemoryRegion.NvServices];
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
ulong hidPa = region.Address;
|
|
|
|
ulong fontPa = region.Address + HidSize;
|
2019-04-20 03:23:13 +01:00
|
|
|
ulong iirsPa = region.Address + HidSize + FontSize;
|
2019-06-17 00:56:46 +01:00
|
|
|
ulong timePa = region.Address + HidSize + FontSize + IirsSize;
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2020-05-03 23:54:50 +01:00
|
|
|
HidBaseAddress = hidPa - DramMemoryMap.DramBase;
|
2018-08-15 19:59:51 +01:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
KPageList hidPageList = new KPageList();
|
|
|
|
KPageList fontPageList = new KPageList();
|
2019-04-20 03:23:13 +01:00
|
|
|
KPageList iirsPageList = new KPageList();
|
2019-06-17 00:56:46 +01:00
|
|
|
KPageList timePageList = new KPageList();
|
NvServices refactoring (#120)
* Initial implementation of NvMap/NvHostCtrl
* More work on NvHostCtrl
* Refactoring of nvservices, move GPU Vmm, make Vmm per-process, refactor most gpu devices, move Gpu to Core, fix CbBind
* Implement GetGpuTime, support CancelSynchronization, fix issue on InsertWaitingMutex, proper double buffering support (again, not working properly for commercial games, only hb)
* Try to fix perf regression reading/writing textures, moved syncpts and events to a UserCtx class, delete global state when the process exits, other minor tweaks
* Remove now unused code, add comment about probably wrong result codes
2018-05-07 19:53:23 +01:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
hidPageList .AddRange(hidPa, HidSize / KMemoryManager.PageSize);
|
|
|
|
fontPageList.AddRange(fontPa, FontSize / KMemoryManager.PageSize);
|
2019-04-20 03:23:13 +01:00
|
|
|
iirsPageList.AddRange(iirsPa, IirsSize / KMemoryManager.PageSize);
|
2019-06-17 00:56:46 +01:00
|
|
|
timePageList.AddRange(timePa, TimeSize / KMemoryManager.PageSize);
|
2018-11-28 22:18:09 +00:00
|
|
|
|
2020-12-01 23:23:43 +00:00
|
|
|
HidSharedMem = new KSharedMemory(KernelContext, hidPageList, 0, 0, KMemoryPermission.Read);
|
|
|
|
FontSharedMem = new KSharedMemory(KernelContext, fontPageList, 0, 0, KMemoryPermission.Read);
|
|
|
|
IirsSharedMem = new KSharedMemory(KernelContext, iirsPageList, 0, 0, KMemoryPermission.Read);
|
2019-10-08 04:48:49 +01:00
|
|
|
|
2020-12-01 23:23:43 +00:00
|
|
|
KSharedMemory timeSharedMemory = new KSharedMemory(KernelContext, timePageList, 0, 0, KMemoryPermission.Read);
|
2019-10-08 04:48:49 +01:00
|
|
|
|
2020-05-03 23:54:50 +01:00
|
|
|
TimeServiceManager.Instance.Initialize(device, this, timeSharedMemory, timePa - DramMemoryMap.DramBase, TimeSize);
|
2018-11-28 22:18:09 +00:00
|
|
|
|
|
|
|
AppletState = new AppletStateMgr(this);
|
|
|
|
|
|
|
|
AppletState.SetFocus(true);
|
|
|
|
|
2020-05-03 23:54:50 +01:00
|
|
|
Font = new SharedFontManager(device, fontPa - DramMemoryMap.DramBase);
|
2018-03-19 18:58:46 +00:00
|
|
|
|
2020-05-04 04:41:29 +01:00
|
|
|
VsyncEvent = new KEvent(KernelContext);
|
2018-09-08 19:33:27 +01:00
|
|
|
|
2020-05-04 04:41:29 +01:00
|
|
|
DisplayResolutionChangeEvent = new KEvent(KernelContext);
|
2020-04-23 12:59:11 +01:00
|
|
|
|
2021-04-13 02:16:43 +01:00
|
|
|
AccountManager = accountManager;
|
2020-01-21 22:23:11 +00:00
|
|
|
ContentManager = contentManager;
|
2021-03-26 00:16:08 +00:00
|
|
|
CaptureManager = new CaptureManager(device);
|
2019-07-14 21:50:11 +01:00
|
|
|
|
2019-10-08 04:48:49 +01:00
|
|
|
// TODO: use set:sys (and get external clock source id from settings)
|
2019-07-15 18:52:35 +01:00
|
|
|
// TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate.
|
2019-10-08 04:48:49 +01:00
|
|
|
UInt128 clockSourceId = new UInt128(Guid.NewGuid().ToByteArray());
|
|
|
|
IRtcManager.GetExternalRtcValue(out ulong rtcValue);
|
|
|
|
|
|
|
|
// We assume the rtc is system time.
|
|
|
|
TimeSpanType systemTime = TimeSpanType.FromSeconds((long)rtcValue);
|
|
|
|
|
2020-04-17 00:18:54 +01:00
|
|
|
// Configure and setup internal offset
|
|
|
|
TimeSpanType internalOffset = TimeSpanType.FromSeconds(ConfigurationState.Instance.System.SystemTimeOffset);
|
2020-09-22 05:50:40 +01:00
|
|
|
|
2020-04-17 00:18:54 +01:00
|
|
|
TimeSpanType systemTimeOffset = new TimeSpanType(systemTime.NanoSeconds + internalOffset.NanoSeconds);
|
|
|
|
|
|
|
|
if (systemTime.IsDaylightSavingTime() && !systemTimeOffset.IsDaylightSavingTime())
|
|
|
|
{
|
|
|
|
internalOffset = internalOffset.AddSeconds(3600L);
|
|
|
|
}
|
|
|
|
else if (!systemTime.IsDaylightSavingTime() && systemTimeOffset.IsDaylightSavingTime())
|
|
|
|
{
|
|
|
|
internalOffset = internalOffset.AddSeconds(-3600L);
|
|
|
|
}
|
|
|
|
|
|
|
|
internalOffset = new TimeSpanType(-internalOffset.NanoSeconds);
|
|
|
|
|
2019-10-08 04:48:49 +01:00
|
|
|
// First init the standard steady clock
|
2020-04-17 00:18:54 +01:00
|
|
|
TimeServiceManager.Instance.SetupStandardSteadyClock(null, clockSourceId, systemTime, internalOffset, TimeSpanType.Zero, false);
|
2019-10-08 04:48:49 +01:00
|
|
|
TimeServiceManager.Instance.SetupStandardLocalSystemClock(null, new SystemClockContext(), systemTime.ToSeconds());
|
2019-07-15 18:52:35 +01:00
|
|
|
|
2019-09-19 01:45:11 +01:00
|
|
|
if (NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes))
|
2019-07-15 18:52:35 +01:00
|
|
|
{
|
|
|
|
TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000);
|
|
|
|
|
2020-05-20 10:35:30 +01:00
|
|
|
// The network system clock needs a valid system clock, as such we setup this system clock using the local system clock.
|
|
|
|
TimeServiceManager.Instance.StandardLocalSystemClock.GetClockContext(null, out SystemClockContext localSytemClockContext);
|
|
|
|
TimeServiceManager.Instance.SetupStandardNetworkSystemClock(localSytemClockContext, standardNetworkClockSufficientAccuracy);
|
2019-07-15 18:52:35 +01:00
|
|
|
}
|
|
|
|
|
2019-10-08 04:48:49 +01:00
|
|
|
TimeServiceManager.Instance.SetupStandardUserSystemClock(null, false, SteadyClockTimePoint.GetRandom());
|
|
|
|
|
|
|
|
// FIXME: TimeZone shoud be init here but it's actually done in ContentManager
|
|
|
|
|
|
|
|
TimeServiceManager.Instance.SetupEphemeralNetworkSystemClock();
|
2020-03-01 22:56:02 +00:00
|
|
|
|
|
|
|
DatabaseImpl.Instance.InitializeDatabase(device);
|
2020-04-19 02:25:57 +01:00
|
|
|
|
|
|
|
HostSyncpoint = new NvHostSyncpt(device);
|
2020-04-22 05:10:27 +01:00
|
|
|
|
|
|
|
SurfaceFlinger = new SurfaceFlinger(device);
|
2020-04-23 12:59:11 +01:00
|
|
|
|
|
|
|
ConfigurationState.Instance.System.EnableDockedMode.Event += OnDockedModeChange;
|
2020-04-30 05:58:19 +01:00
|
|
|
|
|
|
|
InitLibHacHorizon();
|
2020-08-18 02:49:37 +01:00
|
|
|
InitializeAudioRenderer();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void InitializeAudioRenderer()
|
|
|
|
{
|
2021-02-26 00:11:56 +00:00
|
|
|
AudioManager = new AudioManager();
|
|
|
|
AudioOutputManager = new AudioOutputManager();
|
|
|
|
AudioInputManager = new AudioInputManager();
|
2020-08-18 02:49:37 +01:00
|
|
|
AudioRendererManager = new AudioRendererManager();
|
|
|
|
AudioDeviceSessionRegistry = new VirtualDeviceSessionRegistry();
|
|
|
|
|
2021-02-26 00:11:56 +00:00
|
|
|
IWritableEvent[] audioOutputRegisterBufferEvents = new IWritableEvent[Constants.AudioOutSessionCountMax];
|
2020-08-18 02:49:37 +01:00
|
|
|
|
2021-02-26 00:11:56 +00:00
|
|
|
for (int i = 0; i < audioOutputRegisterBufferEvents.Length; i++)
|
2020-08-18 02:49:37 +01:00
|
|
|
{
|
2021-02-26 00:11:56 +00:00
|
|
|
KEvent registerBufferEvent = new KEvent(KernelContext);
|
2020-08-18 02:49:37 +01:00
|
|
|
|
2021-02-26 00:11:56 +00:00
|
|
|
audioOutputRegisterBufferEvents[i] = new AudioKernelEvent(registerBufferEvent);
|
2020-08-18 02:49:37 +01:00
|
|
|
}
|
|
|
|
|
2021-02-26 00:11:56 +00:00
|
|
|
AudioOutputManager.Initialize(Device.AudioDeviceDriver, audioOutputRegisterBufferEvents);
|
|
|
|
|
|
|
|
IWritableEvent[] audioInputRegisterBufferEvents = new IWritableEvent[Constants.AudioInSessionCountMax];
|
2020-08-18 02:49:37 +01:00
|
|
|
|
2021-02-26 00:11:56 +00:00
|
|
|
for (int i = 0; i < audioInputRegisterBufferEvents.Length; i++)
|
2020-08-18 02:49:37 +01:00
|
|
|
{
|
2021-02-26 00:11:56 +00:00
|
|
|
KEvent registerBufferEvent = new KEvent(KernelContext);
|
|
|
|
|
|
|
|
audioInputRegisterBufferEvents[i] = new AudioKernelEvent(registerBufferEvent);
|
2020-08-18 02:49:37 +01:00
|
|
|
}
|
|
|
|
|
2021-02-26 00:11:56 +00:00
|
|
|
AudioInputManager.Initialize(Device.AudioDeviceDriver, audioInputRegisterBufferEvents);
|
|
|
|
|
|
|
|
IWritableEvent[] systemEvents = new IWritableEvent[Constants.AudioRendererSessionCountMax];
|
|
|
|
|
|
|
|
for (int i = 0; i < systemEvents.Length; i++)
|
|
|
|
{
|
|
|
|
KEvent systemEvent = new KEvent(KernelContext);
|
|
|
|
|
|
|
|
systemEvents[i] = new AudioKernelEvent(systemEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioManager.Initialize(Device.AudioDeviceDriver.GetUpdateRequiredEvent(), AudioOutputManager.Update, AudioInputManager.Update);
|
|
|
|
|
|
|
|
AudioRendererManager.Initialize(systemEvents, Device.AudioDeviceDriver);
|
|
|
|
|
|
|
|
AudioManager.Start();
|
2020-04-30 05:58:19 +01:00
|
|
|
}
|
|
|
|
|
2020-12-01 23:23:43 +00:00
|
|
|
public void InitializeServices()
|
|
|
|
{
|
|
|
|
IUserInterface sm = new IUserInterface(KernelContext);
|
|
|
|
|
|
|
|
// Wait until SM server thread is done with initialization,
|
|
|
|
// only then doing connections to SM is safe.
|
|
|
|
sm.Server.InitDone.WaitOne();
|
|
|
|
sm.Server.InitDone.Dispose();
|
2020-12-02 12:14:44 +00:00
|
|
|
|
|
|
|
BsdServer = new ServerBase(KernelContext, "BsdServer");
|
|
|
|
AudRenServer = new ServerBase(KernelContext, "AudioRendererServer");
|
|
|
|
AudOutServer = new ServerBase(KernelContext, "AudioOutServer");
|
|
|
|
HidServer = new ServerBase(KernelContext, "HidServer");
|
|
|
|
NvDrvServer = new ServerBase(KernelContext, "NvservicesServer");
|
|
|
|
TimeServer = new ServerBase(KernelContext, "TimeServer");
|
|
|
|
ViServer = new ServerBase(KernelContext, "ViServerU");
|
|
|
|
ViServerM = new ServerBase(KernelContext, "ViServerM");
|
|
|
|
ViServerS = new ServerBase(KernelContext, "ViServerS");
|
2020-12-01 23:23:43 +00:00
|
|
|
}
|
|
|
|
|
2020-07-09 05:31:15 +01:00
|
|
|
public void LoadKip(string kipPath)
|
2020-05-15 07:16:46 +01:00
|
|
|
{
|
2020-07-09 05:31:15 +01:00
|
|
|
using IStorage kipFile = new LocalStorage(kipPath, FileAccess.Read);
|
2020-05-15 07:16:46 +01:00
|
|
|
|
2020-07-09 05:31:15 +01:00
|
|
|
ProgramLoader.LoadKip(KernelContext, new KipExecutable(kipFile));
|
2020-05-15 07:16:46 +01:00
|
|
|
}
|
|
|
|
|
2020-04-30 05:58:19 +01:00
|
|
|
private void InitLibHacHorizon()
|
|
|
|
{
|
|
|
|
LibHac.Horizon horizon = new LibHac.Horizon(null, Device.FileSystem.FsServer);
|
|
|
|
|
|
|
|
horizon.CreateHorizonClient(out HorizonClient ryujinxClient).ThrowIfFailure();
|
|
|
|
horizon.CreateHorizonClient(out HorizonClient bcatClient).ThrowIfFailure();
|
|
|
|
|
|
|
|
ryujinxClient.Sm.RegisterService(new LibHacIReader(this), "arp:r").ThrowIfFailure();
|
|
|
|
new BcatServer(bcatClient);
|
|
|
|
|
|
|
|
LibHacHorizonServer = horizon;
|
|
|
|
LibHacHorizonClient = ryujinxClient;
|
2020-04-23 12:59:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private void OnDockedModeChange(object sender, ReactiveEventArgs<bool> e)
|
|
|
|
{
|
|
|
|
if (e.NewValue != State.DockedMode)
|
|
|
|
{
|
|
|
|
State.DockedMode = e.NewValue;
|
2020-11-12 05:59:18 +00:00
|
|
|
PerformanceState.PerformanceMode = State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default;
|
2020-04-23 12:59:11 +01:00
|
|
|
|
2020-12-16 00:41:42 +00:00
|
|
|
AppletState.Messages.Enqueue(MessageInfo.OperationModeChanged);
|
|
|
|
AppletState.Messages.Enqueue(MessageInfo.PerformanceModeChanged);
|
|
|
|
AppletState.MessageEvent.ReadableEvent.Signal();
|
|
|
|
|
2020-04-23 12:59:11 +01:00
|
|
|
SignalDisplayResolutionChange();
|
2020-08-23 21:54:11 +01:00
|
|
|
|
|
|
|
// Reconfigure controllers
|
|
|
|
Device.Hid.RefreshInputConfig(ConfigurationState.Instance.Hid.InputConfig.Value);
|
2021-03-18 23:09:33 +00:00
|
|
|
|
|
|
|
Logger.Info?.Print(LogClass.Application, $"IsDocked toggled to: {State.DockedMode}");
|
2020-04-23 12:59:11 +01:00
|
|
|
}
|
2018-02-04 23:08:20 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 00:41:42 +00:00
|
|
|
public void SimulateWakeUpMessage()
|
|
|
|
{
|
|
|
|
AppletState.Messages.Enqueue(MessageInfo.Resume);
|
|
|
|
AppletState.MessageEvent.ReadableEvent.Signal();
|
|
|
|
}
|
|
|
|
|
2021-03-18 20:40:20 +00:00
|
|
|
public void ScanAmiibo(int nfpDeviceId, string amiiboId, bool useRandomUuid)
|
|
|
|
{
|
|
|
|
if (NfpDevices[nfpDeviceId].State == NfpDeviceState.SearchingForTag)
|
|
|
|
{
|
|
|
|
NfpDevices[nfpDeviceId].State = NfpDeviceState.TagFound;
|
|
|
|
NfpDevices[nfpDeviceId].AmiiboId = amiiboId;
|
|
|
|
NfpDevices[nfpDeviceId].UseRandomUuid = useRandomUuid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool SearchingForAmiibo(out int nfpDeviceId)
|
|
|
|
{
|
|
|
|
nfpDeviceId = default;
|
|
|
|
|
|
|
|
for (int i = 0; i < NfpDevices.Count; i++)
|
|
|
|
{
|
|
|
|
if (NfpDevices[i].State == NfpDeviceState.SearchingForTag)
|
|
|
|
{
|
|
|
|
nfpDeviceId = i;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-04-23 12:59:11 +01:00
|
|
|
public void SignalDisplayResolutionChange()
|
|
|
|
{
|
|
|
|
DisplayResolutionChangeEvent.ReadableEvent.Signal();
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:36:43 +01:00
|
|
|
public void SignalVsync()
|
|
|
|
{
|
2018-09-23 19:11:46 +01:00
|
|
|
VsyncEvent.ReadableEvent.Signal();
|
2018-09-19 00:36:43 +01:00
|
|
|
}
|
2018-03-19 18:58:46 +00:00
|
|
|
|
2018-03-12 04:04:52 +00:00
|
|
|
public void Dispose()
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
2018-03-12 04:04:52 +00:00
|
|
|
Dispose(true);
|
|
|
|
}
|
2018-02-04 23:08:20 +00:00
|
|
|
|
2018-12-06 11:16:24 +00:00
|
|
|
protected virtual void Dispose(bool disposing)
|
2018-03-12 04:04:52 +00:00
|
|
|
{
|
2020-02-06 11:38:24 +00:00
|
|
|
if (!_isDisposed && disposing)
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
2020-04-23 12:59:11 +01:00
|
|
|
ConfigurationState.Instance.System.EnableDockedMode.Event -= OnDockedModeChange;
|
|
|
|
|
2020-02-06 11:38:24 +00:00
|
|
|
_isDisposed = true;
|
|
|
|
|
2020-05-04 04:41:29 +01:00
|
|
|
KProcess terminationProcess = new KProcess(KernelContext);
|
|
|
|
KThread terminationThread = new KThread(KernelContext);
|
2019-12-26 01:50:17 +00:00
|
|
|
|
|
|
|
terminationThread.Initialize(0, 0, 0, 3, 0, terminationProcess, ThreadType.Kernel, () =>
|
2018-03-12 04:04:52 +00:00
|
|
|
{
|
2019-12-26 01:50:17 +00:00
|
|
|
// Force all threads to exit.
|
2020-05-04 04:41:29 +01:00
|
|
|
lock (KernelContext.Processes)
|
2018-11-28 22:18:09 +00:00
|
|
|
{
|
2020-12-17 00:44:06 +00:00
|
|
|
// Terminate application.
|
|
|
|
foreach (KProcess process in KernelContext.Processes.Values.Where(x => x.Flags.HasFlag(ProcessCreationFlags.IsApplication)))
|
|
|
|
{
|
|
|
|
process.Terminate();
|
|
|
|
}
|
|
|
|
|
|
|
|
// The application existed, now surface flinger can exit too.
|
|
|
|
SurfaceFlinger.Dispose();
|
|
|
|
|
|
|
|
// Terminate HLE services (must be done after the application is already terminated,
|
|
|
|
// otherwise the application will receive errors due to service termination.
|
|
|
|
foreach (KProcess process in KernelContext.Processes.Values.Where(x => !x.Flags.HasFlag(ProcessCreationFlags.IsApplication)))
|
2019-12-26 01:50:17 +00:00
|
|
|
{
|
|
|
|
process.Terminate();
|
|
|
|
}
|
2018-11-28 22:18:09 +00:00
|
|
|
}
|
2019-12-29 22:37:54 +00:00
|
|
|
|
|
|
|
// Exit ourself now!
|
2020-12-09 22:20:05 +00:00
|
|
|
KernelStatic.GetCurrentThread().Exit();
|
2019-12-26 01:50:17 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
terminationThread.Start();
|
|
|
|
|
2020-09-22 05:50:40 +01:00
|
|
|
// Wait until the thread is actually started.
|
|
|
|
while (terminationThread.HostThread.ThreadState == ThreadState.Unstarted)
|
|
|
|
{
|
|
|
|
Thread.Sleep(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait until the termination thread is done terminating all the other threads.
|
|
|
|
terminationThread.HostThread.Join();
|
|
|
|
|
2020-04-19 02:25:57 +01:00
|
|
|
// Destroy nvservices channels as KThread could be waiting on some user events.
|
|
|
|
// This is safe as KThread that are likely to call ioctls are going to be terminated by the post handler hook on the SVC facade.
|
|
|
|
INvDrvServices.Destroy();
|
|
|
|
|
2021-02-26 00:11:56 +00:00
|
|
|
AudioManager.Dispose();
|
|
|
|
AudioOutputManager.Dispose();
|
|
|
|
AudioInputManager.Dispose();
|
|
|
|
|
2020-08-18 02:49:37 +01:00
|
|
|
AudioRendererManager.Dispose();
|
|
|
|
|
2020-05-04 04:41:29 +01:00
|
|
|
KernelContext.Dispose();
|
2018-02-04 23:08:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-16 19:28:02 +01:00
|
|
|
}
|