feat: implement real applets
Co-authored-by: Alula <6276139+alula@users.noreply.github.com>
This commit is contained in:
parent
c218305bc0
commit
3b568b61ba
@ -8,7 +8,7 @@ namespace ARMeilleure.Signal
|
|||||||
{
|
{
|
||||||
public static class NativeSignalHandlerGenerator
|
public static class NativeSignalHandlerGenerator
|
||||||
{
|
{
|
||||||
public const int MaxTrackedRanges = 16;
|
public const int MaxTrackedRanges = 256;
|
||||||
|
|
||||||
private const int StructAddressOffset = 0;
|
private const int StructAddressOffset = 0;
|
||||||
private const int StructWriteOffset = 4;
|
private const int StructWriteOffset = 4;
|
||||||
|
@ -25,9 +25,6 @@ namespace Ryujinx.HLE.HOS.Applets
|
|||||||
case AppletId.LibAppletShop:
|
case AppletId.LibAppletShop:
|
||||||
case AppletId.LibAppletOff:
|
case AppletId.LibAppletOff:
|
||||||
return new BrowserApplet();
|
return new BrowserApplet();
|
||||||
case AppletId.MiiEdit:
|
|
||||||
Logger.Warning?.Print(LogClass.Application, $"Please use the MiiEdit inside File/Open Applet");
|
|
||||||
return new DummyApplet(system);
|
|
||||||
case AppletId.Cabinet:
|
case AppletId.Cabinet:
|
||||||
return new CabinetApplet(system);
|
return new CabinetApplet(system);
|
||||||
}
|
}
|
||||||
|
@ -576,6 +576,35 @@ namespace Ryujinx.HLE.HOS.Applets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsLaunchedAsReal(ulong pid)
|
||||||
|
{
|
||||||
|
RealApplet applet = null;
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (_applets.TryGetValue(pid, out applet))
|
||||||
|
{
|
||||||
|
if (_applets.Count > 1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (applet==_homeMenu||applet==_overlayDisp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasAnyApplets()
|
||||||
|
{
|
||||||
|
return _applets.Count > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ButtonPressTracker
|
internal class ButtonPressTracker
|
||||||
|
@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||||||
{
|
{
|
||||||
class KBufferDescriptorTable
|
class KBufferDescriptorTable
|
||||||
{
|
{
|
||||||
private const int MaxInternalBuffersCount = 8;
|
private const int MaxInternalBuffersCount = 256;
|
||||||
|
|
||||||
private readonly List<KBufferDescriptor> _sendBufferDescriptors;
|
private readonly List<KBufferDescriptor> _sendBufferDescriptors;
|
||||||
private readonly List<KBufferDescriptor> _receiveBufferDescriptors;
|
private readonly List<KBufferDescriptor> _receiveBufferDescriptors;
|
||||||
|
@ -88,8 +88,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
|
|||||||
// OpenLibraryAppletSelfAccessor() -> object<nn::am::service::ILibraryAppletSelfAccessor>
|
// OpenLibraryAppletSelfAccessor() -> object<nn::am::service::ILibraryAppletSelfAccessor>
|
||||||
public ResultCode OpenLibraryAppletSelfAccessor(ServiceCtx context)
|
public ResultCode OpenLibraryAppletSelfAccessor(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new ILibraryAppletSelfAccessor(context));
|
if (context.Device.System.WindowSystem.IsLaunchedAsReal(_pid))
|
||||||
|
{
|
||||||
|
MakeObject(context, new ILibraryRealAppletSelfAccessor(context, _pid));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MakeObject(context, new ILibraryAppletSelfAccessor(context));
|
||||||
|
}
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,323 @@
|
|||||||
|
using LibHac.Ncm;
|
||||||
|
using LibHac.Tools.FsSystem.NcaUtils;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE.HOS.Applets;
|
||||||
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
using Ryujinx.Horizon.Sdk.Applet;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator
|
||||||
|
{
|
||||||
|
class ILibraryRealAppletAccessor : DisposableIpcService
|
||||||
|
{
|
||||||
|
private readonly KernelContext _kernelContext;
|
||||||
|
private readonly ulong _callerPid;
|
||||||
|
|
||||||
|
private readonly RealAppletId _appletId;
|
||||||
|
private RealApplet _applet;
|
||||||
|
|
||||||
|
private readonly AppletChannel _inChannel;
|
||||||
|
private readonly AppletChannel _outChannel;
|
||||||
|
private readonly AppletChannel _interactiveInChannel;
|
||||||
|
private readonly AppletChannel _interactiveOutChannel;
|
||||||
|
private readonly AppletChannel _contextChannel;
|
||||||
|
|
||||||
|
private readonly KEvent _stateChangedEvent;
|
||||||
|
private readonly KEvent _normalOutDataEvent;
|
||||||
|
private readonly KEvent _interactiveOutDataEvent;
|
||||||
|
|
||||||
|
private int _stateChangedEventHandle;
|
||||||
|
private int _normalOutDataEventHandle;
|
||||||
|
private int _interactiveOutDataEventHandle;
|
||||||
|
|
||||||
|
private int _indirectLayerHandle;
|
||||||
|
|
||||||
|
private ResultCode StartAppletProcess(Horizon system)
|
||||||
|
{
|
||||||
|
// TODO: use ns
|
||||||
|
var programId = RealApplet.GetProgramIdFromAppletId(_appletId);
|
||||||
|
|
||||||
|
string contentPath = system.ContentManager.GetInstalledContentPath(programId, StorageId.BuiltInSystem, NcaContentType.Program);
|
||||||
|
|
||||||
|
if (contentPath.Length == 0)
|
||||||
|
{
|
||||||
|
return ResultCode.AppletLaunchFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentPath.StartsWith("@SystemContent"))
|
||||||
|
{
|
||||||
|
contentPath = FileSystem.VirtualFileSystem.SwitchPathToSystemPath(contentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!system.Device.Processes.LoadNca(contentPath, out var Process))
|
||||||
|
{
|
||||||
|
return ResultCode.AppletLaunchFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
_applet = system.WindowSystem.TrackProcess(Process.ProcessId, _callerPid, false);
|
||||||
|
_applet.AppletStateChanged += OnAppletStateChanged;
|
||||||
|
|
||||||
|
_applet.AppletState.LaunchableEvent.ReadableEvent.Signal();
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ILibraryRealAppletAccessor(RealAppletId appletId, Horizon system, ulong callerPid)
|
||||||
|
{
|
||||||
|
_kernelContext = system.KernelContext;
|
||||||
|
|
||||||
|
_stateChangedEvent = new KEvent(system.KernelContext);
|
||||||
|
_normalOutDataEvent = new KEvent(system.KernelContext);
|
||||||
|
_interactiveOutDataEvent = new KEvent(system.KernelContext);
|
||||||
|
|
||||||
|
_callerPid = callerPid;
|
||||||
|
_appletId = appletId;
|
||||||
|
|
||||||
|
_inChannel = new AppletChannel();
|
||||||
|
_outChannel = new AppletChannel();
|
||||||
|
_interactiveInChannel = new AppletChannel();
|
||||||
|
_interactiveOutChannel = new AppletChannel();
|
||||||
|
_contextChannel = new AppletChannel();
|
||||||
|
|
||||||
|
_outChannel.DataAvailable += OnNormalOutData;
|
||||||
|
_interactiveOutChannel.DataAvailable += OnInteractiveOutData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAppletStateChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_stateChangedEvent.WritableEvent.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNormalOutData(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_normalOutDataEvent.WritableEvent.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInteractiveOutData(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_interactiveOutDataEvent.WritableEvent.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(0)]
|
||||||
|
// GetAppletStateChangedEvent() -> handle<copy>
|
||||||
|
public ResultCode GetAppletStateChangedEvent(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_stateChangedEventHandle == 0)
|
||||||
|
{
|
||||||
|
if (context.Process.HandleTable.GenerateHandle(_stateChangedEvent.ReadableEvent, out _stateChangedEventHandle) != Result.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_stateChangedEventHandle);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(10)]
|
||||||
|
// Start()
|
||||||
|
public ResultCode Start(ServiceCtx context)
|
||||||
|
{
|
||||||
|
var result = StartAppletProcess(context.Device.System);
|
||||||
|
if (result != ResultCode.Success)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ResultCode)_applet.Start(_inChannel, _outChannel, _interactiveInChannel, _interactiveOutChannel, _contextChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(20)]
|
||||||
|
// RequestExit()
|
||||||
|
public ResultCode RequestExit(ServiceCtx context)
|
||||||
|
{
|
||||||
|
_applet.ProcessHandle.SetActivity(false);
|
||||||
|
_applet.AppletState.OnExitRequested();
|
||||||
|
_applet?.ProcessHandle.Terminate();
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(25)]
|
||||||
|
// Terminate()
|
||||||
|
public ResultCode Terminate(ServiceCtx context)
|
||||||
|
{
|
||||||
|
_applet.ProcessHandle.SetActivity(false);
|
||||||
|
_applet.AppletState.OnExitRequested();
|
||||||
|
_applet?.ProcessHandle.Terminate();
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm);
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(30)]
|
||||||
|
// GetResult()
|
||||||
|
public ResultCode GetResult(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_applet == null)
|
||||||
|
{
|
||||||
|
return ResultCode.LibraryAppletTerminated;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ResultCode)_applet.GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(60)]
|
||||||
|
// PresetLibraryAppletGpuTimeSliceZero()
|
||||||
|
public ResultCode PresetLibraryAppletGpuTimeSliceZero(ServiceCtx context)
|
||||||
|
{
|
||||||
|
// NOTE: This call reset two internal fields to 0 and one internal field to "true".
|
||||||
|
// It seems to be used only with software keyboard inline.
|
||||||
|
// Since we doesn't support applets for now, it's fine to stub it.
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(100)]
|
||||||
|
// PushInData(object<nn::am::service::IStorage>)
|
||||||
|
public ResultCode PushInData(ServiceCtx context)
|
||||||
|
{
|
||||||
|
IStorage data = GetObject<IStorage>(context, 0);
|
||||||
|
|
||||||
|
_inChannel.PushData(data.Data);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(101)]
|
||||||
|
// PopOutData() -> object<nn::am::service::IStorage>
|
||||||
|
public ResultCode PopOutData(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_outChannel.TryPopData(out byte[] data))
|
||||||
|
{
|
||||||
|
MakeObject(context, new IStorage(data));
|
||||||
|
|
||||||
|
_normalOutDataEvent.WritableEvent.Clear();
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultCode.NotAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(103)]
|
||||||
|
// PushInteractiveInData(object<nn::am::service::IStorage>)
|
||||||
|
public ResultCode PushInteractiveInData(ServiceCtx context)
|
||||||
|
{
|
||||||
|
IStorage data = GetObject<IStorage>(context, 0);
|
||||||
|
|
||||||
|
_interactiveInChannel.PushData(data.Data);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(104)]
|
||||||
|
// PopInteractiveOutData() -> object<nn::am::service::IStorage>
|
||||||
|
public ResultCode PopInteractiveOutData(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_interactiveOutChannel.TryPopData(out byte[] data))
|
||||||
|
{
|
||||||
|
MakeObject(context, new IStorage(data));
|
||||||
|
|
||||||
|
_interactiveOutDataEvent.WritableEvent.Clear();
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultCode.NotAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(105)]
|
||||||
|
// GetPopOutDataEvent() -> handle<copy>
|
||||||
|
public ResultCode GetPopOutDataEvent(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_normalOutDataEventHandle == 0)
|
||||||
|
{
|
||||||
|
if (context.Process.HandleTable.GenerateHandle(_normalOutDataEvent.ReadableEvent, out _normalOutDataEventHandle) != Result.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_normalOutDataEventHandle);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(106)]
|
||||||
|
// GetPopInteractiveOutDataEvent() -> handle<copy>
|
||||||
|
public ResultCode GetPopInteractiveOutDataEvent(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_interactiveOutDataEventHandle == 0)
|
||||||
|
{
|
||||||
|
if (context.Process.HandleTable.GenerateHandle(_interactiveOutDataEvent.ReadableEvent, out _interactiveOutDataEventHandle) != Result.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_interactiveOutDataEventHandle);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(110)]
|
||||||
|
// NeedsToExitProcess()
|
||||||
|
public ResultCode NeedsToExitProcess(ServiceCtx context)
|
||||||
|
{
|
||||||
|
return ResultCode.Stubbed;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(150)]
|
||||||
|
// RequestForAppletToGetForeground()
|
||||||
|
public ResultCode RequestForAppletToGetForeground(ServiceCtx context)
|
||||||
|
{
|
||||||
|
return ResultCode.Stubbed;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(160)] // 2.0.0+
|
||||||
|
// GetIndirectLayerConsumerHandle() -> u64 indirect_layer_consumer_handle
|
||||||
|
public ResultCode GetIndirectLayerConsumerHandle(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_applet == null)
|
||||||
|
{
|
||||||
|
return ResultCode.LibraryAppletTerminated;
|
||||||
|
}
|
||||||
|
|
||||||
|
_indirectLayerHandle = _applet.AppletState.IndirectLayerHandles.Add(_applet);
|
||||||
|
|
||||||
|
context.ResponseData.Write((ulong)_indirectLayerHandle);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
if (isDisposing)
|
||||||
|
{
|
||||||
|
if (_stateChangedEventHandle != 0)
|
||||||
|
{
|
||||||
|
_kernelContext.Syscall.CloseHandle(_stateChangedEventHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_normalOutDataEventHandle != 0)
|
||||||
|
{
|
||||||
|
_kernelContext.Syscall.CloseHandle(_normalOutDataEventHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_interactiveOutDataEventHandle != 0)
|
||||||
|
{
|
||||||
|
_kernelContext.Syscall.CloseHandle(_interactiveOutDataEventHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
_applet?.AppletState.IndirectLayerHandles.Delete(_indirectLayerHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,274 @@
|
|||||||
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE.HOS.Applets;
|
||||||
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
using Ryujinx.Horizon.Sdk.Applet;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy
|
||||||
|
{
|
||||||
|
class ILibraryRealAppletSelfAccessor : DisposableIpcService
|
||||||
|
{
|
||||||
|
private readonly KernelContext _kernelContext;
|
||||||
|
private readonly RealApplet _applet;
|
||||||
|
|
||||||
|
private readonly KEvent _normalInDataEvent;
|
||||||
|
private readonly KEvent _interactiveInDataEvent;
|
||||||
|
private int _normalInDataEventHandle;
|
||||||
|
private int _interactiveInDataEventHandle;
|
||||||
|
|
||||||
|
public ILibraryRealAppletSelfAccessor(ServiceCtx context, ulong pid)
|
||||||
|
{
|
||||||
|
var system = context.Device.System;
|
||||||
|
|
||||||
|
_kernelContext = system.KernelContext;
|
||||||
|
_applet = system.WindowSystem.GetByAruId(pid);
|
||||||
|
_normalInDataEvent = new KEvent(system.KernelContext);
|
||||||
|
_interactiveInDataEvent = new KEvent(system.KernelContext);
|
||||||
|
|
||||||
|
_applet.InChannel.DataAvailable += OnNormalInData;
|
||||||
|
_applet.InteractiveInChannel.DataAvailable += OnInteractiveInData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNormalInData(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_normalInDataEvent.WritableEvent.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInteractiveInData(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_interactiveInDataEvent.WritableEvent.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(0)]
|
||||||
|
// PopInData() -> object<nn::am::service::IStorage>
|
||||||
|
public ResultCode PopInData(ServiceCtx context)
|
||||||
|
{
|
||||||
|
byte[] appletData;
|
||||||
|
|
||||||
|
if (!_applet.InChannel.TryPopData(out appletData))
|
||||||
|
{
|
||||||
|
return ResultCode.NotAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appletData.Length == 0)
|
||||||
|
{
|
||||||
|
return ResultCode.NotAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
MakeObject(context, new IStorage(appletData));
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(1)]
|
||||||
|
public ResultCode PushOutData(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_applet != null)
|
||||||
|
{
|
||||||
|
IStorage data = GetObject<IStorage>(context, 0);
|
||||||
|
_applet.OutChannel.PushData(data.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(2)]
|
||||||
|
public ResultCode PopInteractiveInData(ServiceCtx context)
|
||||||
|
{
|
||||||
|
byte[] appletData;
|
||||||
|
|
||||||
|
if (!_applet.InteractiveInChannel.TryPopData(out appletData))
|
||||||
|
{
|
||||||
|
return ResultCode.NotAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appletData.Length == 0)
|
||||||
|
{
|
||||||
|
return ResultCode.NotAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
MakeObject(context, new IStorage(appletData));
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(3)]
|
||||||
|
public ResultCode PushInteractiveOutData(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_applet != null)
|
||||||
|
{
|
||||||
|
IStorage data = GetObject<IStorage>(context, 0);
|
||||||
|
_applet.InteractiveOutChannel.PushData(data.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(5)]
|
||||||
|
public ResultCode GetPopInDataEvent(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_normalInDataEventHandle == 0)
|
||||||
|
{
|
||||||
|
if (context.Process.HandleTable.GenerateHandle(_normalInDataEvent.ReadableEvent, out _normalInDataEventHandle) != Result.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_normalInDataEventHandle);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(6)]
|
||||||
|
public ResultCode GetPopInteractiveInDataEvent(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_interactiveInDataEventHandle == 0)
|
||||||
|
{
|
||||||
|
if (context.Process.HandleTable.GenerateHandle(_interactiveInDataEvent.ReadableEvent, out _interactiveInDataEventHandle) != Result.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_interactiveInDataEventHandle);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[CommandCmif(10)]
|
||||||
|
public ResultCode ExitProcessAndReturn(ServiceCtx context)
|
||||||
|
{
|
||||||
|
_applet.ProcessHandle.Terminate();
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(11)]
|
||||||
|
// GetLibraryAppletInfo() -> nn::am::service::LibraryAppletInfo
|
||||||
|
public ResultCode GetLibraryAppletInfo(ServiceCtx context)
|
||||||
|
{
|
||||||
|
LibraryAppletInfo libraryAppletInfo = new();
|
||||||
|
|
||||||
|
libraryAppletInfo.AppletId = (AppletId)_applet.AppletId;
|
||||||
|
libraryAppletInfo.LibraryAppletMode = _applet.LibraryAppletMode;
|
||||||
|
|
||||||
|
context.ResponseData.WriteStruct(libraryAppletInfo);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(12)]
|
||||||
|
// GetMainAppletIdentityInfo() -> nn::am::service::AppletIdentityInfo
|
||||||
|
public ResultCode GetMainAppletIdentityInfo(ServiceCtx context)
|
||||||
|
{
|
||||||
|
AppletIdentifyInfo appletIdentifyInfo = new()
|
||||||
|
{
|
||||||
|
AppletId = AppletId.QLaunch,
|
||||||
|
TitleId = 0x0100000000001000,
|
||||||
|
};
|
||||||
|
|
||||||
|
context.ResponseData.WriteStruct(appletIdentifyInfo);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(13)]
|
||||||
|
// CanUseApplicationCore() -> bool
|
||||||
|
public ResultCode CanUseApplicationCore(ServiceCtx context)
|
||||||
|
{
|
||||||
|
context.ResponseData.Write(false);
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(14)]
|
||||||
|
// GetCallerAppletIdentityInfo() -> nn::am::service::AppletIdentityInfo
|
||||||
|
public ResultCode GetCallerAppletIdentityInfo(ServiceCtx context)
|
||||||
|
{
|
||||||
|
context.ResponseData.WriteStruct(GetCallerIdentity(_applet));
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(30)]
|
||||||
|
// UnpopInData(nn::am::service::IStorage)
|
||||||
|
public ResultCode UnpopInData(ServiceCtx context)
|
||||||
|
{
|
||||||
|
IStorage data = GetObject<IStorage>(context, 0);
|
||||||
|
|
||||||
|
_applet.InChannel.InsertFrontData(data.Data);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(50)]
|
||||||
|
// ReportVisibleError(nn::err::ErrorCode)
|
||||||
|
public ResultCode ReportVisibleError(ServiceCtx context)
|
||||||
|
{
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm);
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(150)]
|
||||||
|
// ShouldSetGpuTimeSliceManually() -> bool
|
||||||
|
public ResultCode ShouldSetGpuTimeSliceManually(ServiceCtx context)
|
||||||
|
{
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm);
|
||||||
|
context.ResponseData.Write(false);
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandCmif(160)]
|
||||||
|
// GetLibraryAppletInfoEx() -> u64 usually 0
|
||||||
|
public ResultCode GetLibraryAppletInfoEx(ServiceCtx context)
|
||||||
|
{
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm);
|
||||||
|
context.ResponseData.Write((ulong)0);
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AppletIdentifyInfo GetCallerIdentity(RealApplet applet)
|
||||||
|
{
|
||||||
|
if (applet.CallerApplet != null)
|
||||||
|
{
|
||||||
|
return new AppletIdentifyInfo
|
||||||
|
{
|
||||||
|
AppletId = (AppletId)applet.CallerApplet.AppletId,
|
||||||
|
TitleId = applet.CallerApplet.ProcessHandle.TitleId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new AppletIdentifyInfo
|
||||||
|
{
|
||||||
|
AppletId = AppletId.QLaunch,
|
||||||
|
TitleId = 0x0100000000001000
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
if (isDisposing)
|
||||||
|
{
|
||||||
|
if (_normalInDataEventHandle != 0)
|
||||||
|
{
|
||||||
|
_kernelContext.Syscall.CloseHandle(_normalInDataEventHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_interactiveInDataEventHandle != 0)
|
||||||
|
{
|
||||||
|
_kernelContext.Syscall.CloseHandle(_interactiveInDataEventHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -124,6 +124,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandCmif(7)]
|
||||||
[CommandCmif(24)]
|
[CommandCmif(24)]
|
||||||
[CommandCmif(26)]
|
[CommandCmif(26)]
|
||||||
|
|
||||||
|
@ -22,7 +22,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||||||
int libraryAppletMode = context.RequestData.ReadInt32();
|
int libraryAppletMode = context.RequestData.ReadInt32();
|
||||||
#pragma warning restore IDE0059
|
#pragma warning restore IDE0059
|
||||||
|
|
||||||
MakeObject(context, new ILibraryAppletAccessor(appletId, context.Device.System, _pid));
|
if (ShouldBeReal(context.Device.System,appletId))
|
||||||
|
{
|
||||||
|
RealAppletId realAppletId = (RealAppletId)appletId;
|
||||||
|
MakeObject(context, new ILibraryRealAppletAccessor(realAppletId, context.Device.System, _pid));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MakeObject(context, new ILibraryAppletAccessor(appletId, context.Device.System, _pid));
|
||||||
|
}
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
@ -95,5 +103,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ShouldBeReal(Horizon horizon, AppletId appletId)
|
||||||
|
{
|
||||||
|
return horizon.Device.Configuration.HostUIHandler.IsAppletReal((RealAppletId)appletId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Ryujinx.HLE.HOS.Applets;
|
using Ryujinx.HLE.HOS.Applets;
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
||||||
|
using Ryujinx.Horizon.Sdk.Applet;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.UI
|
namespace Ryujinx.HLE.UI
|
||||||
{
|
{
|
||||||
@ -71,5 +72,10 @@ namespace Ryujinx.HLE.UI
|
|||||||
/// Gets the UI theme and returns true if is dark mode.
|
/// Gets the UI theme and returns true if is dark mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsDarkMode();
|
bool IsDarkMode();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets weather or not the applet is real in the system
|
||||||
|
/// </summary>
|
||||||
|
bool IsAppletReal(RealAppletId appletId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5647,6 +5647,31 @@
|
|||||||
"zh_TW": "日誌"
|
"zh_TW": "日誌"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "SettingsTabRealApplets",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Real Applets",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "SettingsTabLoggingLogging",
|
"ID": "SettingsTabLoggingLogging",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
@ -150,6 +150,24 @@ namespace Ryujinx.Headless
|
|||||||
if (NeedsOverride(nameof(IgnoreControllerApplet)))
|
if (NeedsOverride(nameof(IgnoreControllerApplet)))
|
||||||
IgnoreControllerApplet = configurationState.System.IgnoreApplet;
|
IgnoreControllerApplet = configurationState.System.IgnoreApplet;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(MissingAppletsAsReal)))
|
||||||
|
MissingAppletsAsReal = configurationState.System.MissingAppletsAsReal;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(SoftwareKeyboardIsReal)))
|
||||||
|
SoftwareKeyboardIsReal = configurationState.System.SoftwareKeyboardIsReal;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(BrowserIsReal)))
|
||||||
|
BrowserIsReal = configurationState.System.BrowserIsReal;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(ControllerIsReal)))
|
||||||
|
ControllerIsReal = configurationState.System.ControllerIsReal;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(PlayerSelectIsReal)))
|
||||||
|
PlayerSelectIsReal = configurationState.System.PlayerSelectIsReal;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(CabinetIsReal)))
|
||||||
|
CabinetIsReal = configurationState.System.CabinetIsReal;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
|
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
|
||||||
@ -411,8 +429,26 @@ namespace Ryujinx.Headless
|
|||||||
public bool IgnoreMissingServices { get; set; }
|
public bool IgnoreMissingServices { get; set; }
|
||||||
|
|
||||||
[Option("ignore-controller-applet", Required = false, Default = false, HelpText = "Enable ignoring the controller applet when your game loses connection to your controller.")]
|
[Option("ignore-controller-applet", Required = false, Default = false, HelpText = "Enable ignoring the controller applet when your game loses connection to your controller.")]
|
||||||
public bool IgnoreControllerApplet { get; set; }
|
public bool IgnoreControllerApplet { get; set; }
|
||||||
|
|
||||||
|
[Option("missing-applets-as-real", Required = false, Default = false, HelpText = "Runs the missing applets as real applets.")]
|
||||||
|
public bool MissingAppletsAsReal { get; set; }
|
||||||
|
|
||||||
|
[Option("is-softwarekeyboard-real", Required = false, Default = false, HelpText = "Runs the software keyboard applets as real")]
|
||||||
|
public bool SoftwareKeyboardIsReal { get; set; }
|
||||||
|
|
||||||
|
[Option("is-browser-real", Required = false, Default = false, HelpText = "Runs the browser applets as real")]
|
||||||
|
public bool BrowserIsReal { get; set; }
|
||||||
|
|
||||||
|
[Option("is-controller-real", Required = false, Default = false, HelpText = "Runs the controller applets as real")]
|
||||||
|
public bool ControllerIsReal { get; set; }
|
||||||
|
|
||||||
|
[Option("is-playerselect-real", Required = false, Default = false, HelpText = "Runs the player select applets as real")]
|
||||||
|
public bool PlayerSelectIsReal { get; set; }
|
||||||
|
|
||||||
|
[Option("is-cabinet-real", Required = false, Default = false, HelpText = "Runs the cabinet applets as real")]
|
||||||
|
public bool CabinetIsReal { get; set; }
|
||||||
|
|
||||||
// Values
|
// Values
|
||||||
|
|
||||||
[Value(0, MetaName = "input", HelpText = "Input to load.", Required = true)]
|
[Value(0, MetaName = "input", HelpText = "Input to load.", Required = true)]
|
||||||
|
@ -13,6 +13,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
|
|||||||
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
||||||
using Ryujinx.HLE.Loaders.Processes;
|
using Ryujinx.HLE.Loaders.Processes;
|
||||||
using Ryujinx.HLE.UI;
|
using Ryujinx.HLE.UI;
|
||||||
|
using Ryujinx.Horizon.Sdk.Applet;
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
using Ryujinx.Input.SDL2;
|
using Ryujinx.Input.SDL2;
|
||||||
@ -568,5 +569,10 @@ namespace Ryujinx.Headless
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsAppletReal(RealAppletId appletId)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,5 +172,11 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Assets\Fonts\Mono\" />
|
<Folder Include="Assets\Fonts\Mono\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="UI\Views\Settings\SettingsRealApplets.axaml.cs">
|
||||||
|
<DependentUpon>SettingsRealApplets.axaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -15,6 +15,7 @@ using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
|
|||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
||||||
using Ryujinx.HLE.UI;
|
using Ryujinx.HLE.UI;
|
||||||
|
using Ryujinx.Horizon.Sdk.Applet;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -318,5 +319,36 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
{
|
{
|
||||||
return ConfigurationState.Instance.UI.BaseStyle.Value == "Dark";
|
return ConfigurationState.Instance.UI.BaseStyle.Value == "Dark";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsMissingAppletsAsReal()
|
||||||
|
{
|
||||||
|
return ConfigurationState.Instance.System.MissingAppletsAsReal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsAppletReal(RealAppletId appletId)
|
||||||
|
{
|
||||||
|
bool softwareKeyboardReal = ConfigurationState.Instance.System.SoftwareKeyboardIsReal;
|
||||||
|
bool browserReal = ConfigurationState.Instance.System.BrowserIsReal;
|
||||||
|
bool controllerReal = ConfigurationState.Instance.System.ControllerIsReal;
|
||||||
|
bool playerSelectReal = ConfigurationState.Instance.System.PlayerSelectIsReal;
|
||||||
|
bool cabinetReal = ConfigurationState.Instance.System.CabinetIsReal;
|
||||||
|
bool missingAppletsAsReal = ConfigurationState.Instance.System.MissingAppletsAsReal;
|
||||||
|
|
||||||
|
switch (appletId)
|
||||||
|
{
|
||||||
|
case RealAppletId.LibraryAppletSwkbd:
|
||||||
|
return softwareKeyboardReal;
|
||||||
|
case RealAppletId.LibraryAppletWeb:
|
||||||
|
return browserReal;
|
||||||
|
case RealAppletId.LibraryAppletController:
|
||||||
|
return controllerReal;
|
||||||
|
case RealAppletId.LibraryAppletPlayerSelect:
|
||||||
|
return playerSelectReal;
|
||||||
|
case RealAppletId.LibraryAppletCabinet:
|
||||||
|
return cabinetReal;
|
||||||
|
default:
|
||||||
|
return missingAppletsAsReal;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
src/Ryujinx/UI/Helpers/Converters/BoolToIndexConverter.cs
Normal file
27
src/Ryujinx/UI/Helpers/Converters/BoolToIndexConverter.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using Avalonia.Data.Converters;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Helpers
|
||||||
|
{
|
||||||
|
public class BoolToIndexConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is bool boolValue)
|
||||||
|
{
|
||||||
|
return boolValue ? 0 : 1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is int index)
|
||||||
|
{
|
||||||
|
return index == 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
src/Ryujinx/UI/ViewModels/SettingsRealAppsViewModel.cs
Normal file
21
src/Ryujinx/UI/ViewModels/SettingsRealAppsViewModel.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using Avalonia.Data.Converters;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using Gommon;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.ViewModels
|
||||||
|
{
|
||||||
|
public partial class SettingsRealAppsViewModel : BaseModel
|
||||||
|
{
|
||||||
|
private readonly SettingsViewModel _baseViewModel;
|
||||||
|
|
||||||
|
public SettingsRealAppsViewModel() {}
|
||||||
|
|
||||||
|
public SettingsRealAppsViewModel(SettingsViewModel settingsVm)
|
||||||
|
{
|
||||||
|
_baseViewModel = settingsVm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -190,6 +190,12 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
public bool EnableInternetAccess { get; set; }
|
public bool EnableInternetAccess { get; set; }
|
||||||
public bool EnableFsIntegrityChecks { get; set; }
|
public bool EnableFsIntegrityChecks { get; set; }
|
||||||
public bool IgnoreMissingServices { get; set; }
|
public bool IgnoreMissingServices { get; set; }
|
||||||
|
public bool MissingAppletsAsReal { get; set; }
|
||||||
|
public bool SoftwareKeyboardIsReal { get; set; }
|
||||||
|
public bool BrowserIsReal { get; set; }
|
||||||
|
public bool ControllerIsReal { get; set; }
|
||||||
|
public bool PlayerSelectIsReal { get; set; }
|
||||||
|
public bool CabinetIsReal { get; set; }
|
||||||
public MemoryConfiguration DramSize { get; set; }
|
public MemoryConfiguration DramSize { get; set; }
|
||||||
public bool EnableShaderCache { get; set; }
|
public bool EnableShaderCache { get; set; }
|
||||||
public bool EnableTextureRecompression { get; set; }
|
public bool EnableTextureRecompression { get; set; }
|
||||||
@ -518,6 +524,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
DramSize = config.System.DramSize;
|
DramSize = config.System.DramSize;
|
||||||
IgnoreMissingServices = config.System.IgnoreMissingServices;
|
IgnoreMissingServices = config.System.IgnoreMissingServices;
|
||||||
IgnoreApplet = config.System.IgnoreApplet;
|
IgnoreApplet = config.System.IgnoreApplet;
|
||||||
|
|
||||||
|
MissingAppletsAsReal = config.System.MissingAppletsAsReal;
|
||||||
|
SoftwareKeyboardIsReal = config.System.SoftwareKeyboardIsReal;
|
||||||
|
BrowserIsReal = config.System.BrowserIsReal;
|
||||||
|
ControllerIsReal = config.System.ControllerIsReal;
|
||||||
|
PlayerSelectIsReal = config.System.PlayerSelectIsReal;
|
||||||
|
CabinetIsReal = config.System.CabinetIsReal;
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
EnablePptc = config.System.EnablePtc;
|
EnablePptc = config.System.EnablePtc;
|
||||||
@ -622,6 +635,12 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
config.System.DramSize.Value = DramSize;
|
config.System.DramSize.Value = DramSize;
|
||||||
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
|
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
|
||||||
config.System.IgnoreApplet.Value = IgnoreApplet;
|
config.System.IgnoreApplet.Value = IgnoreApplet;
|
||||||
|
config.System.MissingAppletsAsReal.Value = MissingAppletsAsReal;
|
||||||
|
config.System.SoftwareKeyboardIsReal.Value = SoftwareKeyboardIsReal;
|
||||||
|
config.System.BrowserIsReal.Value = BrowserIsReal;
|
||||||
|
config.System.ControllerIsReal.Value = ControllerIsReal;
|
||||||
|
config.System.PlayerSelectIsReal.Value = PlayerSelectIsReal;
|
||||||
|
config.System.CabinetIsReal.Value = CabinetIsReal;
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
config.System.EnablePtc.Value = EnablePptc;
|
config.System.EnablePtc.Value = EnablePptc;
|
||||||
|
142
src/Ryujinx/UI/Views/Settings/SettingsRealApplets.axaml
Normal file
142
src/Ryujinx/UI/Views/Settings/SettingsRealApplets.axaml
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<UserControl
|
||||||
|
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsRealAppsView"
|
||||||
|
xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||||
|
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
x:DataType="viewModels:SettingsViewModel">
|
||||||
|
|
||||||
|
<!-- Resources -->
|
||||||
|
<UserControl.Resources>
|
||||||
|
<helpers:BoolToIndexConverter x:Key="BoolToIndexConverter" />
|
||||||
|
</UserControl.Resources>
|
||||||
|
|
||||||
|
<Design.DataContext>
|
||||||
|
<viewModels:SettingsViewModel />
|
||||||
|
</Design.DataContext>
|
||||||
|
|
||||||
|
<ScrollViewer HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
HorizontalScrollBarVisibility="Disabled"
|
||||||
|
VerticalScrollBarVisibility="Auto">
|
||||||
|
<Border Classes="settings">
|
||||||
|
<StackPanel Margin="10"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Orientation="Vertical"
|
||||||
|
Spacing="10">
|
||||||
|
<!-- Header -->
|
||||||
|
<TextBlock HorizontalAlignment="Center"
|
||||||
|
Classes="h1"
|
||||||
|
Text="Real Applets" />
|
||||||
|
<TextBlock Foreground="{DynamicResource SecondaryTextColor}"
|
||||||
|
TextDecorations="Underline"
|
||||||
|
Text="This is a collection of real applet options." />
|
||||||
|
|
||||||
|
<!-- Missing Applets Row -->
|
||||||
|
<Grid Margin="10,0,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<ComboBox Width="100"
|
||||||
|
SelectedIndex="{Binding MissingAppletsAsReal, Mode=TwoWay, Converter={StaticResource BoolToIndexConverter}}">
|
||||||
|
<ComboBoxItem Content="Real" />
|
||||||
|
<ComboBoxItem Content="Skip" />
|
||||||
|
</ComboBox>
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
Text="Missing Applets" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Software Keyboard Row -->
|
||||||
|
<Grid Margin="10,0,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<ComboBox Width="100"
|
||||||
|
SelectedIndex="{Binding SoftwareKeyboardIsReal, Mode=TwoWay, Converter={StaticResource BoolToIndexConverter}}">
|
||||||
|
<ComboBoxItem Content="Real" />
|
||||||
|
<ComboBoxItem Content="Software" />
|
||||||
|
</ComboBox>
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
Text="Software Keyboard" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Browser Row -->
|
||||||
|
<Grid Margin="10,0,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<ComboBox Width="100"
|
||||||
|
SelectedIndex="{Binding BrowserIsReal, Mode=TwoWay, Converter={StaticResource BoolToIndexConverter}}">
|
||||||
|
<ComboBoxItem Content="Real" />
|
||||||
|
<ComboBoxItem Content="Software" />
|
||||||
|
</ComboBox>
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
Text="Browser" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Controller Row -->
|
||||||
|
<Grid Margin="10,0,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<ComboBox Width="100"
|
||||||
|
SelectedIndex="{Binding ControllerIsReal, Mode=TwoWay, Converter={StaticResource BoolToIndexConverter}}">
|
||||||
|
<ComboBoxItem Content="Real" />
|
||||||
|
<ComboBoxItem Content="Software" />
|
||||||
|
</ComboBox>
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
Text="Controller" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Player Select Row -->
|
||||||
|
<Grid Margin="10,0,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<ComboBox Width="100"
|
||||||
|
SelectedIndex="{Binding PlayerSelectIsReal, Mode=TwoWay, Converter={StaticResource BoolToIndexConverter}}">
|
||||||
|
<ComboBoxItem Content="Real" />
|
||||||
|
<ComboBoxItem Content="Software" />
|
||||||
|
</ComboBox>
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
Text="Player Select" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Cabinet Row -->
|
||||||
|
<Grid Margin="10,0,0,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<ComboBox Width="100"
|
||||||
|
SelectedIndex="{Binding CabinetIsReal, Mode=TwoWay, Converter={StaticResource BoolToIndexConverter}}">
|
||||||
|
<ComboBoxItem Content="Real" />
|
||||||
|
<ComboBoxItem Content="Software" />
|
||||||
|
</ComboBox>
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
Text="Cabinet" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</ScrollViewer>
|
||||||
|
</UserControl>
|
15
src/Ryujinx/UI/Views/Settings/SettingsRealApplets.axaml.cs
Normal file
15
src/Ryujinx/UI/Views/Settings/SettingsRealApplets.axaml.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Data.Converters;
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Views.Settings
|
||||||
|
{
|
||||||
|
public partial class SettingsRealAppsView : UserControl
|
||||||
|
{
|
||||||
|
public SettingsRealAppsView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -38,6 +38,7 @@
|
|||||||
<settings:SettingsAudioView Name="AudioPage" />
|
<settings:SettingsAudioView Name="AudioPage" />
|
||||||
<settings:SettingsNetworkView Name="NetworkPage" />
|
<settings:SettingsNetworkView Name="NetworkPage" />
|
||||||
<settings:SettingsLoggingView Name="LoggingPage" />
|
<settings:SettingsLoggingView Name="LoggingPage" />
|
||||||
|
<settings:SettingsRealAppsView Name="RealAppletsPage" />
|
||||||
<settings:SettingsHacksView Name="HacksPage" />
|
<settings:SettingsHacksView Name="HacksPage" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<ui:NavigationView
|
<ui:NavigationView
|
||||||
@ -93,6 +94,10 @@
|
|||||||
Content="{ext:Locale SettingsTabLogging}"
|
Content="{ext:Locale SettingsTabLogging}"
|
||||||
Tag="LoggingPage"
|
Tag="LoggingPage"
|
||||||
IconSource="Document" />
|
IconSource="Document" />
|
||||||
|
<ui:NavigationViewItem
|
||||||
|
Content="{ext:Locale SettingsTabRealApplets}"
|
||||||
|
Tag="RealAppletsPage"
|
||||||
|
IconSource="Document" />
|
||||||
<ui:NavigationViewItem
|
<ui:NavigationViewItem
|
||||||
IsVisible="{Binding ShowDirtyHacks}"
|
IsVisible="{Binding ShowDirtyHacks}"
|
||||||
Content="Dirty Hacks"
|
Content="Dirty Hacks"
|
||||||
|
@ -4,6 +4,7 @@ using Avalonia.Input;
|
|||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using Ryujinx.Ava.UI.Views.Settings;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using System;
|
using System;
|
||||||
@ -94,6 +95,9 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
case nameof(LoggingPage):
|
case nameof(LoggingPage):
|
||||||
NavPanel.Content = LoggingPage;
|
NavPanel.Content = LoggingPage;
|
||||||
break;
|
break;
|
||||||
|
case nameof(RealAppletsPage):
|
||||||
|
NavPanel.Content = RealAppletsPage;
|
||||||
|
break;
|
||||||
case nameof(HacksPage):
|
case nameof(HacksPage):
|
||||||
HacksPage.DataContext = ViewModel;
|
HacksPage.DataContext = ViewModel;
|
||||||
NavPanel.Content = HacksPage;
|
NavPanel.Content = HacksPage;
|
||||||
|
@ -439,6 +439,36 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ulong[] DirtyHacks { get; set; }
|
public ulong[] DirtyHacks { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs missing applets as real ones
|
||||||
|
/// </summary>
|
||||||
|
public bool MissingAppletsAsReal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches the SoftwareKeyboard as a real applet
|
||||||
|
/// </summary>
|
||||||
|
public bool SoftwareKeyboardIsReal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches the Browser as a real applet
|
||||||
|
/// </summary>
|
||||||
|
public bool BrowserIsReal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches the Controller as a real applet
|
||||||
|
/// </summary>
|
||||||
|
public bool ControllerIsReal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches the PlayerSelect as a real applet
|
||||||
|
/// </summary>
|
||||||
|
public bool PlayerSelectIsReal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches the Cabinet as a real applet
|
||||||
|
/// </summary>
|
||||||
|
public bool CabinetIsReal { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads a configuration file from disk
|
/// Loads a configuration file from disk
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -100,6 +100,13 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
System.IgnoreApplet.Value = cff.IgnoreApplet;
|
System.IgnoreApplet.Value = cff.IgnoreApplet;
|
||||||
System.UseHypervisor.Value = cff.UseHypervisor;
|
System.UseHypervisor.Value = cff.UseHypervisor;
|
||||||
|
|
||||||
|
System.MissingAppletsAsReal.Value = cff.MissingAppletsAsReal;
|
||||||
|
System.SoftwareKeyboardIsReal.Value = cff.SoftwareKeyboardIsReal;
|
||||||
|
System.BrowserIsReal.Value = cff.BrowserIsReal;
|
||||||
|
System.ControllerIsReal.Value = cff.ControllerIsReal;
|
||||||
|
System.PlayerSelectIsReal.Value = cff.PlayerSelectIsReal;
|
||||||
|
System.CabinetIsReal.Value = cff.CabinetIsReal;
|
||||||
|
|
||||||
UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn;
|
UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn;
|
||||||
UI.GuiColumns.IconColumn.Value = cff.GuiColumns.IconColumn;
|
UI.GuiColumns.IconColumn.Value = cff.GuiColumns.IconColumn;
|
||||||
UI.GuiColumns.AppColumn.Value = cff.GuiColumns.AppColumn;
|
UI.GuiColumns.AppColumn.Value = cff.GuiColumns.AppColumn;
|
||||||
@ -416,6 +423,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
// This was accidentally enabled by default when it was PRed. That is not what we want,
|
// This was accidentally enabled by default when it was PRed. That is not what we want,
|
||||||
// so as a compromise users who want to use it will simply need to re-enable it once after updating.
|
// so as a compromise users who want to use it will simply need to re-enable it once after updating.
|
||||||
cff.IgnoreApplet = false;
|
cff.IgnoreApplet = false;
|
||||||
|
cff.MissingAppletsAsReal = false;
|
||||||
}),
|
}),
|
||||||
(60, static cff => cff.StartNoUI = false),
|
(60, static cff => cff.StartNoUI = false),
|
||||||
(61, static cff =>
|
(61, static cff =>
|
||||||
|
@ -383,6 +383,36 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> UseHypervisor { get; private set; }
|
public ReactiveObject<bool> UseHypervisor { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches missing applets as real apps
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> MissingAppletsAsReal { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches the SoftwareKeyboard as a real applet
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> SoftwareKeyboardIsReal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches the Browser as a real applet
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> BrowserIsReal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches the Controller as a real applet
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> ControllerIsReal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches the PlayerSelect as a real applet
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> PlayerSelectIsReal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Launches the Cabinet as a real applet
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> CabinetIsReal { get; set; }
|
||||||
|
|
||||||
public SystemSection()
|
public SystemSection()
|
||||||
{
|
{
|
||||||
Language = new ReactiveObject<Language>();
|
Language = new ReactiveObject<Language>();
|
||||||
@ -423,6 +453,19 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
AudioVolume.LogChangesToValue(nameof(AudioVolume));
|
AudioVolume.LogChangesToValue(nameof(AudioVolume));
|
||||||
UseHypervisor = new ReactiveObject<bool>();
|
UseHypervisor = new ReactiveObject<bool>();
|
||||||
UseHypervisor.LogChangesToValue(nameof(UseHypervisor));
|
UseHypervisor.LogChangesToValue(nameof(UseHypervisor));
|
||||||
|
|
||||||
|
MissingAppletsAsReal = new ReactiveObject<bool>();
|
||||||
|
MissingAppletsAsReal.LogChangesToValue(nameof(MissingAppletsAsReal));
|
||||||
|
SoftwareKeyboardIsReal = new ReactiveObject<bool>();
|
||||||
|
SoftwareKeyboardIsReal.LogChangesToValue(nameof(SoftwareKeyboardIsReal));
|
||||||
|
BrowserIsReal = new ReactiveObject<bool>();
|
||||||
|
BrowserIsReal.LogChangesToValue(nameof(BrowserIsReal));
|
||||||
|
ControllerIsReal = new ReactiveObject<bool>();
|
||||||
|
ControllerIsReal.LogChangesToValue(nameof(ControllerIsReal));
|
||||||
|
PlayerSelectIsReal = new ReactiveObject<bool>();
|
||||||
|
PlayerSelectIsReal.LogChangesToValue(nameof(PlayerSelectIsReal));
|
||||||
|
CabinetIsReal = new ReactiveObject<bool>();
|
||||||
|
CabinetIsReal.LogChangesToValue(nameof(CabinetIsReal));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +141,12 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
LdnServer = Multiplayer.LdnServer,
|
LdnServer = Multiplayer.LdnServer,
|
||||||
ShowDirtyHacks = Hacks.ShowDirtyHacks,
|
ShowDirtyHacks = Hacks.ShowDirtyHacks,
|
||||||
DirtyHacks = Hacks.EnabledHacks.Select(it => it.Pack()).ToArray(),
|
DirtyHacks = Hacks.EnabledHacks.Select(it => it.Pack()).ToArray(),
|
||||||
|
MissingAppletsAsReal = System.MissingAppletsAsReal,
|
||||||
|
SoftwareKeyboardIsReal = System.SoftwareKeyboardIsReal,
|
||||||
|
BrowserIsReal = System.BrowserIsReal,
|
||||||
|
ControllerIsReal = System.ControllerIsReal,
|
||||||
|
PlayerSelectIsReal = System.PlayerSelectIsReal,
|
||||||
|
CabinetIsReal = System.CabinetIsReal,
|
||||||
};
|
};
|
||||||
|
|
||||||
return configurationFile;
|
return configurationFile;
|
||||||
@ -199,6 +205,12 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
System.DramSize.Value = MemoryConfiguration.MemoryConfiguration4GiB;
|
System.DramSize.Value = MemoryConfiguration.MemoryConfiguration4GiB;
|
||||||
System.IgnoreMissingServices.Value = false;
|
System.IgnoreMissingServices.Value = false;
|
||||||
System.IgnoreApplet.Value = false;
|
System.IgnoreApplet.Value = false;
|
||||||
|
System.MissingAppletsAsReal.Value = false;
|
||||||
|
System.SoftwareKeyboardIsReal.Value = false;
|
||||||
|
System.BrowserIsReal.Value = false;
|
||||||
|
System.ControllerIsReal.Value = false;
|
||||||
|
System.PlayerSelectIsReal.Value = false;
|
||||||
|
System.CabinetIsReal.Value = false;
|
||||||
System.UseHypervisor.Value = true;
|
System.UseHypervisor.Value = true;
|
||||||
Multiplayer.LanInterfaceId.Value = "0";
|
Multiplayer.LanInterfaceId.Value = "0";
|
||||||
Multiplayer.Mode.Value = MultiplayerMode.Disabled;
|
Multiplayer.Mode.Value = MultiplayerMode.Disabled;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user