mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-06-06 12:29:15 +00:00
Compare commits
2 Commits
Canary-1.3
...
Canary-1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce340e5d0b | ||
|
|
d94b759e89 |
@@ -45,7 +45,7 @@
|
|||||||
<!--<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />-->
|
<!--<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />-->
|
||||||
<PackageVersion Include="Ryujinx.Audio.OpenAL" Version="1.25.1" />
|
<PackageVersion Include="Ryujinx.Audio.OpenAL" Version="1.25.1" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.4-build6" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.4-build6" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.MoltenVK" Version="1.4.2-ryujinx.3" />
|
||||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.133" />
|
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.133" />
|
||||||
<PackageVersion Include="Ryujinx.UpdateClient" Version="2.0.6" />
|
<PackageVersion Include="Ryujinx.UpdateClient" Version="2.0.6" />
|
||||||
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="2.0.6" />
|
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="2.0.6" />
|
||||||
@@ -53,9 +53,10 @@
|
|||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||||
<PackageVersion Include="Sep" Version="0.14.1" />
|
<PackageVersion Include="Sep" Version="0.14.1" />
|
||||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.22.0" />
|
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" />
|
<PackageVersion Include="Silk.NET.Vulkan" Version="2.23.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.23.0" />
|
||||||
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.23.0" />
|
||||||
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Win32" Version="2.88.9" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Win32" Version="2.88.9" />
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.macOS" Version="2.88.9" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.macOS" Version="2.88.9" />
|
||||||
|
|||||||
@@ -12250,6 +12250,56 @@
|
|||||||
"zh_TW": "弱震動調節:"
|
"zh_TW": "弱震動調節:"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "ControllerSettingsRumbleUseHDRumble",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Enable HD Rumble",
|
||||||
|
"es_ES": "Activa vibración HD",
|
||||||
|
"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": "HDRumbleTooltip",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Sends more data to the controller for better rumble.\n\nCurrently only supports first-party Nintendo Switch controllers.\n\nLeave ON if you're using JoyCons or a Pro Controller.",
|
||||||
|
"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": "DialogMessageSaveNotAvailableMessage",
|
"ID": "DialogMessageSaveNotAvailableMessage",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
|||||||
@@ -47,14 +47,12 @@ def get_new_name(
|
|||||||
input_component = str(input_dylib_path).replace(str(input_directory), "")[1:]
|
input_component = str(input_dylib_path).replace(str(input_directory), "")[1:]
|
||||||
return Path(os.path.join(output_directory, input_component))
|
return Path(os.path.join(output_directory, input_component))
|
||||||
|
|
||||||
|
def get_archs(dylib_path: Path) -> list[str]:
|
||||||
def is_fat_file(dylib_path: Path) -> str:
|
res = subprocess.check_output([LIPO, "-info", str(dylib_path)]).decode("utf-8")
|
||||||
res = subprocess.check_output([LIPO, "-info", str(dylib_path.absolute())]).decode(
|
if res.startswith("Non-fat file"):
|
||||||
"utf-8"
|
return [res.split(":")[-1].strip()]
|
||||||
)
|
else:
|
||||||
|
return res.split("are:")[-1].strip().split()
|
||||||
return not res.split("\n")[0].startswith("Non-fat file")
|
|
||||||
|
|
||||||
|
|
||||||
def construct_universal_dylib(
|
def construct_universal_dylib(
|
||||||
arm64_input_dylib_path: Path, x86_64_input_dylib_path: Path, output_dylib_path: Path
|
arm64_input_dylib_path: Path, x86_64_input_dylib_path: Path, output_dylib_path: Path
|
||||||
@@ -69,11 +67,12 @@ def construct_universal_dylib(
|
|||||||
os.path.basename(arm64_input_dylib_path.resolve()), output_dylib_path
|
os.path.basename(arm64_input_dylib_path.resolve()), output_dylib_path
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if is_fat_file(arm64_input_dylib_path) or not x86_64_input_dylib_path.exists():
|
arm64_archs = get_archs(arm64_input_dylib_path)
|
||||||
with open(output_dylib_path, "wb") as dst:
|
x86_64_archs = get_archs(x86_64_input_dylib_path) if x86_64_input_dylib_path.exists() else []
|
||||||
with open(arm64_input_dylib_path, "rb") as src:
|
|
||||||
dst.write(src.read())
|
if "arm64" in arm64_archs and "x86_64" in arm64_archs:
|
||||||
else:
|
shutil.copy2(arm64_input_dylib_path, output_dylib_path)
|
||||||
|
elif x86_64_archs:
|
||||||
subprocess.check_call(
|
subprocess.check_call(
|
||||||
[
|
[
|
||||||
LIPO,
|
LIPO,
|
||||||
|
|||||||
@@ -16,5 +16,10 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
|
|||||||
/// Enable Rumble
|
/// Enable Rumble
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableRumble { get; set; }
|
public bool EnableRumble { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable HD Rumble support
|
||||||
|
/// </summary
|
||||||
|
public bool UseHDRumble { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,10 +42,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ResourceDescriptor descriptor = rdc.Descriptors[descIndex];
|
ResourceDescriptor descriptor = rdc.Descriptors[descIndex];
|
||||||
ResourceStages stages = descriptor.Stages;
|
ResourceStages stages = descriptor.Stages;
|
||||||
|
|
||||||
if (descriptor.Type == ResourceType.StorageBuffer && isMoltenVk)
|
if (descriptor.Type == ResourceType.StorageBuffer && gd.IsMoltenVk)
|
||||||
{
|
{
|
||||||
// There's a bug on MoltenVK where using the same buffer across different stages
|
// There's a bug in MoltenVK where using the same buffer across different stages
|
||||||
// causes invalid resource errors, allow the binding on all active stages as workaround.
|
// causes invalid resource errors, allow the binding on all active stages as workaround.
|
||||||
|
// https://github.com/KhronosGroup/MoltenVK/issues/1870
|
||||||
stages = activeStages;
|
stages = activeStages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -435,8 +435,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName),
|
_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName),
|
||||||
features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue
|
features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue
|
||||||
featuresRobustness2.NullDescriptor || IsMoltenVk,
|
featuresRobustness2.NullDescriptor || IsMoltenVk,
|
||||||
supportsPushDescriptors && !IsMoltenVk,
|
supportsPushDescriptors,
|
||||||
propertiesPushDescriptor.MaxPushDescriptors,
|
IsMoltenVk ? 16 : propertiesPushDescriptor.MaxPushDescriptors, // In case an old version of MoltenVK is used, apply a limit to prevent vertex explosions.
|
||||||
featuresPrimitiveTopologyListRestart.PrimitiveTopologyListRestart,
|
featuresPrimitiveTopologyListRestart.PrimitiveTopologyListRestart,
|
||||||
featuresPrimitiveTopologyListRestart.PrimitiveTopologyPatchListRestart,
|
featuresPrimitiveTopologyListRestart.PrimitiveTopologyPatchListRestart,
|
||||||
supportsTransformFeedback,
|
supportsTransformFeedback,
|
||||||
@@ -775,10 +775,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
supportsShaderBallot: false,
|
supportsShaderBallot: false,
|
||||||
supportsShaderBarrierDivergence: Vendor != Vendor.Intel,
|
supportsShaderBarrierDivergence: Vendor != Vendor.Intel,
|
||||||
supportsShaderFloat64: Capabilities.SupportsShaderFloat64,
|
supportsShaderFloat64: Capabilities.SupportsShaderFloat64,
|
||||||
|
|
||||||
supportsShaderNonUniformIndexing:
|
supportsShaderNonUniformIndexing:
|
||||||
featuresVk12.ShaderSampledImageArrayNonUniformIndexing &&
|
featuresVk12.ShaderSampledImageArrayNonUniformIndexing &&
|
||||||
featuresVk12.ShaderStorageImageArrayNonUniformIndexing,
|
featuresVk12.ShaderStorageImageArrayNonUniformIndexing,
|
||||||
supportsTextureGatherOffsets: features2.Features.ShaderImageGatherExtended && !IsMoltenVk,
|
supportsTextureGatherOffsets: features2.Features.ShaderImageGatherExtended,
|
||||||
supportsTextureShadowLod: false,
|
supportsTextureShadowLod: false,
|
||||||
supportsVertexStoreAndAtomics: features2.Features.VertexPipelineStoresAndAtomics,
|
supportsVertexStoreAndAtomics: features2.Features.VertexPipelineStoresAndAtomics,
|
||||||
supportsViewportIndexVertexTessellation: featuresVk12.ShaderOutputViewportIndex,
|
supportsViewportIndexVertexTessellation: featuresVk12.ShaderOutputViewportIndex,
|
||||||
|
|||||||
@@ -14,7 +14,10 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" >
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Services.Hid;
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using SDL;
|
using SDL;
|
||||||
using static SDL.SDL3;
|
using static SDL.SDL3;
|
||||||
@@ -13,6 +14,7 @@ namespace Ryujinx.Input.SDL3
|
|||||||
private readonly SDL_hid_device* _hidHandle;
|
private readonly SDL_hid_device* _hidHandle;
|
||||||
|
|
||||||
private int _globalCount;
|
private int _globalCount;
|
||||||
|
private ulong _lastWriteTicks;
|
||||||
|
|
||||||
private NpadHdRumble(SDL_hid_device* hidHandle)
|
private NpadHdRumble(SDL_hid_device* hidHandle)
|
||||||
{
|
{
|
||||||
@@ -28,7 +30,7 @@ namespace Ryujinx.Input.SDL3
|
|||||||
}
|
}
|
||||||
|
|
||||||
ushort product = SDL_GetGamepadProduct(gamepadHandle);
|
ushort product = SDL_GetGamepadProduct(gamepadHandle);
|
||||||
if (product != 0x2006 && product != 0x2007 && product != 0x2009 && product != 0x200e)
|
if (!Enum.IsDefined(typeof(HDRumbleSupported), product))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -37,7 +39,7 @@ namespace Ryujinx.Input.SDL3
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Some of the code was translated from https://github.com/MIZUSHIKI/JoyShockLibrary-plus-HDRumble
|
// Some of the code was translated from https://github.com/MIZUSHIKI/JoyShockLibrary-plus-HDRumble
|
||||||
private void WriteHdRumble(
|
private bool WriteHdRumble(
|
||||||
int encLeftLowFreq, int encLeftLowAmp,
|
int encLeftLowFreq, int encLeftLowAmp,
|
||||||
int encLeftHighFreq, int encLeftHighAmp,
|
int encLeftHighFreq, int encLeftHighAmp,
|
||||||
int encRightLowFreq, int encRightLowAmp,
|
int encRightLowFreq, int encRightLowAmp,
|
||||||
@@ -65,26 +67,35 @@ namespace Ryujinx.Input.SDL3
|
|||||||
|
|
||||||
fixed (byte* ptr = buf)
|
fixed (byte* ptr = buf)
|
||||||
{
|
{
|
||||||
SDL_hid_write(_hidHandle, ptr, (nuint)buf.Length);
|
if (SendHDRumble(ptr, (nuint)buf.Length) >= 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(SDL_GetError()))
|
||||||
|
{
|
||||||
|
Logger.Error?.PrintMsg(LogClass.Hid, SDL_GetError());
|
||||||
|
SDL_ClearError();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static int EncodeLowFreq(float lowFreq)
|
private static int EncodeLowFreq(float lowFreq)
|
||||||
{
|
{
|
||||||
float lf = Math.Clamp(lowFreq, 40.875885f, 626.286133f);
|
float lf = Math.Clamp(lowFreq, 40.875885f, 626.286133f);
|
||||||
return (int)Math.Round(32 * Math.Log2(lf * 0.1f)) - 0x40;
|
return (int) Math.Round(32 * Math.Log2(lf * 0.1f) - 0x40);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int EncodeHighFreq(float highFreq)
|
private static int EncodeHighFreq(float highFreq)
|
||||||
{
|
{
|
||||||
float hf = Math.Clamp(highFreq, 81.75177f, 1252.572266f);
|
float hf = Math.Clamp(highFreq, 81.75177f, 1252.572266f);
|
||||||
return ((int)Math.Round(32 * Math.Log2(hf * 0.1f)) - 0x60) * 4;
|
return (int) Math.Round((32 * Math.Log2(hf * 0.1f) - 0x60) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int EncodeLowAmp(float rawAmp)
|
private static int EncodeLowAmp(float rawAmp)
|
||||||
{
|
{
|
||||||
int encodedAmp = 0;
|
double encodedAmp = 0;
|
||||||
|
|
||||||
if (rawAmp is > 0 and < 0.012f)
|
if (rawAmp is > 0 and < 0.012f)
|
||||||
{
|
{
|
||||||
@@ -92,15 +103,15 @@ namespace Ryujinx.Input.SDL3
|
|||||||
}
|
}
|
||||||
else if (rawAmp is >= 0.012f and < 0.112f)
|
else if (rawAmp is >= 0.012f and < 0.112f)
|
||||||
{
|
{
|
||||||
encodedAmp = (int)Math.Round(4 * Math.Log2(rawAmp * 110f));
|
encodedAmp = 4 * Math.Log2(rawAmp * 110f);
|
||||||
}
|
}
|
||||||
else if (rawAmp is >= 0.112f and < 0.225f)
|
else if (rawAmp is >= 0.112f and < 0.225f)
|
||||||
{
|
{
|
||||||
encodedAmp = (int)Math.Round(16 * Math.Log2(rawAmp * 17f));
|
encodedAmp = 16 * Math.Log2(rawAmp * 17f);
|
||||||
}
|
}
|
||||||
else if (rawAmp is >= 0.225f and <= 1f)
|
else if (rawAmp is >= 0.225f and <= 1f)
|
||||||
{
|
{
|
||||||
encodedAmp = (int)Math.Round(32 * Math.Log2(rawAmp * 8.7f));
|
encodedAmp = 32 * Math.Log2(rawAmp * 8.7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int)Math.Floor(encodedAmp / 2.0) + 64;
|
return (int)Math.Floor(encodedAmp / 2.0) + 64;
|
||||||
@@ -108,7 +119,7 @@ namespace Ryujinx.Input.SDL3
|
|||||||
|
|
||||||
private static int EncodeHighAmp(float rawAmp)
|
private static int EncodeHighAmp(float rawAmp)
|
||||||
{
|
{
|
||||||
int encodedAmp = 0;
|
double encodedAmp = 0;
|
||||||
|
|
||||||
if (rawAmp is > 0 and < 0.012f)
|
if (rawAmp is > 0 and < 0.012f)
|
||||||
{
|
{
|
||||||
@@ -116,23 +127,23 @@ namespace Ryujinx.Input.SDL3
|
|||||||
}
|
}
|
||||||
else if (rawAmp is >= 0.012f and < 0.112f)
|
else if (rawAmp is >= 0.012f and < 0.112f)
|
||||||
{
|
{
|
||||||
encodedAmp = (int)Math.Round(4 * Math.Log2(rawAmp * 110f));
|
encodedAmp = 4 * Math.Log2(rawAmp * 110f);
|
||||||
}
|
}
|
||||||
else if (rawAmp is >= 0.112f and < 0.225f)
|
else if (rawAmp is >= 0.112f and < 0.225f)
|
||||||
{
|
{
|
||||||
encodedAmp = (int)Math.Round(16 * Math.Log2(rawAmp * 17f));
|
encodedAmp = 16 * Math.Log2(rawAmp * 17f);
|
||||||
}
|
}
|
||||||
else if (rawAmp is >= 0.225f and <= 1f)
|
else if (rawAmp is >= 0.225f and <= 1f)
|
||||||
{
|
{
|
||||||
encodedAmp = (int)Math.Round(32 * Math.Log2(rawAmp * 8.7f));
|
encodedAmp = 32 * Math.Log2(rawAmp * 8.7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return encodedAmp * 2;
|
return (int) Math.Round(encodedAmp * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HdRumble(VibrationValue left, VibrationValue right)
|
public bool HdRumble(VibrationValue left, VibrationValue right)
|
||||||
{
|
{
|
||||||
WriteHdRumble(EncodeLowFreq(left.FrequencyLow),
|
return WriteHdRumble(EncodeLowFreq(left.FrequencyLow),
|
||||||
EncodeLowAmp(left.AmplitudeLow),
|
EncodeLowAmp(left.AmplitudeLow),
|
||||||
EncodeHighFreq(left.FrequencyHigh),
|
EncodeHighFreq(left.FrequencyHigh),
|
||||||
EncodeHighAmp(left.AmplitudeHigh),
|
EncodeHighAmp(left.AmplitudeHigh),
|
||||||
@@ -140,7 +151,34 @@ namespace Ryujinx.Input.SDL3
|
|||||||
EncodeLowAmp(right.AmplitudeLow),
|
EncodeLowAmp(right.AmplitudeLow),
|
||||||
EncodeHighFreq(right.FrequencyHigh),
|
EncodeHighFreq(right.FrequencyHigh),
|
||||||
EncodeHighAmp(right.AmplitudeHigh));
|
EncodeHighAmp(right.AmplitudeHigh));
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
private int SendHDRumble(byte* data, nuint length)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
ulong currentTicks = SDL_GetTicks();
|
||||||
|
|
||||||
|
// Ditch rumble if we haven't hit the poll-rate yet.
|
||||||
|
// TODO: figure out a better way to do this
|
||||||
|
// While the polling check makes the rumble accurate, it also causes it to miss signals.
|
||||||
|
if ((currentTicks - _lastWriteTicks) < 8) // https://docs.handheldlegend.com/s/progcc-3/doc/lag-comparison-aAR1mV3JLX
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_LockJoysticks();
|
||||||
|
{
|
||||||
|
// Fun fact: Mario Kart 8 Deluxe sends rumble packets
|
||||||
|
// where the amplitude is zero, but the frequency isn't.
|
||||||
|
result = SDL_hid_write(_hidHandle, data, length);
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
_lastWriteTicks = currentTicks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_UnlockJoysticks();
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -148,4 +186,18 @@ namespace Ryujinx.Input.SDL3
|
|||||||
SDL_hid_close(_hidHandle);
|
SDL_hid_close(_hidHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum HDRumbleSupported : ushort
|
||||||
|
{
|
||||||
|
JoyConLeft = 0x2006,
|
||||||
|
JoyConRight = 0x2007,
|
||||||
|
JoyconPair = 0x2008,
|
||||||
|
ProController = 0x2009,
|
||||||
|
JoyconGrip = 0x200e,
|
||||||
|
Joycon2Right = 0x2066,
|
||||||
|
Joycon2Left = 0x2067,
|
||||||
|
Joycon2Pair = 0x2068,
|
||||||
|
Switch2ProController = 0x2069,
|
||||||
|
GamecubeController = 0x2073
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,10 +197,12 @@ namespace Ryujinx.Input.SDL3
|
|||||||
return _hdRumble?.HdRumble(left, right) ?? false;
|
return _hdRumble?.HdRumble(left, right) ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
public bool Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
{
|
{
|
||||||
if ((Features & GamepadFeaturesFlag.Rumble) == 0)
|
if ((Features & GamepadFeaturesFlag.Rumble) == 0)
|
||||||
return;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ushort lowFrequencyRaw = (ushort)(lowFrequency * ushort.MaxValue);
|
ushort lowFrequencyRaw = (ushort)(lowFrequency * ushort.MaxValue);
|
||||||
ushort highFrequencyRaw = (ushort)(highFrequency * ushort.MaxValue);
|
ushort highFrequencyRaw = (ushort)(highFrequency * ushort.MaxValue);
|
||||||
@@ -219,6 +221,15 @@ namespace Ryujinx.Input.SDL3
|
|||||||
if (!SDL_RumbleGamepad(_gamepadHandle, lowFrequencyRaw, highFrequencyRaw, durationMs))
|
if (!SDL_RumbleGamepad(_gamepadHandle, lowFrequencyRaw, highFrequencyRaw, durationMs))
|
||||||
Logger.Error?.Print(LogClass.Hid, "Rumble is not supported on this game controller.");
|
Logger.Error?.Print(LogClass.Hid, "Rumble is not supported on this game controller.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(SDL_GetError()))
|
||||||
|
{
|
||||||
|
Logger.Error?.PrintMsg(LogClass.Hid, SDL_GetError());
|
||||||
|
SDL_ClearError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 GetMotionData(MotionInputId inputId)
|
public Vector3 GetMotionData(MotionInputId inputId)
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ namespace Ryujinx.Input.SDL3
|
|||||||
|
|
||||||
public void SetTriggerThreshold(float triggerThreshold)
|
public void SetTriggerThreshold(float triggerThreshold)
|
||||||
{
|
{
|
||||||
|
// No operations
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HDRumble(VibrationValue left, VibrationValue right)
|
public bool HDRumble(VibrationValue left, VibrationValue right)
|
||||||
@@ -170,10 +170,12 @@ namespace Ryujinx.Input.SDL3
|
|||||||
return _hdRumble?.HdRumble(left, right) ?? false;
|
return _hdRumble?.HdRumble(left, right) ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
public bool Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
{
|
{
|
||||||
if ((Features & GamepadFeaturesFlag.Rumble) == 0)
|
if ((Features & GamepadFeaturesFlag.Rumble) == 0)
|
||||||
return;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ushort lowFrequencyRaw = (ushort)(lowFrequency * ushort.MaxValue);
|
ushort lowFrequencyRaw = (ushort)(lowFrequency * ushort.MaxValue);
|
||||||
ushort highFrequencyRaw = (ushort)(highFrequency * ushort.MaxValue);
|
ushort highFrequencyRaw = (ushort)(highFrequency * ushort.MaxValue);
|
||||||
@@ -192,6 +194,15 @@ namespace Ryujinx.Input.SDL3
|
|||||||
if (!SDL_RumbleGamepad(_gamepadHandle, lowFrequencyRaw, highFrequencyRaw, durationMs))
|
if (!SDL_RumbleGamepad(_gamepadHandle, lowFrequencyRaw, highFrequencyRaw, durationMs))
|
||||||
Logger.Error?.Print(LogClass.Hid, "Rumble is not supported on this game controller.");
|
Logger.Error?.Print(LogClass.Hid, "Rumble is not supported on this game controller.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(SDL_GetError()))
|
||||||
|
{
|
||||||
|
Logger.Error?.PrintMsg(LogClass.Hid, SDL_GetError());
|
||||||
|
SDL_ClearError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 GetMotionData(MotionInputId inputId)
|
public Vector3 GetMotionData(MotionInputId inputId)
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
|
using Gommon;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
@@ -61,7 +64,14 @@ namespace Ryujinx.Input.SDL3
|
|||||||
return left.IsPressed(inputId) || right.IsPressed(inputId);
|
return left.IsPressed(inputId) || right.IsPressed(inputId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
public bool HDRumble(VibrationValue left, VibrationValue right)
|
||||||
|
{
|
||||||
|
// return _hdRumble?.HdRumble(left, right) ?? false;
|
||||||
|
// TODO: Track rumble and motion on both controllers
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
{
|
{
|
||||||
if (lowFrequency != 0)
|
if (lowFrequency != 0)
|
||||||
{
|
{
|
||||||
@@ -78,6 +88,15 @@ namespace Ryujinx.Input.SDL3
|
|||||||
left.Rumble(0, 0, durationMs);
|
left.Rumble(0, 0, durationMs);
|
||||||
right.Rumble(0, 0, durationMs);
|
right.Rumble(0, 0, durationMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!SDL_GetError().IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
Logger.Error?.PrintMsg(LogClass.Hid, SDL_GetError());
|
||||||
|
SDL_ClearError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetConfiguration(InputConfig configuration)
|
public void SetConfiguration(InputConfig configuration)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
@@ -396,9 +397,14 @@ namespace Ryujinx.Input.SDL3
|
|||||||
// No operations
|
// No operations
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
public bool HDRumble(VibrationValue left, VibrationValue right)
|
||||||
{
|
{
|
||||||
// No operations
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 GetMotionData(MotionInputId inputId)
|
public Vector3 GetMotionData(MotionInputId inputId)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
@@ -67,7 +68,12 @@ namespace Ryujinx.Input.SDL3
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
public bool HDRumble(VibrationValue left, VibrationValue right)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
|||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Services.Hid;
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@@ -555,34 +554,37 @@ namespace Ryujinx.Input.HLE
|
|||||||
{
|
{
|
||||||
if (queue.TryDequeue(out (VibrationValue, VibrationValue) dualVibrationValue))
|
if (queue.TryDequeue(out (VibrationValue, VibrationValue) dualVibrationValue))
|
||||||
{
|
{
|
||||||
if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Rumble.EnableRumble)
|
if (_config is not StandardControllerInputConfig controllerConfig ||
|
||||||
|
!controllerConfig.Rumble.EnableRumble)
|
||||||
{
|
{
|
||||||
VibrationValue leftVibrationValue = dualVibrationValue.Item1;
|
return;
|
||||||
VibrationValue rightVibrationValue = dualVibrationValue.Item2;
|
|
||||||
|
|
||||||
float low = Math.Min(1f, (float)((rightVibrationValue.AmplitudeLow * 0.85 + rightVibrationValue.AmplitudeHigh * 0.15) * controllerConfig.Rumble.StrongRumble));
|
|
||||||
float high = Math.Min(1f, (float)((leftVibrationValue.AmplitudeLow * 0.15 + leftVibrationValue.AmplitudeHigh * 0.85) * controllerConfig.Rumble.WeakRumble));
|
|
||||||
|
|
||||||
leftVibrationValue.AmplitudeLow *= controllerConfig.Rumble.WeakRumble;
|
|
||||||
leftVibrationValue.AmplitudeHigh *= controllerConfig.Rumble.StrongRumble;
|
|
||||||
rightVibrationValue.AmplitudeLow *= controllerConfig.Rumble.WeakRumble;
|
|
||||||
rightVibrationValue.AmplitudeHigh *= controllerConfig.Rumble.StrongRumble;
|
|
||||||
|
|
||||||
if (_gamepad?.HDRumble(leftVibrationValue, rightVibrationValue) == false)
|
|
||||||
{
|
|
||||||
_gamepad?.Rumble(low, high, uint.MaxValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Debug?.Print(LogClass.Hid, $"Effect for {controllerConfig.PlayerIndex} " +
|
|
||||||
$"L.low.amp={leftVibrationValue.AmplitudeLow}, " +
|
|
||||||
$"L.high.amp={leftVibrationValue.AmplitudeHigh}, " +
|
|
||||||
$"L.low.freq={leftVibrationValue.FrequencyLow}, " +
|
|
||||||
$"L.high.freq={leftVibrationValue.FrequencyHigh}, " +
|
|
||||||
$"R.low.amp={rightVibrationValue.AmplitudeLow}, " +
|
|
||||||
$"R.high.amp={rightVibrationValue.AmplitudeHigh} " +
|
|
||||||
$"R.low.freq={rightVibrationValue.FrequencyLow}, " +
|
|
||||||
$"R.high.freq={rightVibrationValue.FrequencyHigh}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VibrationValue leftVibrationValue = dualVibrationValue.Item1;
|
||||||
|
VibrationValue rightVibrationValue = dualVibrationValue.Item2;
|
||||||
|
|
||||||
|
leftVibrationValue.AmplitudeLow *= controllerConfig.Rumble.WeakRumble;
|
||||||
|
leftVibrationValue.AmplitudeHigh *= controllerConfig.Rumble.StrongRumble;
|
||||||
|
rightVibrationValue.AmplitudeLow *= controllerConfig.Rumble.WeakRumble;
|
||||||
|
rightVibrationValue.AmplitudeHigh *= controllerConfig.Rumble.StrongRumble;
|
||||||
|
|
||||||
|
if (!controllerConfig.Rumble.UseHDRumble || _gamepad?.HDRumble(leftVibrationValue, rightVibrationValue) == false)
|
||||||
|
{
|
||||||
|
float low = Math.Min(1f, (float)((rightVibrationValue.AmplitudeLow * 0.85 + rightVibrationValue.AmplitudeHigh * 0.15)));
|
||||||
|
float high = Math.Min(1f, (float)((leftVibrationValue.AmplitudeLow * 0.15 + leftVibrationValue.AmplitudeHigh * 0.85)));
|
||||||
|
_gamepad?.Rumble(low, high, 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Debug?.Print(LogClass.Hid, $"Effect for {controllerConfig.PlayerIndex} " +
|
||||||
|
// Value=value/multiplier * multiplier (result)
|
||||||
|
$"L.low.amp={leftVibrationValue.AmplitudeLow / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.AmplitudeLow}), " +
|
||||||
|
$"L.high.amp={leftVibrationValue.AmplitudeHigh / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.AmplitudeHigh}), " +
|
||||||
|
$"L.low.freq={leftVibrationValue.FrequencyLow / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.FrequencyLow}), " +
|
||||||
|
$"L.high.freq={leftVibrationValue.FrequencyHigh / controllerConfig.Rumble.WeakRumble} * {controllerConfig.Rumble.WeakRumble} ({leftVibrationValue.FrequencyHigh}), " +
|
||||||
|
$"R.low.amp={rightVibrationValue.AmplitudeLow / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.AmplitudeLow}), " +
|
||||||
|
$"R.high.amp={rightVibrationValue.AmplitudeHigh / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.AmplitudeHigh}), " +
|
||||||
|
$"R.low.freq={rightVibrationValue.FrequencyLow / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.FrequencyLow}), " +
|
||||||
|
$"R.high.freq={rightVibrationValue.FrequencyHigh / controllerConfig.Rumble.StrongRumble} * {controllerConfig.Rumble.StrongRumble} ({rightVibrationValue.FrequencyHigh})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,10 +80,7 @@ namespace Ryujinx.Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="left">The vibration data for the left side</param>
|
/// <param name="left">The vibration data for the left side</param>
|
||||||
/// <param name="right">The vibration data for the right side</param>
|
/// <param name="right">The vibration data for the right side</param>
|
||||||
bool HDRumble(VibrationValue left, VibrationValue right)
|
bool HDRumble(VibrationValue left, VibrationValue right);
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starts a rumble effect on the gamepad.
|
/// Starts a rumble effect on the gamepad.
|
||||||
@@ -91,10 +88,10 @@ namespace Ryujinx.Input
|
|||||||
/// <param name="lowFrequency">The intensity of the low frequency from 0.0f to 1.0f</param>
|
/// <param name="lowFrequency">The intensity of the low frequency from 0.0f to 1.0f</param>
|
||||||
/// <param name="highFrequency">The intensity of the high frequency from 0.0f to 1.0f</param>
|
/// <param name="highFrequency">The intensity of the high frequency from 0.0f to 1.0f</param>
|
||||||
/// <param name="durationMs">The duration of the rumble effect in milliseconds.</param>
|
/// <param name="durationMs">The duration of the rumble effect in milliseconds.</param>
|
||||||
void Rumble(float lowFrequency, float highFrequency, uint durationMs);
|
bool Rumble(float lowFrequency, float highFrequency, uint durationMs);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a snaphost of the state of the gamepad that is remapped with the informations from the <see cref="InputConfig"/> set via <see cref="SetConfiguration(InputConfig)"/>.
|
/// Get a snaphost of the state of the gamepad that is remapped with the information from the <see cref="InputConfig"/> set via <see cref="SetConfiguration(InputConfig)"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A remapped snaphost of the state of the gamepad.</returns>
|
/// <returns>A remapped snaphost of the state of the gamepad.</returns>
|
||||||
GamepadStateSnapshot GetMappedStateSnapshot();
|
GamepadStateSnapshot GetMappedStateSnapshot();
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ namespace Ryujinx.Headless
|
|||||||
StrongRumble = 1f,
|
StrongRumble = 1f,
|
||||||
WeakRumble = 1f,
|
WeakRumble = 1f,
|
||||||
EnableRumble = false,
|
EnableRumble = false,
|
||||||
|
UseHDRumble = true
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -149,9 +150,20 @@ namespace Ryujinx.Ava.Input
|
|||||||
Logger.Info?.Print(LogClass.UI, "SetLed called on an AvaloniaKeyboard");
|
Logger.Info?.Print(LogClass.UI, "SetLed called on an AvaloniaKeyboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTriggerThreshold(float triggerThreshold) { }
|
public void SetTriggerThreshold(float triggerThreshold)
|
||||||
|
{
|
||||||
|
// No operations
|
||||||
|
}
|
||||||
|
|
||||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs) { }
|
public bool HDRumble(VibrationValue left, VibrationValue right)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public Vector3 GetMotionData(MotionInputId inputId) => Vector3.Zero;
|
public Vector3 GetMotionData(MotionInputId inputId) => Vector3.Zero;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
@@ -65,7 +66,12 @@ namespace Ryujinx.Ava.Input
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
public bool HDRumble(VibrationValue left, VibrationValue right)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
<PackageReference Include="OpenTK.Core" />
|
<PackageReference Include="OpenTK.Core" />
|
||||||
<PackageReference Include="Ryujinx.Audio.OpenAL" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
<PackageReference Include="Ryujinx.Audio.OpenAL" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
||||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" />
|
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" />
|
||||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'" />
|
<PackageReference Include="Ryujinx.Graphics.Vulkan.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'" />
|
||||||
<PackageReference Include="Ryujinx.UpdateClient" />
|
<PackageReference Include="Ryujinx.UpdateClient" />
|
||||||
<PackageReference Include="Ryujinx.Systems.Update.Common" />
|
<PackageReference Include="Ryujinx.Systems.Update.Common" />
|
||||||
<PackageReference Include="securifybv.ShellLink" />
|
<PackageReference Include="securifybv.ShellLink" />
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current version of the file format
|
/// The current version of the file format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int CurrentVersion = 72;
|
public const int CurrentVersion = 73;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version of the configuration file format
|
/// Version of the configuration file format
|
||||||
|
|||||||
@@ -333,6 +333,7 @@ namespace Ryujinx.Ava.Systems.Configuration
|
|||||||
EnableRumble = false,
|
EnableRumble = false,
|
||||||
StrongRumble = 1f,
|
StrongRumble = 1f,
|
||||||
WeakRumble = 1f,
|
WeakRumble = 1f,
|
||||||
|
UseHDRumble = true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||||||
|
|
||||||
public float WeakRumble { get; set; }
|
public float WeakRumble { get; set; }
|
||||||
public float StrongRumble { get; set; }
|
public float StrongRumble { get; set; }
|
||||||
|
public bool UseHDRumble { get; set; }
|
||||||
|
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
@@ -236,6 +237,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||||||
EnableRumble = controllerInput.Rumble.EnableRumble;
|
EnableRumble = controllerInput.Rumble.EnableRumble;
|
||||||
WeakRumble = controllerInput.Rumble.WeakRumble;
|
WeakRumble = controllerInput.Rumble.WeakRumble;
|
||||||
StrongRumble = controllerInput.Rumble.StrongRumble;
|
StrongRumble = controllerInput.Rumble.StrongRumble;
|
||||||
|
UseHDRumble = controllerInput.Rumble.UseHDRumble;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controllerInput.Led != null)
|
if (controllerInput.Led != null)
|
||||||
@@ -307,6 +309,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
|||||||
EnableRumble = EnableRumble,
|
EnableRumble = EnableRumble,
|
||||||
WeakRumble = WeakRumble,
|
WeakRumble = WeakRumble,
|
||||||
StrongRumble = StrongRumble,
|
StrongRumble = StrongRumble,
|
||||||
|
UseHDRumble = UseHDRumble,
|
||||||
},
|
},
|
||||||
Led = new LedConfigController
|
Led = new LedConfigController
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -789,6 +789,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
StrongRumble = 1f,
|
StrongRumble = 1f,
|
||||||
WeakRumble = 1f,
|
WeakRumble = 1f,
|
||||||
EnableRumble = false,
|
EnableRumble = false,
|
||||||
|
UseHDRumble = true
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial float WeakRumble { get; set; }
|
public partial float WeakRumble { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial bool EnableHDRumble { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,15 @@
|
|||||||
Margin="5,0"
|
Margin="5,0"
|
||||||
Text="{Binding WeakRumble, StringFormat=\{0:0.00\}}" />
|
Text="{Binding WeakRumble, StringFormat=\{0:0.00\}}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<CheckBox
|
||||||
|
Margin="5"
|
||||||
|
IsChecked="{Binding EnableHDRumble}">
|
||||||
|
<TextBlock
|
||||||
|
Margin="0,3,0,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{ext:Locale ControllerSettingsRumbleUseHDRumble}"
|
||||||
|
ToolTip.Tip="{ext:Locale HDRumbleTooltip}" />
|
||||||
|
</CheckBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||||||
{
|
{
|
||||||
StrongRumble = config.StrongRumble,
|
StrongRumble = config.StrongRumble,
|
||||||
WeakRumble = config.WeakRumble,
|
WeakRumble = config.WeakRumble,
|
||||||
|
EnableHDRumble = config.UseHDRumble
|
||||||
};
|
};
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -45,6 +46,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||||||
GamepadInputConfig config = viewModel.Config;
|
GamepadInputConfig config = viewModel.Config;
|
||||||
config.StrongRumble = content.ViewModel.StrongRumble;
|
config.StrongRumble = content.ViewModel.StrongRumble;
|
||||||
config.WeakRumble = content.ViewModel.WeakRumble;
|
config.WeakRumble = content.ViewModel.WeakRumble;
|
||||||
|
config.UseHDRumble = content.ViewModel.EnableHDRumble;
|
||||||
};
|
};
|
||||||
|
|
||||||
await contentDialog.ShowAsync();
|
await contentDialog.ShowAsync();
|
||||||
|
|||||||
Reference in New Issue
Block a user