mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-05-26 15:09:17 +00:00
Compare commits
1 Commits
refactor/a
...
Canary-1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7aa6775af |
@@ -21,7 +21,7 @@ jobs:
|
|||||||
name: ${{ matrix.platform.name }} (${{ matrix.configuration }})
|
name: ${{ matrix.platform.name }} (${{ matrix.configuration }})
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/gruke-build/ubuntu:dotnet-latest
|
image: ghcr.io/catthehacker/ubuntu:act-latest
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -37,6 +37,19 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v5
|
||||||
|
with:
|
||||||
|
global-json-file: global.json
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install 7zip
|
||||||
|
run: |
|
||||||
|
sudo apt update && sudo apt install -y 7zip
|
||||||
|
|
||||||
- name: Overwrite csc problem matcher
|
- name: Overwrite csc problem matcher
|
||||||
run: echo "::add-matcher::.forgejo/csc.json"
|
run: echo "::add-matcher::.forgejo/csc.json"
|
||||||
|
|
||||||
@@ -94,6 +107,14 @@ jobs:
|
|||||||
|
|
||||||
PLATFORM_NAME="${{ matrix.platform.name }}"
|
PLATFORM_NAME="${{ matrix.platform.name }}"
|
||||||
|
|
||||||
|
sudo apt update && sudo apt install -y zsync desktop-file-utils appstream libfuse2t64
|
||||||
|
|
||||||
|
mkdir -p tools
|
||||||
|
export PATH="$PATH:$(readlink -f tools)"
|
||||||
|
|
||||||
|
# Setup appimagetool
|
||||||
|
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||||
|
chmod +x tools/appimagetool
|
||||||
chmod +x distribution/linux/appimage/build-appimage.sh
|
chmod +x distribution/linux/appimage/build-appimage.sh
|
||||||
|
|
||||||
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
||||||
@@ -120,9 +141,7 @@ jobs:
|
|||||||
|
|
||||||
build_macos:
|
build_macos:
|
||||||
name: macOS Universal (${{ matrix.configuration }})
|
name: macOS Universal (${{ matrix.configuration }})
|
||||||
runs-on: docker
|
runs-on: ubuntu-latest
|
||||||
container:
|
|
||||||
image: ghcr.io/gruke-build/ubuntu:dotnet-latest
|
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -131,12 +150,21 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v5
|
||||||
|
with:
|
||||||
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Setup LLVM 17
|
- name: Setup LLVM 17
|
||||||
run: |
|
run: |
|
||||||
wget https://apt.llvm.org/llvm.sh
|
wget https://apt.llvm.org/llvm.sh
|
||||||
chmod +x llvm.sh
|
chmod +x llvm.sh
|
||||||
sudo ./llvm.sh 17
|
sudo ./llvm.sh 17
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
- name: Install rcodesign
|
- name: Install rcodesign
|
||||||
run: |
|
run: |
|
||||||
gli ghr -R indygreg/apple-platform-rs -p apple-codesign-*-x86_64-unknown-linux-musl.tar.gz -O apple-codesign.tar.gz
|
gli ghr -R indygreg/apple-platform-rs -p apple-codesign-*-x86_64-unknown-linux-musl.tar.gz -O apple-codesign.tar.gz
|
||||||
|
|||||||
@@ -31,16 +31,29 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
platform:
|
platform:
|
||||||
- { name: win-x64, os: ghcr.io/gruke-build/ubuntu:dotnet-latest, zip_os_name: win_x64 }
|
- { name: win-x64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: win_x64 }
|
||||||
#- { name: win-arm64, os: ghcr.io/gruke-build/ubuntu:dotnet-latest, zip_os_name: win_arm64 }
|
#- { name: win-arm64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: win_arm64 }
|
||||||
- { name: linux-x64, os: ghcr.io/gruke-build/ubuntu:dotnet-latest, zip_os_name: linux_x64 }
|
- { name: linux-x64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: linux_x64 }
|
||||||
- { name: linux-arm64, os: ghcr.io/gruke-build/ubuntu:dotnet-latest, zip_os_name: linux_arm64 }
|
- { name: linux-arm64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: linux_arm64 }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v5
|
||||||
|
with:
|
||||||
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Overwrite csc problem matcher
|
- name: Overwrite csc problem matcher
|
||||||
run: echo "::add-matcher::.forgejo/csc.json"
|
run: echo "::add-matcher::.forgejo/csc.json"
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install 7zip
|
||||||
|
run: |
|
||||||
|
sudo apt update && sudo apt install -y 7zip
|
||||||
|
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
run: |
|
run: |
|
||||||
@@ -92,6 +105,14 @@ jobs:
|
|||||||
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
||||||
PLATFORM_NAME="${{ matrix.platform.name }}"
|
PLATFORM_NAME="${{ matrix.platform.name }}"
|
||||||
|
|
||||||
|
sudo apt update && sudo apt install -y zsync desktop-file-utils appstream libfuse2t64
|
||||||
|
|
||||||
|
mkdir -p tools
|
||||||
|
export PATH="$PATH:$(readlink -f tools)"
|
||||||
|
|
||||||
|
# Setup appimagetool
|
||||||
|
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||||
|
chmod +x tools/appimagetool
|
||||||
chmod +x distribution/linux/appimage/build-appimage.sh
|
chmod +x distribution/linux/appimage/build-appimage.sh
|
||||||
|
|
||||||
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
||||||
@@ -128,16 +149,25 @@ jobs:
|
|||||||
name: Release MacOS universal
|
name: Release MacOS universal
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/gruke-build/ubuntu:dotnet-latest
|
image: ghcr.io/catthehacker/ubuntu:act-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v5
|
||||||
|
with:
|
||||||
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Setup LLVM 17
|
- name: Setup LLVM 17
|
||||||
run: |
|
run: |
|
||||||
wget https://apt.llvm.org/llvm.sh
|
wget https://apt.llvm.org/llvm.sh
|
||||||
chmod +x llvm.sh
|
chmod +x llvm.sh
|
||||||
sudo ./llvm.sh 17
|
sudo ./llvm.sh 17
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
- name: Install rcodesign
|
- name: Install rcodesign
|
||||||
run: |
|
run: |
|
||||||
gli ghr -R indygreg/apple-platform-rs -p apple-codesign-*-x86_64-unknown-linux-musl.tar.gz -O apple-codesign.tar.gz
|
gli ghr -R indygreg/apple-platform-rs -p apple-codesign-*-x86_64-unknown-linux-musl.tar.gz -O apple-codesign.tar.gz
|
||||||
@@ -182,11 +212,18 @@ jobs:
|
|||||||
name: Post CI Steps
|
name: Post CI Steps
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/gruke-build/ubuntu:act-latest
|
image: ghcr.io/catthehacker/ubuntu:act-latest
|
||||||
needs:
|
needs:
|
||||||
- macos_release
|
- macos_release
|
||||||
- release
|
- release
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -25,16 +25,29 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
platform:
|
platform:
|
||||||
- { name: win-x64, os: ghcr.io/gruke-build/ubuntu:act-latest, zip_os_name: win_x64 }
|
- { name: win-x64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: win_x64 }
|
||||||
#- { name: win-arm64, os: ghcr.io/gruke-build/ubuntu:act-latest, zip_os_name: win_arm64 }
|
#- { name: win-arm64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: win_arm64 }
|
||||||
- { name: linux-x64, os: ghcr.io/gruke-build/ubuntu:act-latest, zip_os_name: linux_x64 }
|
- { name: linux-x64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: linux_x64 }
|
||||||
- { name: linux-arm64, os: ghcr.io/gruke-build/ubuntu:act-latest, zip_os_name: linux_arm64 }
|
- { name: linux-arm64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: linux_arm64 }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v5
|
||||||
|
with:
|
||||||
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Overwrite csc problem matcher
|
- name: Overwrite csc problem matcher
|
||||||
run: echo "::add-matcher::.github/csc.json"
|
run: echo "::add-matcher::.github/csc.json"
|
||||||
|
|
||||||
|
- name: Install 7zip
|
||||||
|
run: |
|
||||||
|
sudo apt install -y 7zip
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
run: |
|
run: |
|
||||||
@@ -89,6 +102,14 @@ jobs:
|
|||||||
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
||||||
PLATFORM_NAME="${{ matrix.platform.name }}"
|
PLATFORM_NAME="${{ matrix.platform.name }}"
|
||||||
|
|
||||||
|
sudo apt install -y zsync desktop-file-utils appstream
|
||||||
|
|
||||||
|
mkdir -p tools
|
||||||
|
export PATH="$PATH:$(readlink -f tools)"
|
||||||
|
|
||||||
|
# Setup appimagetool
|
||||||
|
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||||
|
chmod +x tools/appimagetool
|
||||||
chmod +x distribution/linux/appimage/build-appimage.sh
|
chmod +x distribution/linux/appimage/build-appimage.sh
|
||||||
|
|
||||||
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
||||||
@@ -122,9 +143,7 @@ jobs:
|
|||||||
|
|
||||||
macos_release:
|
macos_release:
|
||||||
name: Release MacOS universal
|
name: Release MacOS universal
|
||||||
runs-on: docker
|
runs-on: ubuntu-latest
|
||||||
container:
|
|
||||||
image: ghcr.io/gruke-build/ubuntu:dotnet-latest
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
@@ -138,6 +157,11 @@ jobs:
|
|||||||
chmod +x llvm.sh
|
chmod +x llvm.sh
|
||||||
sudo ./llvm.sh 17
|
sudo ./llvm.sh 17
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
- name: Install rcodesign
|
- name: Install rcodesign
|
||||||
run: |
|
run: |
|
||||||
gli ghr -R indygreg/apple-platform-rs -p apple-codesign-*-x86_64-unknown-linux-musl.tar.gz -O apple-codesign.tar.gz
|
gli ghr -R indygreg/apple-platform-rs -p apple-codesign-*-x86_64-unknown-linux-musl.tar.gz -O apple-codesign.tar.gz
|
||||||
@@ -181,13 +205,18 @@ jobs:
|
|||||||
|
|
||||||
post_ci:
|
post_ci:
|
||||||
name: Post-CI Steps
|
name: Post-CI Steps
|
||||||
runs-on: docker
|
runs-on: ubuntu-latest
|
||||||
container:
|
|
||||||
image: ghcr.io/gruke-build/ubuntu:act-latest
|
|
||||||
needs:
|
needs:
|
||||||
- macos_release
|
- macos_release
|
||||||
- release
|
- release
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
151
src/Ryujinx.Input.SDL3/NpadHdRumble.cs
Normal file
151
src/Ryujinx.Input.SDL3/NpadHdRumble.cs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
|
using SDL;
|
||||||
|
using static SDL.SDL3;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Input.SDL3
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Manages a HID handle of a gamepad to encode and write HD rumble commands for Nin controllers.
|
||||||
|
/// </summary>
|
||||||
|
public unsafe class NpadHdRumble : IDisposable
|
||||||
|
{
|
||||||
|
private readonly SDL_hid_device* _hidHandle;
|
||||||
|
|
||||||
|
private int _globalCount;
|
||||||
|
|
||||||
|
private NpadHdRumble(SDL_hid_device* hidHandle)
|
||||||
|
{
|
||||||
|
_hidHandle = hidHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NpadHdRumble Create(SDL_Gamepad* gamepadHandle)
|
||||||
|
{
|
||||||
|
ushort vendor = SDL_GetGamepadVendor(gamepadHandle);
|
||||||
|
if (vendor != 0x057e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort product = SDL_GetGamepadProduct(gamepadHandle);
|
||||||
|
if (product != 0x2006 && product != 0x2007 && product != 0x2009 && product != 0x200e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NpadHdRumble(SDL_hid_open(vendor, product, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some of the code was translated from https://github.com/MIZUSHIKI/JoyShockLibrary-plus-HDRumble
|
||||||
|
private void WriteHdRumble(
|
||||||
|
int encLeftLowFreq, int encLeftLowAmp,
|
||||||
|
int encLeftHighFreq, int encLeftHighAmp,
|
||||||
|
int encRightLowFreq, int encRightLowAmp,
|
||||||
|
int encRightHighFreq, int encRightHighAmp)
|
||||||
|
{
|
||||||
|
byte[] buf = new byte[10];
|
||||||
|
|
||||||
|
buf[0] = 0x10;
|
||||||
|
buf[1] = (byte)((++_globalCount) & 0xF);
|
||||||
|
|
||||||
|
buf[2] = (byte)(encLeftHighFreq & 0xFF);
|
||||||
|
buf[3] = (byte)(encLeftHighAmp + ((encLeftHighFreq >> 8) & 0xFF));
|
||||||
|
buf[4] = (byte)(encLeftLowFreq + ((encLeftLowAmp >> 8) & 0xFF));
|
||||||
|
buf[5] = (byte)(encLeftLowAmp & 0xFF);
|
||||||
|
|
||||||
|
buf[6] = (byte)(encRightHighFreq & 0xFF);
|
||||||
|
buf[7] = (byte)(encRightHighAmp + ((encRightHighFreq >> 8) & 0xFF));
|
||||||
|
buf[8] = (byte)(encRightLowFreq + ((encRightLowAmp >> 8) & 0xFF));
|
||||||
|
buf[9] = (byte)(encRightLowAmp & 0xFF);
|
||||||
|
|
||||||
|
if (_globalCount > 0xF)
|
||||||
|
{
|
||||||
|
_globalCount = 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed (byte* ptr = buf)
|
||||||
|
{
|
||||||
|
SDL_hid_write(_hidHandle, ptr, (nuint)buf.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static int EncodeLowFreq(float lowFreq)
|
||||||
|
{
|
||||||
|
float lf = Math.Clamp(lowFreq, 40.875885f, 626.286133f);
|
||||||
|
return (int)Math.Round(32 * Math.Log2(lf * 0.1f)) - 0x40;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int EncodeHighFreq(float highFreq)
|
||||||
|
{
|
||||||
|
float hf = Math.Clamp(highFreq, 81.75177f, 1252.572266f);
|
||||||
|
return ((int)Math.Round(32 * Math.Log2(hf * 0.1f)) - 0x60) * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int EncodeLowAmp(float rawAmp)
|
||||||
|
{
|
||||||
|
int encodedAmp = 0;
|
||||||
|
|
||||||
|
if (rawAmp is > 0 and < 0.012f)
|
||||||
|
{
|
||||||
|
encodedAmp = 1;
|
||||||
|
}
|
||||||
|
else if (rawAmp is >= 0.012f and < 0.112f)
|
||||||
|
{
|
||||||
|
encodedAmp = (int)Math.Round(4 * Math.Log2(rawAmp * 110f));
|
||||||
|
}
|
||||||
|
else if (rawAmp is >= 0.112f and < 0.225f)
|
||||||
|
{
|
||||||
|
encodedAmp = (int)Math.Round(16 * Math.Log2(rawAmp * 17f));
|
||||||
|
}
|
||||||
|
else if (rawAmp is >= 0.225f and <= 1f)
|
||||||
|
{
|
||||||
|
encodedAmp = (int)Math.Round(32 * Math.Log2(rawAmp * 8.7f));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)Math.Floor(encodedAmp / 2.0) + 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int EncodeHighAmp(float rawAmp)
|
||||||
|
{
|
||||||
|
int encodedAmp = 0;
|
||||||
|
|
||||||
|
if (rawAmp is > 0 and < 0.012f)
|
||||||
|
{
|
||||||
|
encodedAmp = 1;
|
||||||
|
}
|
||||||
|
else if (rawAmp is >= 0.012f and < 0.112f)
|
||||||
|
{
|
||||||
|
encodedAmp = (int)Math.Round(4 * Math.Log2(rawAmp * 110f));
|
||||||
|
}
|
||||||
|
else if (rawAmp is >= 0.112f and < 0.225f)
|
||||||
|
{
|
||||||
|
encodedAmp = (int)Math.Round(16 * Math.Log2(rawAmp * 17f));
|
||||||
|
}
|
||||||
|
else if (rawAmp is >= 0.225f and <= 1f)
|
||||||
|
{
|
||||||
|
encodedAmp = (int)Math.Round(32 * Math.Log2(rawAmp * 8.7f));
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodedAmp * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HdRumble(VibrationValue left, VibrationValue right)
|
||||||
|
{
|
||||||
|
WriteHdRumble(EncodeLowFreq(left.FrequencyLow),
|
||||||
|
EncodeLowAmp(left.AmplitudeLow),
|
||||||
|
EncodeHighFreq(left.FrequencyHigh),
|
||||||
|
EncodeHighAmp(left.AmplitudeHigh),
|
||||||
|
EncodeLowFreq(right.FrequencyLow),
|
||||||
|
EncodeLowAmp(right.AmplitudeLow),
|
||||||
|
EncodeHighFreq(right.FrequencyHigh),
|
||||||
|
EncodeHighAmp(right.AmplitudeHigh));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
SDL_hid_close(_hidHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ using Ryujinx.Common.Configuration.Hid;
|
|||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
@@ -76,11 +77,14 @@ namespace Ryujinx.Input.SDL3
|
|||||||
|
|
||||||
private SDL_Gamepad* _gamepadHandle;
|
private SDL_Gamepad* _gamepadHandle;
|
||||||
|
|
||||||
|
private NpadHdRumble _hdRumble;
|
||||||
|
|
||||||
private float _triggerThreshold;
|
private float _triggerThreshold;
|
||||||
|
|
||||||
public SDL3Gamepad(SDL_Gamepad* gamepadHandle, string driverId)
|
public SDL3Gamepad(SDL_Gamepad* gamepadHandle, string driverId)
|
||||||
{
|
{
|
||||||
_gamepadHandle = gamepadHandle;
|
_gamepadHandle = gamepadHandle;
|
||||||
|
_hdRumble = NpadHdRumble.Create(gamepadHandle);
|
||||||
_buttonsUserMapping = new List<ButtonMappingEntry>(20);
|
_buttonsUserMapping = new List<ButtonMappingEntry>(20);
|
||||||
|
|
||||||
Name = SDL_GetGamepadName(_gamepadHandle);
|
Name = SDL_GetGamepadName(_gamepadHandle);
|
||||||
@@ -165,6 +169,10 @@ namespace Ryujinx.Input.SDL3
|
|||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
|
if (disposing && _hdRumble != null)
|
||||||
|
{
|
||||||
|
_hdRumble.Dispose();
|
||||||
|
}
|
||||||
if (disposing && _gamepadHandle != null)
|
if (disposing && _gamepadHandle != null)
|
||||||
{
|
{
|
||||||
SDL_CloseGamepad(_gamepadHandle);
|
SDL_CloseGamepad(_gamepadHandle);
|
||||||
@@ -184,6 +192,11 @@ namespace Ryujinx.Input.SDL3
|
|||||||
_triggerThreshold = triggerThreshold;
|
_triggerThreshold = triggerThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HDRumble(VibrationValue left, VibrationValue right)
|
||||||
|
{
|
||||||
|
return _hdRumble?.HdRumble(left, right) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
{
|
{
|
||||||
if ((Features & GamepadFeaturesFlag.Rumble) == 0)
|
if ((Features & GamepadFeaturesFlag.Rumble) == 0)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
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;
|
||||||
@@ -62,6 +63,8 @@ namespace Ryujinx.Input.SDL3
|
|||||||
|
|
||||||
private SDL_Gamepad* _gamepadHandle;
|
private SDL_Gamepad* _gamepadHandle;
|
||||||
|
|
||||||
|
private NpadHdRumble _hdRumble;
|
||||||
|
|
||||||
private enum JoyConType
|
private enum JoyConType
|
||||||
{
|
{
|
||||||
Left, Right
|
Left, Right
|
||||||
@@ -76,6 +79,7 @@ namespace Ryujinx.Input.SDL3
|
|||||||
public SDL3JoyCon(SDL_Gamepad* gamepadHandle, string driverId)
|
public SDL3JoyCon(SDL_Gamepad* gamepadHandle, string driverId)
|
||||||
{
|
{
|
||||||
_gamepadHandle = gamepadHandle;
|
_gamepadHandle = gamepadHandle;
|
||||||
|
_hdRumble = NpadHdRumble.Create(gamepadHandle);
|
||||||
_buttonsUserMapping = new List<ButtonMappingEntry>(10);
|
_buttonsUserMapping = new List<ButtonMappingEntry>(10);
|
||||||
|
|
||||||
Name = SDL_GetGamepadName(_gamepadHandle);
|
Name = SDL_GetGamepadName(_gamepadHandle);
|
||||||
@@ -139,6 +143,10 @@ namespace Ryujinx.Input.SDL3
|
|||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
|
if (disposing && _hdRumble != null)
|
||||||
|
{
|
||||||
|
_hdRumble.Dispose();
|
||||||
|
}
|
||||||
if (disposing && _gamepadHandle != null)
|
if (disposing && _gamepadHandle != null)
|
||||||
{
|
{
|
||||||
SDL_CloseGamepad(_gamepadHandle);
|
SDL_CloseGamepad(_gamepadHandle);
|
||||||
@@ -157,6 +165,11 @@ namespace Ryujinx.Input.SDL3
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HDRumble(VibrationValue left, VibrationValue right)
|
||||||
|
{
|
||||||
|
return _hdRumble?.HdRumble(left, right) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
|
||||||
{
|
{
|
||||||
if ((Features & GamepadFeaturesFlag.Rumble) == 0)
|
if ((Features & GamepadFeaturesFlag.Rumble) == 0)
|
||||||
|
|||||||
@@ -563,14 +563,25 @@ namespace Ryujinx.Input.HLE
|
|||||||
float low = Math.Min(1f, (float)((rightVibrationValue.AmplitudeLow * 0.85 + rightVibrationValue.AmplitudeHigh * 0.15) * controllerConfig.Rumble.StrongRumble));
|
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));
|
float high = Math.Min(1f, (float)((leftVibrationValue.AmplitudeLow * 0.15 + leftVibrationValue.AmplitudeHigh * 0.85) * controllerConfig.Rumble.WeakRumble));
|
||||||
|
|
||||||
_gamepad?.Rumble(low, high, uint.MaxValue);
|
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} " +
|
Logger.Debug?.Print(LogClass.Hid, $"Effect for {controllerConfig.PlayerIndex} " +
|
||||||
$"L.low.amp={leftVibrationValue.AmplitudeLow}, " +
|
$"L.low.amp={leftVibrationValue.AmplitudeLow}, " +
|
||||||
$"L.high.amp={leftVibrationValue.AmplitudeHigh}, " +
|
$"L.high.amp={leftVibrationValue.AmplitudeHigh}, " +
|
||||||
|
$"L.low.freq={leftVibrationValue.FrequencyLow}, " +
|
||||||
|
$"L.high.freq={leftVibrationValue.FrequencyHigh}, " +
|
||||||
$"R.low.amp={rightVibrationValue.AmplitudeLow}, " +
|
$"R.low.amp={rightVibrationValue.AmplitudeLow}, " +
|
||||||
$"R.high.amp={rightVibrationValue.AmplitudeHigh} " +
|
$"R.high.amp={rightVibrationValue.AmplitudeHigh} " +
|
||||||
$"--> ({low}, {high})");
|
$"R.low.freq={rightVibrationValue.FrequencyLow}, " +
|
||||||
|
$"R.high.freq={rightVibrationValue.FrequencyHigh}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@@ -74,6 +75,16 @@ namespace Ryujinx.Input
|
|||||||
|
|
||||||
public void ClearLed() => SetLed(0);
|
public void ClearLed() => SetLed(0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts an HD vibration effect on the gamepad if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The vibration data for the left side</param>
|
||||||
|
/// <param name="right">The vibration data for the right side</param>
|
||||||
|
bool HDRumble(VibrationValue left, VibrationValue right)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starts a rumble effect on the gamepad.
|
/// Starts a rumble effect on the gamepad.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user