Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
223172ac0b | |||
8c9633d72f | |||
1f93fd52d9 | |||
aac7bbd378 | |||
bed516bfda | |||
69b05f9918 | |||
fb7c80e928 | |||
bb2f9df0a1 |
@ -43,6 +43,12 @@ namespace ARMeilleure.State
|
||||
public long TpidrEl0 { get; set; }
|
||||
public long Tpidr { get; set; }
|
||||
|
||||
public uint Pstate
|
||||
{
|
||||
get => _nativeContext.GetPstate();
|
||||
set => _nativeContext.SetPstate(value);
|
||||
}
|
||||
|
||||
public FPCR Fpcr { get; set; }
|
||||
public FPSR Fpsr { get; set; }
|
||||
public FPCR StandardFpcrValue => (Fpcr & (FPCR.Ahp)) | FPCR.Dn | FPCR.Fz;
|
||||
|
@ -95,6 +95,25 @@ namespace ARMeilleure.State
|
||||
GetStorage().Flags[(int)flag] = value ? 1u : 0u;
|
||||
}
|
||||
|
||||
public unsafe uint GetPstate()
|
||||
{
|
||||
uint value = 0;
|
||||
for (int flag = 0; flag < RegisterConsts.FlagsCount; flag++)
|
||||
{
|
||||
value |= GetStorage().Flags[flag] != 0 ? 1u << flag : 0u;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public unsafe void SetPstate(uint value)
|
||||
{
|
||||
for (int flag = 0; flag < RegisterConsts.FlagsCount; flag++)
|
||||
{
|
||||
uint bit = 1u << flag;
|
||||
GetStorage().Flags[flag] = (value & bit) == bit ? 1u : 0u;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe bool GetFPStateFlag(FPState flag)
|
||||
{
|
||||
if ((uint)flag >= RegisterConsts.FpFlagsCount)
|
||||
|
@ -5,6 +5,7 @@
|
||||
public Stick Joystick { get; set; }
|
||||
public bool InvertStickX { get; set; }
|
||||
public bool InvertStickY { get; set; }
|
||||
public bool Rotate90CW { get; set; }
|
||||
public Button StickButton { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -328,6 +328,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
public void SetAllInputUserAttributes()
|
||||
{
|
||||
UsedInputAttributes |= Constants.AllAttributesMask;
|
||||
ThisInputAttributesComponents |= ~UInt128.Zero >> (128 - Constants.MaxAttributes * 4);
|
||||
}
|
||||
|
||||
public void SetAllOutputUserAttributes()
|
||||
|
@ -218,10 +218,17 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
while (usedAttributes != UInt128.Zero)
|
||||
{
|
||||
int index = usedAttributes.TrailingZeroCount();
|
||||
|
||||
InitializeOutputComponent(context, AttributeConsts.UserAttributeBase + index * 4, perPatch: false);
|
||||
int vecIndex = index / 4;
|
||||
|
||||
usedAttributes &= ~UInt128.Pow2(index);
|
||||
|
||||
// We don't need to initialize passthrough attributes.
|
||||
if ((context.Config.PassthroughAttributes & (1 << vecIndex)) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
InitializeOutputComponent(context, AttributeConsts.UserAttributeBase + index * 4, perPatch: false);
|
||||
}
|
||||
|
||||
UInt128 usedAttributesPerPatch = context.Config.NextInputAttributesPerPatchComponents;
|
||||
|
@ -10,6 +10,12 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
private ulong _v0;
|
||||
private ulong _v1;
|
||||
|
||||
public UInt128(ulong low, ulong high)
|
||||
{
|
||||
_v0 = low;
|
||||
_v1 = high;
|
||||
}
|
||||
|
||||
public int TrailingZeroCount()
|
||||
{
|
||||
int count = BitOperations.TrailingZeroCount(_v0);
|
||||
@ -25,25 +31,57 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
if (x >= 64)
|
||||
{
|
||||
return new UInt128() { _v0 = 0, _v1 = 1UL << (x - 64 ) };
|
||||
return new UInt128(0, 1UL << (x - 64));
|
||||
}
|
||||
|
||||
return new UInt128() { _v0 = 1UL << x, _v1 = 0 };
|
||||
return new UInt128(1UL << x, 0);
|
||||
}
|
||||
|
||||
public static UInt128 operator ~(UInt128 x)
|
||||
{
|
||||
return new UInt128() { _v0 = ~x._v0, _v1 = ~x._v1 };
|
||||
return new UInt128(~x._v0, ~x._v1);
|
||||
}
|
||||
|
||||
public static UInt128 operator &(UInt128 x, UInt128 y)
|
||||
{
|
||||
return new UInt128() { _v0 = x._v0 & y._v0, _v1 = x._v1 & y._v1 };
|
||||
return new UInt128(x._v0 & y._v0, x._v1 & y._v1);
|
||||
}
|
||||
|
||||
public static UInt128 operator |(UInt128 x, UInt128 y)
|
||||
{
|
||||
return new UInt128() { _v0 = x._v0 | y._v0, _v1 = x._v1 | y._v1 };
|
||||
return new UInt128(x._v0 | y._v0, x._v1 | y._v1);
|
||||
}
|
||||
|
||||
public static UInt128 operator <<(UInt128 x, int shift)
|
||||
{
|
||||
if (shift == 0)
|
||||
{
|
||||
return new UInt128(x._v0, x._v1);
|
||||
}
|
||||
else if (shift >= 64)
|
||||
{
|
||||
return new UInt128(0, x._v0 << (shift - 64));
|
||||
}
|
||||
|
||||
ulong shiftOut = x._v0 >> (64 - shift);
|
||||
|
||||
return new UInt128(x._v0 << shift, (x._v1 << shift) | shiftOut);
|
||||
}
|
||||
|
||||
public static UInt128 operator >>(UInt128 x, int shift)
|
||||
{
|
||||
if (shift == 0)
|
||||
{
|
||||
return new UInt128(x._v0, x._v1);
|
||||
}
|
||||
else if (shift >= 64)
|
||||
{
|
||||
return new UInt128(x._v1 >> (shift - 64), 0);
|
||||
}
|
||||
|
||||
ulong shiftOut = x._v1 & ((1UL << shift) - 1);
|
||||
|
||||
return new UInt128((x._v0 >> shift) | (shiftOut << (64 - shift)), x._v1 >> shift);
|
||||
}
|
||||
|
||||
public static bool operator ==(UInt128 x, UInt128 y)
|
||||
|
@ -751,7 +751,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||
{
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
if (currentThread.Owner != null &&
|
||||
if (currentThread.Context.Running &&
|
||||
currentThread.Owner != null &&
|
||||
currentThread.GetUserDisableCount() != 0 &&
|
||||
currentThread.Owner.PinnedThreads[currentThread.CurrentCore] == null)
|
||||
{
|
||||
|
@ -658,10 +658,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||
|
||||
private static uint GetPsr(ARMeilleure.State.ExecutionContext context)
|
||||
{
|
||||
return (context.GetPstateFlag(ARMeilleure.State.PState.NFlag) ? (1U << (int)ARMeilleure.State.PState.NFlag) : 0U) |
|
||||
(context.GetPstateFlag(ARMeilleure.State.PState.ZFlag) ? (1U << (int)ARMeilleure.State.PState.ZFlag) : 0U) |
|
||||
(context.GetPstateFlag(ARMeilleure.State.PState.CFlag) ? (1U << (int)ARMeilleure.State.PState.CFlag) : 0U) |
|
||||
(context.GetPstateFlag(ARMeilleure.State.PState.VFlag) ? (1U << (int)ARMeilleure.State.PState.VFlag) : 0U);
|
||||
return context.Pstate & 0xFF0FFE20;
|
||||
}
|
||||
|
||||
private ThreadContext GetCurrentContext()
|
||||
@ -1371,7 +1368,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||
|
||||
PreferredCore = _originalPreferredCore;
|
||||
AffinityMask = _originalAffinityMask;
|
||||
|
||||
|
||||
if (AffinityMask != affinityMask)
|
||||
{
|
||||
if ((AffinityMask & 1UL << ActiveCore) != 0)
|
||||
|
@ -1,13 +1,15 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Olsc
|
||||
{
|
||||
[Service("olsc:u")] // 10.0.0+
|
||||
class IOlscServiceForApplication : IpcService
|
||||
{
|
||||
private bool _initialized;
|
||||
private bool _initialized;
|
||||
private Dictionary<UserId, bool> _saveDataBackupSettingDatabase;
|
||||
|
||||
public IOlscServiceForApplication(ServiceCtx context) { }
|
||||
|
||||
@ -16,7 +18,9 @@ namespace Ryujinx.HLE.HOS.Services.Olsc
|
||||
public ResultCode Initialize(ServiceCtx context)
|
||||
{
|
||||
// NOTE: Service call arp:r GetApplicationInstanceUnregistrationNotifier with the pid and initialize some internal struct.
|
||||
// Since we will not support online savedata backup. It's fine to stub it for now.
|
||||
// Since we will not support online savedata backup, it's fine to stub it for now.
|
||||
|
||||
_saveDataBackupSettingDatabase = new Dictionary<UserId, bool>();
|
||||
|
||||
_initialized = true;
|
||||
|
||||
@ -25,12 +29,11 @@ namespace Ryujinx.HLE.HOS.Services.Olsc
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(14)]
|
||||
// SetSaveDataBackupSettingEnabled(nn::account::Uid, bool)
|
||||
public ResultCode SetSaveDataBackupSettingEnabled(ServiceCtx context)
|
||||
[CommandHipc(13)]
|
||||
// GetSaveDataBackupSetting(nn::account::Uid) -> u8
|
||||
public ResultCode GetSaveDataBackupSetting(ServiceCtx context)
|
||||
{
|
||||
UserId userId = context.RequestData.ReadStruct<UserId>();
|
||||
ulong saveDataBackupSettingEnabled = context.RequestData.ReadUInt64();
|
||||
UserId userId = context.RequestData.ReadStruct<UserId>();
|
||||
|
||||
if (!_initialized)
|
||||
{
|
||||
@ -42,8 +45,42 @@ namespace Ryujinx.HLE.HOS.Services.Olsc
|
||||
return ResultCode.NullArgument;
|
||||
}
|
||||
|
||||
// NOTE: Service store the UserId and the boolean in an internal SaveDataBackupSettingDatabase object.
|
||||
// Since we will not support online savedata backup. It's fine to stub it for now.
|
||||
if (_saveDataBackupSettingDatabase[userId])
|
||||
{
|
||||
context.ResponseData.Write((byte)1); // TODO: Determine value.
|
||||
}
|
||||
else
|
||||
{
|
||||
context.ResponseData.Write((byte)2); // TODO: Determine value.
|
||||
}
|
||||
|
||||
// NOTE: Since we will not support online savedata backup, it's fine to stub it for now.
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceOlsc, new { userId });
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(14)]
|
||||
// SetSaveDataBackupSettingEnabled(nn::account::Uid, bool)
|
||||
public ResultCode SetSaveDataBackupSettingEnabled(ServiceCtx context)
|
||||
{
|
||||
bool saveDataBackupSettingEnabled = context.RequestData.ReadUInt64() != 0;
|
||||
UserId userId = context.RequestData.ReadStruct<UserId>();
|
||||
|
||||
if (!_initialized)
|
||||
{
|
||||
return ResultCode.NotInitialized;
|
||||
}
|
||||
|
||||
if (userId.IsNull)
|
||||
{
|
||||
return ResultCode.NullArgument;
|
||||
}
|
||||
|
||||
_saveDataBackupSettingDatabase[userId] = saveDataBackupSettingEnabled;
|
||||
|
||||
// NOTE: Since we will not support online savedata backup, it's fine to stub it for now.
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceOlsc, new { userId, saveDataBackupSettingEnabled });
|
||||
|
||||
|
@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
|
||||
|
||||
if (serviceType != ViServiceType.Application)
|
||||
{
|
||||
return ResultCode.InvalidRange;
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
MakeObject(context, new IApplicationDisplayService(serviceType));
|
||||
|
@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
|
||||
|
||||
if (serviceType != ViServiceType.Manager)
|
||||
{
|
||||
return ResultCode.InvalidRange;
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
MakeObject(context, new IApplicationDisplayService(serviceType));
|
||||
|
@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
|
||||
|
||||
if (serviceType != ViServiceType.System)
|
||||
{
|
||||
return ResultCode.InvalidRange;
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
MakeObject(context, new IApplicationDisplayService(serviceType));
|
||||
|
@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
|
||||
|
||||
InvalidArguments = (1 << ErrorCodeShift) | ModuleId,
|
||||
InvalidLayerSize = (4 << ErrorCodeShift) | ModuleId,
|
||||
InvalidRange = (5 << ErrorCodeShift) | ModuleId,
|
||||
PermissionDenied = (5 << ErrorCodeShift) | ModuleId,
|
||||
InvalidScalingMode = (6 << ErrorCodeShift) | ModuleId,
|
||||
InvalidValue = (7 << ErrorCodeShift) | ModuleId,
|
||||
AlreadyOpened = (9 << ErrorCodeShift) | ModuleId
|
||||
|
@ -1,7 +1,6 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.HLE.HOS.Applets;
|
||||
using Ryujinx.HLE.HOS.Ipc;
|
||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
@ -22,16 +21,21 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||
{
|
||||
private readonly ViServiceType _serviceType;
|
||||
|
||||
private readonly List<DisplayInfo> _displayInfo;
|
||||
private readonly Dictionary<ulong, DisplayInfo> _openDisplayInfo;
|
||||
private class DisplayState
|
||||
{
|
||||
public int RetrievedEventsCount;
|
||||
}
|
||||
|
||||
private readonly List<DisplayInfo> _displayInfo;
|
||||
private readonly Dictionary<ulong, DisplayState> _openDisplays;
|
||||
|
||||
private int _vsyncEventHandle;
|
||||
|
||||
public IApplicationDisplayService(ViServiceType serviceType)
|
||||
{
|
||||
_serviceType = serviceType;
|
||||
_displayInfo = new List<DisplayInfo>();
|
||||
_openDisplayInfo = new Dictionary<ulong, DisplayInfo>();
|
||||
_serviceType = serviceType;
|
||||
_displayInfo = new List<DisplayInfo>();
|
||||
_openDisplays = new Dictionary<ulong, DisplayState>();
|
||||
|
||||
void AddDisplayInfo(string name, bool layerLimitEnabled, ulong layerLimitMax, ulong width, ulong height)
|
||||
{
|
||||
@ -64,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||
// FIXME: Should be _serviceType != ViServiceType.Application but guests crashes if we do this check.
|
||||
if (_serviceType > ViServiceType.System)
|
||||
{
|
||||
return ResultCode.InvalidRange;
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
MakeObject(context, new HOSBinderDriverServer());
|
||||
@ -79,7 +83,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||
// FIXME: Should be _serviceType == ViServiceType.System but guests crashes if we do this check.
|
||||
if (_serviceType > ViServiceType.System)
|
||||
{
|
||||
return ResultCode.InvalidRange;
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
MakeObject(context, new ISystemDisplayService(this));
|
||||
@ -93,7 +97,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||
{
|
||||
if (_serviceType > ViServiceType.System)
|
||||
{
|
||||
return ResultCode.InvalidRange;
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
MakeObject(context, new IManagerDisplayService(this));
|
||||
@ -107,7 +111,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||
{
|
||||
if (_serviceType > ViServiceType.System)
|
||||
{
|
||||
return ResultCode.InvalidRange;
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
MakeObject(context, new HOSBinderDriverServer());
|
||||
@ -174,7 +178,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||
return ResultCode.InvalidValue;
|
||||
}
|
||||
|
||||
if (!_openDisplayInfo.TryAdd((ulong)displayId, _displayInfo[displayId]))
|
||||
if (!_openDisplays.TryAdd((ulong)displayId, new DisplayState()))
|
||||
{
|
||||
return ResultCode.AlreadyOpened;
|
||||
}
|
||||
@ -190,7 +194,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||
{
|
||||
ulong displayId = context.RequestData.ReadUInt64();
|
||||
|
||||
if (!_openDisplayInfo.Remove(displayId))
|
||||
if (!_openDisplays.Remove(displayId))
|
||||
{
|
||||
return ResultCode.InvalidValue;
|
||||
}
|
||||
@ -454,11 +458,16 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||
{
|
||||
ulong displayId = context.RequestData.ReadUInt64();
|
||||
|
||||
if (!_openDisplayInfo.ContainsKey(displayId))
|
||||
if (!_openDisplays.TryGetValue(displayId, out DisplayState displayState))
|
||||
{
|
||||
return ResultCode.InvalidValue;
|
||||
}
|
||||
|
||||
if (displayState.RetrievedEventsCount > 0)
|
||||
{
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
if (_vsyncEventHandle == 0)
|
||||
{
|
||||
if (context.Process.HandleTable.GenerateHandle(context.Device.System.VsyncEvent.ReadableEvent, out _vsyncEventHandle) != KernelResult.Success)
|
||||
@ -467,6 +476,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||
}
|
||||
}
|
||||
|
||||
displayState.RetrievedEventsCount++;
|
||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_vsyncEventHandle);
|
||||
|
||||
return ResultCode.Success;
|
||||
|
@ -220,6 +220,7 @@ namespace Ryujinx.Headless.SDL2
|
||||
StickButton = ConfigGamepadInputId.LeftStick,
|
||||
InvertStickX = false,
|
||||
InvertStickY = false,
|
||||
Rotate90CW = false,
|
||||
},
|
||||
|
||||
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
|
||||
@ -241,6 +242,7 @@ namespace Ryujinx.Headless.SDL2
|
||||
StickButton = ConfigGamepadInputId.RightStick,
|
||||
InvertStickX = false,
|
||||
InvertStickY = false,
|
||||
Rotate90CW = false,
|
||||
},
|
||||
|
||||
Motion = new StandardMotionConfigController
|
||||
|
@ -350,6 +350,14 @@ namespace Ryujinx.Input.SDL2
|
||||
{
|
||||
resultY = -resultY;
|
||||
}
|
||||
|
||||
if ((inputId == StickInputId.Left && _configuration.LeftJoyconStick.Rotate90CW) ||
|
||||
(inputId == StickInputId.Right && _configuration.RightJoyconStick.Rotate90CW))
|
||||
{
|
||||
float temp = resultX;
|
||||
resultX = resultY;
|
||||
resultY = -temp;
|
||||
}
|
||||
}
|
||||
|
||||
return (resultX, resultY);
|
||||
|
@ -283,10 +283,7 @@ namespace Ryujinx.Tests.Cpu
|
||||
}
|
||||
|
||||
uint finalCpsr = test.FinalRegs[15];
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
Assert.That(GetContext().GetPstateFlag((PState)i), Is.EqualTo((finalCpsr & (1u << i)) != 0));
|
||||
}
|
||||
Assert.That(GetContext().Pstate, Is.EqualTo(finalCpsr));
|
||||
}
|
||||
|
||||
protected void SetWorkingMemory(uint offset, byte[] data)
|
||||
|
@ -14,7 +14,7 @@ namespace Ryujinx.Configuration
|
||||
/// <summary>
|
||||
/// The current version of the file format
|
||||
/// </summary>
|
||||
public const int CurrentVersion = 36;
|
||||
public const int CurrentVersion = 37;
|
||||
|
||||
/// <summary>
|
||||
/// Version of the configuration file format
|
||||
@ -236,6 +236,11 @@ namespace Ryujinx.Configuration
|
||||
/// </summary>
|
||||
public bool StartFullscreen { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Show console window
|
||||
/// </summary>
|
||||
public bool ShowConsole { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enable or disable keyboard support (Independent from controllers binding)
|
||||
/// </summary>
|
||||
|
@ -6,6 +6,7 @@ using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Configuration.System;
|
||||
using Ryujinx.Configuration.Ui;
|
||||
using Ryujinx.Ui.Helper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@ -88,6 +89,11 @@ namespace Ryujinx.Configuration
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> StartFullscreen { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Hide / Show Console Window
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> ShowConsole { get; private set; }
|
||||
|
||||
public UiSection()
|
||||
{
|
||||
GuiColumns = new Columns();
|
||||
@ -96,6 +102,8 @@ namespace Ryujinx.Configuration
|
||||
EnableCustomTheme = new ReactiveObject<bool>();
|
||||
CustomThemePath = new ReactiveObject<string>();
|
||||
StartFullscreen = new ReactiveObject<bool>();
|
||||
ShowConsole = new ReactiveObject<bool>();
|
||||
ShowConsole.Event += static (s, e) => { ConsoleHelper.SetConsoleWindowState(e.NewValue); };
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,6 +516,7 @@ namespace Ryujinx.Configuration
|
||||
EnableCustomTheme = Ui.EnableCustomTheme,
|
||||
CustomThemePath = Ui.CustomThemePath,
|
||||
StartFullscreen = Ui.StartFullscreen,
|
||||
ShowConsole = Ui.ShowConsole,
|
||||
EnableKeyboard = Hid.EnableKeyboard,
|
||||
EnableMouse = Hid.EnableMouse,
|
||||
Hotkeys = Hid.Hotkeys,
|
||||
@ -574,6 +583,7 @@ namespace Ryujinx.Configuration
|
||||
Ui.EnableCustomTheme.Value = false;
|
||||
Ui.CustomThemePath.Value = "";
|
||||
Ui.StartFullscreen.Value = false;
|
||||
Ui.ShowConsole.Value = true;
|
||||
Hid.EnableKeyboard.Value = false;
|
||||
Hid.EnableMouse.Value = false;
|
||||
Hid.Hotkeys.Value = new KeyboardHotkeys
|
||||
@ -995,7 +1005,7 @@ namespace Ryujinx.Configuration
|
||||
controllerConfig.RangeRight = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
@ -1007,7 +1017,16 @@ namespace Ryujinx.Configuration
|
||||
|
||||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
|
||||
if (configurationFileFormat.Version < 37)
|
||||
{
|
||||
Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 37.");
|
||||
|
||||
configurationFileFormat.ShowConsole = true;
|
||||
|
||||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
|
||||
Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading;
|
||||
Graphics.ResScale.Value = configurationFileFormat.ResScale;
|
||||
@ -1061,6 +1080,7 @@ namespace Ryujinx.Configuration
|
||||
Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme;
|
||||
Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath;
|
||||
Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen;
|
||||
Ui.ShowConsole.Value = configurationFileFormat.ShowConsole;
|
||||
Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard;
|
||||
Hid.EnableMouse.Value = configurationFileFormat.EnableMouse;
|
||||
Hid.Hotkeys.Value = configurationFileFormat.Hotkeys;
|
||||
|
49
Ryujinx/Ui/Helper/ConsoleHelper.cs
Normal file
49
Ryujinx/Ui/Helper/ConsoleHelper.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace Ryujinx.Ui.Helper
|
||||
{
|
||||
public static class ConsoleHelper
|
||||
{
|
||||
public static bool SetConsoleWindowStateSupported => OperatingSystem.IsWindows();
|
||||
|
||||
public static void SetConsoleWindowState(bool show)
|
||||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
SetConsoleWindowStateWindows(show);
|
||||
}
|
||||
else if (show == false)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, "OS doesn't support hiding console window");
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static void SetConsoleWindowStateWindows(bool show)
|
||||
{
|
||||
const int SW_HIDE = 0;
|
||||
const int SW_SHOW = 5;
|
||||
|
||||
IntPtr hWnd = GetConsoleWindow();
|
||||
|
||||
if (hWnd == IntPtr.Zero)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, "Attempted to show/hide console window but console window does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[DllImport("kernel32")]
|
||||
static extern IntPtr GetConsoleWindow();
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[DllImport("user32")]
|
||||
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
}
|
||||
}
|
@ -107,6 +107,7 @@ namespace Ryujinx.Ui
|
||||
[GUI] MenuItem _hideUi;
|
||||
[GUI] MenuItem _fullScreen;
|
||||
[GUI] CheckMenuItem _startFullScreen;
|
||||
[GUI] CheckMenuItem _showConsole;
|
||||
[GUI] CheckMenuItem _favToggle;
|
||||
[GUI] MenuItem _firmwareInstallDirectory;
|
||||
[GUI] MenuItem _firmwareInstallFile;
|
||||
@ -213,6 +214,9 @@ namespace Ryujinx.Ui
|
||||
_startFullScreen.Active = true;
|
||||
}
|
||||
|
||||
_showConsole.Active = ConfigurationState.Instance.Ui.ShowConsole.Value;
|
||||
_showConsole.Visible = ConsoleHelper.SetConsoleWindowStateSupported;
|
||||
|
||||
_actionMenu.Sensitive = false;
|
||||
_pauseEmulation.Sensitive = false;
|
||||
_resumeEmulation.Sensitive = false;
|
||||
@ -1535,6 +1539,13 @@ namespace Ryujinx.Ui
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
private void ShowConsole_Toggled(object sender, EventArgs args)
|
||||
{
|
||||
ConfigurationState.Instance.Ui.ShowConsole.Value = _showConsole.Active;
|
||||
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
private void OptionMenu_StateChanged(object o, StateChangedArgs args)
|
||||
{
|
||||
_manageUserProfiles.Sensitive = _emulationContext == null;
|
||||
|
@ -142,6 +142,15 @@
|
||||
<signal name="toggled" handler="StartFullScreen_Toggled" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckMenuItem" id="_showConsole">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Show Log Console</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="toggled" handler="ShowConsole_Toggled" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem">
|
||||
<property name="visible">True</property>
|
||||
|
@ -73,6 +73,7 @@ namespace Ryujinx.Ui.Windows
|
||||
[GUI] ToggleButton _lStick;
|
||||
[GUI] CheckButton _invertLStickX;
|
||||
[GUI] CheckButton _invertLStickY;
|
||||
[GUI] CheckButton _rotateL90CW;
|
||||
[GUI] ToggleButton _lStickUp;
|
||||
[GUI] ToggleButton _lStickDown;
|
||||
[GUI] ToggleButton _lStickLeft;
|
||||
@ -88,6 +89,7 @@ namespace Ryujinx.Ui.Windows
|
||||
[GUI] ToggleButton _rStick;
|
||||
[GUI] CheckButton _invertRStickX;
|
||||
[GUI] CheckButton _invertRStickY;
|
||||
[GUI] CheckButton _rotateR90CW;
|
||||
[GUI] ToggleButton _rStickUp;
|
||||
[GUI] ToggleButton _rStickDown;
|
||||
[GUI] ToggleButton _rStickLeft;
|
||||
@ -490,6 +492,7 @@ namespace Ryujinx.Ui.Windows
|
||||
_lStick.Label = controllerConfig.LeftJoyconStick.Joystick.ToString();
|
||||
_invertLStickX.Active = controllerConfig.LeftJoyconStick.InvertStickX;
|
||||
_invertLStickY.Active = controllerConfig.LeftJoyconStick.InvertStickY;
|
||||
_rotateL90CW.Active = controllerConfig.LeftJoyconStick.Rotate90CW;
|
||||
_lStickButton.Label = controllerConfig.LeftJoyconStick.StickButton.ToString();
|
||||
_dpadUp.Label = controllerConfig.LeftJoycon.DpadUp.ToString();
|
||||
_dpadDown.Label = controllerConfig.LeftJoycon.DpadDown.ToString();
|
||||
@ -503,6 +506,7 @@ namespace Ryujinx.Ui.Windows
|
||||
_rStick.Label = controllerConfig.RightJoyconStick.Joystick.ToString();
|
||||
_invertRStickX.Active = controllerConfig.RightJoyconStick.InvertStickX;
|
||||
_invertRStickY.Active = controllerConfig.RightJoyconStick.InvertStickY;
|
||||
_rotateR90CW.Active = controllerConfig.RightJoyconStick.Rotate90CW;
|
||||
_rStickButton.Label = controllerConfig.RightJoyconStick.StickButton.ToString();
|
||||
_a.Label = controllerConfig.RightJoycon.ButtonA.ToString();
|
||||
_b.Label = controllerConfig.RightJoycon.ButtonB.ToString();
|
||||
@ -718,6 +722,7 @@ namespace Ryujinx.Ui.Windows
|
||||
Joystick = lStick,
|
||||
InvertStickY = _invertLStickY.Active,
|
||||
StickButton = lStickButton,
|
||||
Rotate90CW = _rotateL90CW.Active,
|
||||
},
|
||||
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
|
||||
{
|
||||
@ -737,6 +742,7 @@ namespace Ryujinx.Ui.Windows
|
||||
Joystick = rStick,
|
||||
InvertStickY = _invertRStickY.Active,
|
||||
StickButton = rStickButton,
|
||||
Rotate90CW = _rotateR90CW.Active,
|
||||
},
|
||||
Motion = motionConfig,
|
||||
Rumble = new RumbleConfigController
|
||||
@ -1056,6 +1062,7 @@ namespace Ryujinx.Ui.Windows
|
||||
StickButton = ConfigGamepadInputId.LeftStick,
|
||||
InvertStickX = false,
|
||||
InvertStickY = false,
|
||||
Rotate90CW = false,
|
||||
},
|
||||
|
||||
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
|
||||
@ -1077,6 +1084,7 @@ namespace Ryujinx.Ui.Windows
|
||||
StickButton = ConfigGamepadInputId.RightStick,
|
||||
InvertStickX = false,
|
||||
InvertStickY = false,
|
||||
Rotate90CW = false,
|
||||
},
|
||||
|
||||
Motion = new StandardMotionConfigController
|
||||
|
@ -740,6 +740,19 @@
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="_rotateL90CW">
|
||||
<property name="label" translatable="yes">Rotate 90° Clockwise</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
@ -1697,6 +1710,19 @@
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="_rotateR90CW">
|
||||
<property name="label" translatable="yes">Rotate 90° Clockwise</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
Reference in New Issue
Block a user