Compare commits
121 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
87f238be60 | ||
|
4d0dbbfae2 | ||
|
08384ee5a8 | ||
|
d4d0a48bfe | ||
|
57d8afd0c9 | ||
|
c43fb92bbf | ||
|
167f50bbcd | ||
|
ba91f5d401 | ||
|
79f6c18a9b | ||
|
4f63782bac | ||
|
6f5fcb7970 | ||
|
6ef8946169 | ||
|
42340fc743 | ||
|
103e7cb021 | ||
|
31ed061bea | ||
|
4218311e6a | ||
|
e37735ed26 | ||
|
74a18b7c18 | ||
|
74fe814329 | ||
|
d1a093e5ca | ||
|
dfb14a5607 | ||
|
904a5ffcb4 | ||
|
946633276b | ||
|
baf94e0e3e | ||
|
cf6201a4a6 | ||
|
18909195d1 | ||
|
f06d22d6f0 | ||
|
84d6e8d121 | ||
|
95c4912d58 | ||
|
356a75af0b | ||
|
4ae9921063 | ||
|
6a8ac389e5 | ||
|
8dd1eb333c | ||
|
7dc3a62c14 | ||
|
e59dba42ef | ||
|
bd6937ae5c | ||
|
b82e789d4f | ||
|
4a6724622e | ||
|
0c73eba3db | ||
|
a082e14ede | ||
|
d29da11d5f | ||
|
ea07328aea | ||
|
a0b3d82ee0 | ||
|
609de33b0b | ||
|
dfc0819e72 | ||
|
d4803356bb | ||
|
459efd0db7 | ||
|
8bb7a3fc97 | ||
|
628d092fc6 | ||
|
6c90d50c8e | ||
|
d56bab1e24 | ||
|
a37e2d6e44 | ||
|
25123232bd | ||
|
8927e0669f | ||
|
bbed3b9926 | ||
|
24c8b0edc0 | ||
|
e5066449a5 | ||
|
d704bcd93b | ||
|
c94f0fbb83 | ||
|
d1b30fbe08 | ||
|
4505a7f162 | ||
|
ccbbaddbcb | ||
|
8bf102d2cd | ||
|
2adf031830 | ||
|
bb4a28b525 | ||
|
a8fbcdae9f | ||
|
4e81ab4229 | ||
|
4117c13377 | ||
|
20a392ad55 | ||
|
70fcba39de | ||
|
7795b662a9 | ||
|
30bdc4544e | ||
|
f6475cca17 | ||
|
0335c52254 | ||
|
b8d992e5a7 | ||
|
a620cbcc90 | ||
|
cea204d48e | ||
|
35fb409e85 | ||
|
d7ec4308b4 | ||
|
fbdd390f90 | ||
|
f33fea3287 | ||
|
5d3eea40be | ||
|
cd37c75b82 | ||
|
43705c2320 | ||
|
371e6fa24c | ||
|
1d9b63cc6a | ||
|
795539bc82 | ||
|
dd2e851e95 | ||
|
2ca70eb9a0 | ||
|
6575952432 | ||
|
9a28ba72b1 | ||
|
34a9922b57 | ||
|
4df22eb867 | ||
|
f241f88558 | ||
|
90455a05e6 | ||
|
edc76883db | ||
|
427b7d06b5 | ||
|
331c07807f | ||
|
a772b073ec | ||
|
870d9599cc | ||
|
2dbbc9bc05 | ||
|
72634c80f4 | ||
|
bebd8eb822 | ||
|
f4b74e9ce1 | ||
|
4e19b36ad7 | ||
|
b16923a902 | ||
|
7e58b21f3d | ||
|
4fbc978e73 | ||
|
1a45dc8df8 | ||
|
f037fcba9a | ||
|
59a0c7cfd8 | ||
|
6f50b9bdb0 | ||
|
f11d663df7 | ||
|
19a949d0bf | ||
|
feec5ef7b3 | ||
|
9864675a0b | ||
|
06bff0159c | ||
|
04ed8c1f83 | ||
|
ad8d5b9b56 | ||
|
1df6c07f78 | ||
|
0531c16326 |
@@ -17,8 +17,8 @@ tab_width = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# JSON files
|
||||
[*.json]
|
||||
# Markdown, JSON, YAML, props and csproj files
|
||||
[*.{md,json,yml,props,csproj}]
|
||||
|
||||
# Indentation and spacing
|
||||
indent_size = 2
|
||||
|
18
.github/dependabot.yml
vendored
18
.github/dependabot.yml
vendored
@@ -13,7 +13,7 @@ updates:
|
||||
|
||||
- package-ecosystem: nuget
|
||||
directory: /
|
||||
open-pull-requests-limit: 5
|
||||
open-pull-requests-limit: 10
|
||||
schedule:
|
||||
interval: daily
|
||||
labels:
|
||||
@@ -22,3 +22,19 @@ updates:
|
||||
- marysaka
|
||||
commit-message:
|
||||
prefix: nuget
|
||||
groups:
|
||||
Avalonia:
|
||||
patterns:
|
||||
- "*Avalonia*"
|
||||
Silk.NET:
|
||||
patterns:
|
||||
- "Silk.NET*"
|
||||
OpenTK:
|
||||
patterns:
|
||||
- "OpenTK*"
|
||||
SixLabors:
|
||||
patterns:
|
||||
- "SixLabors*"
|
||||
NUnit:
|
||||
patterns:
|
||||
- "NUnit*"
|
||||
|
42
.github/labeler.yml
vendored
42
.github/labeler.yml
vendored
@@ -1,33 +1,35 @@
|
||||
audio: 'src/Ryujinx.Audio*/**'
|
||||
audio:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: 'src/Ryujinx.Audio*/**'
|
||||
|
||||
cpu:
|
||||
- 'src/ARMeilleure/**'
|
||||
- 'src/Ryujinx.Cpu/**'
|
||||
- 'src/Ryujinx.Memory/**'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['src/ARMeilleure/**', 'src/Ryujinx.Cpu/**', 'src/Ryujinx.Memory/**']
|
||||
|
||||
gpu:
|
||||
- 'src/Ryujinx.Graphics.*/**'
|
||||
- 'src/Spv.Generator/**'
|
||||
- 'src/Ryujinx.ShaderTools/**'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['src/Ryujinx.Graphics.*/**', 'src/Spv.Generator/**', 'src/Ryujinx.ShaderTools/**']
|
||||
|
||||
'graphics-backend:opengl':
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: 'src/Ryujinx.Graphics.OpenGL/**'
|
||||
|
||||
'graphics-backend:opengl': 'src/Ryujinx.Graphics.OpenGL/**'
|
||||
'graphics-backend:vulkan':
|
||||
- 'src/Ryujinx.Graphics.Vulkan/**'
|
||||
- 'src/Spv.Generator/**'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Vulkan/**', 'src/Spv.Generator/**']
|
||||
|
||||
gui:
|
||||
- 'src/Ryujinx/**'
|
||||
- 'src/Ryujinx.Ui.Common/**'
|
||||
- 'src/Ryujinx.Ui.LocaleGenerator/**'
|
||||
- 'src/Ryujinx.Ava/**'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.UI.Common/**', 'src/Ryujinx.UI.LocaleGenerator/**', 'src/Ryujinx.Ava/**']
|
||||
|
||||
horizon:
|
||||
- 'src/Ryujinx.HLE/**'
|
||||
- 'src/Ryujinx.Horizon*/**'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['src/Ryujinx.HLE/**', 'src/Ryujinx.Horizon/**']
|
||||
|
||||
kernel: 'src/Ryujinx.HLE/HOS/Kernel/**'
|
||||
kernel:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: 'src/Ryujinx.HLE/HOS/Kernel/**'
|
||||
|
||||
infra:
|
||||
- '.github/**'
|
||||
- 'distribution/**'
|
||||
- 'Directory.Packages.props'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['.github/**', 'distribution/**', 'Directory.Packages.props']
|
||||
|
79
.github/workflows/build.yml
vendored
79
.github/workflows/build.yml
vendored
@@ -10,28 +10,17 @@ env:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.OS_NAME }} (${{ matrix.configuration }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.platform.name }} (${{ matrix.configuration }})
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
configuration: [Debug, Release]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
OS_NAME: Linux x64
|
||||
DOTNET_RUNTIME_IDENTIFIER: linux-x64
|
||||
RELEASE_ZIP_OS_NAME: linux_x64
|
||||
|
||||
- os: macOS-latest
|
||||
OS_NAME: macOS x64
|
||||
DOTNET_RUNTIME_IDENTIFIER: osx-x64
|
||||
RELEASE_ZIP_OS_NAME: osx_x64
|
||||
|
||||
- os: windows-latest
|
||||
OS_NAME: Windows x64
|
||||
DOTNET_RUNTIME_IDENTIFIER: win-x64
|
||||
RELEASE_ZIP_OS_NAME: win_x64
|
||||
platform:
|
||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
||||
- { name: osx-x64, os: macOS-latest, zip_os_name: osx_x64 }
|
||||
|
||||
fail-fast: false
|
||||
steps:
|
||||
@@ -40,7 +29,7 @@ jobs:
|
||||
- uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
global-json-file: global.json
|
||||
|
||||
|
||||
- name: Overwrite csc problem matcher
|
||||
run: echo "::add-matcher::.github/csc.json"
|
||||
|
||||
@@ -49,6 +38,16 @@ jobs:
|
||||
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Change config filename
|
||||
run: sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
|
||||
|
||||
- name: Change config filename for macOS
|
||||
run: sed -r -i '' 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os == 'macOS-latest'
|
||||
|
||||
- name: Build
|
||||
run: dotnet build -c "${{ matrix.configuration }}" -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER
|
||||
|
||||
@@ -58,46 +57,47 @@ jobs:
|
||||
commands: dotnet test --no-build -c "${{ matrix.configuration }}"
|
||||
timeout-minutes: 10
|
||||
retry-codes: 139
|
||||
if: matrix.platform.name != 'linux-arm64'
|
||||
|
||||
- name: Publish Ryujinx
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
|
||||
|
||||
- name: Publish Ryujinx.Headless.SDL2
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
|
||||
|
||||
- name: Publish Ryujinx.Ava
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Ava --self-contained true
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Ava --self-contained true
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
|
||||
|
||||
- name: Set executable bit
|
||||
run: |
|
||||
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
||||
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
|
||||
chmod +x ./publish_ava/Ryujinx.Ava ./publish_ava/Ryujinx.sh
|
||||
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest'
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
|
||||
|
||||
- name: Upload Ryujinx artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
|
||||
path: publish
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
|
||||
|
||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
|
||||
path: publish_sdl2_headless
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
|
||||
|
||||
- name: Upload Ryujinx.Ava artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
|
||||
path: publish_ava
|
||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
|
||||
|
||||
build_macos:
|
||||
name: macOS Universal (${{ matrix.configuration }})
|
||||
@@ -135,6 +135,11 @@ jobs:
|
||||
id: git_short_hash
|
||||
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Change config filename
|
||||
run: sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
- name: Publish macOS Ryujinx.Ava
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
||||
@@ -144,14 +149,14 @@ jobs:
|
||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
||||
|
||||
- name: Upload Ryujinx.Ava artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||
path: "publish_ava/*.tar.gz"
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||
path: "publish_headless/*.tar.gz"
|
||||
|
4
.github/workflows/checks.yml
vendored
4
.github/workflows/checks.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
- '!.github/**'
|
||||
- '!*.yml'
|
||||
- '!*.config'
|
||||
- '!README.md'
|
||||
- '!*.md'
|
||||
- '.github/workflows/*.yml'
|
||||
|
||||
permissions:
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
|
||||
- name: Upload report
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dotnet-format
|
||||
path: ./*-report.json
|
||||
|
72
.github/workflows/flatpak.yml
vendored
72
.github/workflows/flatpak.yml
vendored
@@ -51,38 +51,76 @@ jobs:
|
||||
- name: Restore Nuget packages
|
||||
# With .NET 8.0.100, Microsoft.NET.ILLink.Tasks isn't restored by default and only seems to appears when publishing.
|
||||
# So we just publish to grab the dependencies
|
||||
run: dotnet publish -c Release -r linux-x64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained
|
||||
run: |
|
||||
dotnet publish -c Release -r linux-x64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained
|
||||
dotnet publish -c Release -r linux-arm64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained
|
||||
|
||||
- name: Generate nuget_sources.json
|
||||
shell: python
|
||||
run: |
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
import base64
|
||||
import binascii
|
||||
import json
|
||||
import os
|
||||
import urllib.request
|
||||
|
||||
sources = []
|
||||
|
||||
for path in Path(os.environ['NUGET_PACKAGES']).glob('**/*.nupkg.sha512'):
|
||||
name = path.parent.parent.name
|
||||
version = path.parent.name
|
||||
filename = '{}.{}.nupkg'.format(name, version)
|
||||
url = 'https://api.nuget.org/v3-flatcontainer/{}/{}/{}'.format(name, version, filename)
|
||||
|
||||
with path.open() as fp:
|
||||
sha512 = binascii.hexlify(base64.b64decode(fp.read())).decode('ascii')
|
||||
def create_source_from_external(name, version):
|
||||
full_dir_path = Path(os.environ["NUGET_PACKAGES"]).joinpath(name).joinpath(version)
|
||||
os.makedirs(full_dir_path, exist_ok=True)
|
||||
|
||||
sources.append({
|
||||
'type': 'file',
|
||||
'url': url,
|
||||
'sha512': sha512,
|
||||
'dest': os.environ['NUGET_SOURCES_DESTDIR'],
|
||||
'dest-filename': filename,
|
||||
})
|
||||
filename = "{}.{}.nupkg".format(name, version)
|
||||
url = "https://api.nuget.org/v3-flatcontainer/{}/{}/{}".format(
|
||||
name, version, filename
|
||||
)
|
||||
|
||||
with open('flathub/nuget_sources.json', 'w') as fp:
|
||||
json.dump(sources, fp, indent=4)
|
||||
print(f"Processing {url}...")
|
||||
response = urllib.request.urlopen(url)
|
||||
sha512 = hashlib.sha512(response.read()).hexdigest()
|
||||
|
||||
return {
|
||||
"type": "file",
|
||||
"url": url,
|
||||
"sha512": sha512,
|
||||
"dest": os.environ["NUGET_SOURCES_DESTDIR"],
|
||||
"dest-filename": filename,
|
||||
}
|
||||
|
||||
|
||||
has_added_x64_apphost = False
|
||||
|
||||
for path in Path(os.environ["NUGET_PACKAGES"]).glob("**/*.nupkg.sha512"):
|
||||
name = path.parent.parent.name
|
||||
version = path.parent.name
|
||||
filename = "{}.{}.nupkg".format(name, version)
|
||||
url = "https://api.nuget.org/v3-flatcontainer/{}/{}/{}".format(
|
||||
name, version, filename
|
||||
)
|
||||
|
||||
with path.open() as fp:
|
||||
sha512 = binascii.hexlify(base64.b64decode(fp.read())).decode("ascii")
|
||||
|
||||
sources.append(
|
||||
{
|
||||
"type": "file",
|
||||
"url": url,
|
||||
"sha512": sha512,
|
||||
"dest": os.environ["NUGET_SOURCES_DESTDIR"],
|
||||
"dest-filename": filename,
|
||||
}
|
||||
)
|
||||
|
||||
# .NET will not add current installed application host to the list, force inject it here.
|
||||
if not has_added_x64_apphost and name.startswith('microsoft.netcore.app.host'):
|
||||
sources.append(create_source_from_external("microsoft.netcore.app.host.linux-x64", version))
|
||||
has_added_x64_apphost = True
|
||||
|
||||
with open("flathub/nuget_sources.json", "w") as fp:
|
||||
json.dump(sources, fp, indent=4)
|
||||
|
||||
- name: Update flatpak metadata
|
||||
id: metadata
|
||||
|
41
.github/workflows/mako.yml
vendored
Normal file
41
.github/workflows/mako.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: Mako
|
||||
on:
|
||||
discussion:
|
||||
types: [created, edited, answered, unanswered, category_changed]
|
||||
discussion_comment:
|
||||
types: [created, edited]
|
||||
gollum:
|
||||
issue_comment:
|
||||
types: [created, edited]
|
||||
issues:
|
||||
types: [opened, edited, reopened, pinned, milestoned, demilestoned, assigned, unassigned, labeled, unlabeled]
|
||||
pull_request_target:
|
||||
types: [opened, edited, reopened, synchronize, ready_for_review, assigned, unassigned]
|
||||
|
||||
jobs:
|
||||
tasks:
|
||||
name: Run Ryujinx tasks
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
discussions: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
if: github.event_name == 'pull_request_target'
|
||||
with:
|
||||
# Ensure we pin the source origin as pull_request_target run under forks.
|
||||
fetch-depth: 0
|
||||
repository: Ryujinx/Ryujinx
|
||||
ref: master
|
||||
|
||||
- name: Run Mako command
|
||||
uses: Ryujinx/Ryujinx-Mako@master
|
||||
with:
|
||||
command: exec-ryujinx-tasks
|
||||
args: --event-name "${{ github.event_name }}" --event-path "${{ github.event_path }}" -w "${{ github.workspace }}" "${{ github.repository }}" "${{ github.run_id }}"
|
||||
app_id: ${{ secrets.MAKO_APP_ID }}
|
||||
private_key: ${{ secrets.MAKO_PRIVATE_KEY }}
|
||||
installation_id: ${{ secrets.MAKO_INSTALLATION_ID }}
|
19
.github/workflows/pr_triage.yml
vendored
19
.github/workflows/pr_triage.yml
vendored
@@ -21,27 +21,8 @@ jobs:
|
||||
repository: Ryujinx/Ryujinx
|
||||
ref: master
|
||||
|
||||
- name: Checkout Ryujinx-Mako
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: Ryujinx/Ryujinx-Mako
|
||||
ref: master
|
||||
path: '.ryujinx-mako'
|
||||
|
||||
- name: Setup Ryujinx-Mako
|
||||
uses: ./.ryujinx-mako/.github/actions/setup-mako
|
||||
|
||||
- name: Update labels based on changes
|
||||
uses: actions/labeler@v5
|
||||
with:
|
||||
sync-labels: true
|
||||
dot: true
|
||||
|
||||
- name: Assign reviewers
|
||||
run: |
|
||||
poetry -n -C .ryujinx-mako run ryujinx-mako update-reviewers ${{ github.repository }} ${{ github.event.pull_request.number }} .github/reviewers.yml
|
||||
shell: bash
|
||||
env:
|
||||
MAKO_APP_ID: ${{ secrets.MAKO_APP_ID }}
|
||||
MAKO_PRIVATE_KEY: ${{ secrets.MAKO_PRIVATE_KEY }}
|
||||
MAKO_INSTALLATION_ID: ${{ secrets.MAKO_INSTALLATION_ID }}
|
||||
|
45
.github/workflows/release.yml
vendored
45
.github/workflows/release.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
- '*.yml'
|
||||
- '*.json'
|
||||
- '*.config'
|
||||
- 'README.md'
|
||||
- '*.md'
|
||||
|
||||
concurrency: release
|
||||
|
||||
@@ -45,22 +45,15 @@ jobs:
|
||||
})
|
||||
|
||||
release:
|
||||
name: Release ${{ matrix.OS_NAME }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Release for ${{ matrix.platform.name }}
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
OS_NAME: Linux x64
|
||||
DOTNET_RUNTIME_IDENTIFIER: linux-x64
|
||||
RELEASE_ZIP_OS_NAME: linux_x64
|
||||
|
||||
- os: windows-latest
|
||||
OS_NAME: Windows x64
|
||||
DOTNET_RUNTIME_IDENTIFIER: win-x64
|
||||
RELEASE_ZIP_OS_NAME: win_x64
|
||||
platform:
|
||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -85,6 +78,7 @@ jobs:
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
|
||||
- name: Create output dir
|
||||
@@ -92,42 +86,42 @@ jobs:
|
||||
|
||||
- name: Publish
|
||||
run: |
|
||||
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_gtk/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained true
|
||||
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained true
|
||||
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Ava --self-contained true
|
||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_gtk/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained true
|
||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained true
|
||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Ava --self-contained true
|
||||
|
||||
- name: Packing Windows builds
|
||||
if: matrix.os == 'windows-latest'
|
||||
if: matrix.platform.os == 'windows-latest'
|
||||
run: |
|
||||
pushd publish_gtk
|
||||
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
|
||||
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
|
||||
popd
|
||||
|
||||
pushd publish_sdl2_headless
|
||||
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
|
||||
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
|
||||
popd
|
||||
|
||||
pushd publish_ava
|
||||
7z a ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
|
||||
7z a ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
|
||||
popd
|
||||
shell: bash
|
||||
|
||||
- name: Packing Linux builds
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
if: matrix.platform.os == 'ubuntu-latest'
|
||||
run: |
|
||||
pushd publish_gtk
|
||||
chmod +x publish/Ryujinx.sh publish/Ryujinx
|
||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
||||
popd
|
||||
|
||||
pushd publish_sdl2_headless
|
||||
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
|
||||
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
||||
popd
|
||||
|
||||
pushd publish_ava
|
||||
chmod +x publish/Ryujinx.sh publish/Ryujinx.Ava
|
||||
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
||||
popd
|
||||
shell: bash
|
||||
|
||||
@@ -186,6 +180,7 @@ jobs:
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
|
||||
- name: Publish macOS Ryujinx.Ava
|
||||
|
@@ -3,39 +3,39 @@
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="11.0.5" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.5" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.5" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.5" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.5" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.3" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.3" />
|
||||
<PackageVersion Include="Avalonia" Version="11.0.7" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.7" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.7" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.7" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.7" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.13" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.13" />
|
||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageVersion Include="Concentus" Version="1.1.7" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||
<PackageVersion Include="DynamicData" Version="7.14.2" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.4" />
|
||||
<PackageVersion Include="DynamicData" Version="8.3.27" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.3.0-beta.4" />
|
||||
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.3.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
|
||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||
<PackageVersion Include="NetCoreServer" Version="7.0.0" />
|
||||
<PackageVersion Include="NetCoreServer" Version="8.0.7" />
|
||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
|
||||
<PackageVersion Include="OpenTK.Core" Version="4.8.1" />
|
||||
<PackageVersion Include="OpenTK.Graphics" Version="4.8.1" />
|
||||
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.1" />
|
||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.1" />
|
||||
<PackageVersion Include="OpenTK.Core" Version="4.8.2" />
|
||||
<PackageVersion Include="OpenTK.Graphics" Version="4.8.2" />
|
||||
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.2" />
|
||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
|
||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.28.1-build28" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||
@@ -44,9 +44,8 @@
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp" Version="1.0.4" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
|
||||
<PackageVersion Include="SPB" Version="0.0.4-build28" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="8.0.0" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
|
||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="8.0.2" />
|
||||
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Management" Version="8.0.0" />
|
||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||
|
93
README.md
93
README.md
@@ -1,21 +1,21 @@
|
||||
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://ryujinx.org/"><img src="https://i.imgur.com/WcCj6Rt.png" alt="Ryujinx" width="150"></a>
|
||||
<a href="https://ryujinx.org/"><img src="https://raw.githubusercontent.com/Ryujinx/Ryujinx/master/distribution/misc/Logo.svg" alt="Ryujinx" width="150"></a>
|
||||
<br>
|
||||
<b>Ryujinx</b>
|
||||
<br>
|
||||
<sub><sup><b>(REE-YOU-JINX)</b></sup></sub>
|
||||
<br>
|
||||
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
Ryujinx is an open-source Nintendo Switch emulator, created by gdkchan, written in C#.
|
||||
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
||||
It was written from scratch and development on the project began in September 2017. Ryujinx is available on Github under the <a href="https://github.com/Ryujinx/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>. <br />
|
||||
|
||||
Ryujinx is an open-source Nintendo Switch emulator, created by gdkchan, written in C#.
|
||||
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
||||
It was written from scratch and development on the project began in September 2017.
|
||||
Ryujinx is available on Github under the <a href="https://github.com/Ryujinx/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>.
|
||||
<br />
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml">
|
||||
<img src="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml/badge.svg"
|
||||
@@ -34,87 +34,111 @@
|
||||
<img src="https://raw.githubusercontent.com/Ryujinx/Ryujinx-Website/master/public/assets/images/shell.png">
|
||||
</p>
|
||||
|
||||
<h5 align="center">
|
||||
|
||||
</h5>
|
||||
|
||||
## Compatibility
|
||||
|
||||
As of April 2023, Ryujinx has been tested on approximately 4,050 titles; over 4,000 boot past menus and into gameplay, with roughly 3,400 of those being considered playable.
|
||||
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues). Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
||||
As of October 2023, Ryujinx has been tested on approximately 4,200 titles;
|
||||
over 4,150 boot past menus and into gameplay, with roughly 3,500 of those being considered playable.
|
||||
|
||||
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues).
|
||||
|
||||
Anyone is free to submit a new game test or update an existing game test entry;
|
||||
simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue.
|
||||
Use the search function to see if a game has been tested already!
|
||||
|
||||
## Usage
|
||||
|
||||
To run this emulator, your PC must be equipped with at least 8GiB of RAM; failing to meet this requirement may result in a poor gameplay experience or unexpected crashes.
|
||||
To run this emulator, your PC must be equipped with at least 8GiB of RAM;
|
||||
failing to meet this requirement may result in a poor gameplay experience or unexpected crashes.
|
||||
|
||||
See our [Setup & Configuration Guide](https://github.com/Ryujinx/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide) on how to set up the emulator.
|
||||
|
||||
For our Local Wireless and LAN builds, see our [Multiplayer: Local Play/Local Wireless Guide
|
||||
For our Local Wireless (LDN) builds, see our [Multiplayer: Local Play/Local Wireless Guide
|
||||
](https://github.com/Ryujinx/Ryujinx/wiki/Multiplayer-(LDN-Local-Wireless)-Guide).
|
||||
|
||||
Avalonia UI comes with translations for various languages. See [Crowdin](https://crwd.in/ryujinx) for more information.
|
||||
|
||||
## Latest build
|
||||
|
||||
These builds are compiled automatically for each commit on the master branch. While we strive to ensure optimal stability and performance prior to pushing an update, our automated builds **may be unstable or completely broken.**
|
||||
These builds are compiled automatically for each commit on the master branch.
|
||||
While we strive to ensure optimal stability and performance prior to pushing an update, our automated builds **may be unstable or completely broken**.
|
||||
|
||||
If you want to see details on updates to the emulator, you can visit our [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog).
|
||||
|
||||
The latest automatic build for Windows, macOS, and Linux can be found on the [Official Website](https://ryujinx.org/download).
|
||||
|
||||
## Documentation
|
||||
|
||||
If you are planning to contribute or just want to learn more about this project please read through our [documentation](docs/README.md).
|
||||
|
||||
## Building
|
||||
|
||||
If you wish to build the emulator yourself, follow these steps:
|
||||
|
||||
### Step 1
|
||||
Install the X64 version of [.NET 8.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/8.0).
|
||||
|
||||
Install the [.NET 8.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/8.0).
|
||||
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
|
||||
|
||||
### Step 2
|
||||
|
||||
Either use `git clone https://github.com/Ryujinx/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||
|
||||
### Step 3
|
||||
|
||||
To build Ryujinx, open a command prompt inside the project directory. You can quickly access it on Windows by holding shift in File Explorer, then right clicking and selecting `Open command window here`. Then type the following command:
|
||||
`dotnet build -c Release -o build`
|
||||
To build Ryujinx, open a command prompt inside the project directory.
|
||||
You can quickly access it on Windows by holding shift in File Explorer, then right clicking and selecting `Open command window here`.
|
||||
Then type the following command: `dotnet build -c Release -o build`
|
||||
the built files will be found in the newly created build directory.
|
||||
|
||||
Ryujinx system files are stored in the `Ryujinx` folder. This folder is located in the user folder, which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
||||
|
||||
Ryujinx system files are stored in the `Ryujinx` folder.
|
||||
This folder is located in the user folder, which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
||||
|
||||
## Features
|
||||
|
||||
- **Audio**
|
||||
- **Audio**
|
||||
|
||||
Audio output is entirely supported, audio input (microphone) isn't supported. We use C# wrappers for [OpenAL](https://openal-soft.org/), and [SDL2](https://www.libsdl.org/) & [libsoundio](http://libsound.io/) as fallbacks.
|
||||
Audio output is entirely supported, audio input (microphone) isn't supported.
|
||||
We use C# wrappers for [OpenAL](https://openal-soft.org/), and [SDL2](https://www.libsdl.org/) & [libsoundio](http://libsound.io/) as fallbacks.
|
||||
|
||||
- **CPU**
|
||||
|
||||
The CPU emulator, ARMeilleure, emulates an ARMv8 CPU and currently has support for most 64-bit ARMv8 and some of the ARMv7 (and older) instructions, including partial 32-bit support. It translates the ARM code to a custom IR, performs a few optimizations, and turns that into x86 code.
|
||||
There are three memory manager options available depending on the user's preference, leveraging both software-based (slower) and host-mapped modes (much faster). The fastest option (host, unchecked) is set by default.
|
||||
Ryujinx also features an optional Profiled Persistent Translation Cache, which essentially caches translated functions so that they do not need to be translated every time the game loads. The net result is a significant reduction in load times (the amount of time between launching a game and arriving at the title screen) for nearly every game. NOTE: this feature is enabled by default in the Options menu > System tab. You must launch the game at least twice to the title screen or beyond before performance improvements are unlocked on the third launch! These improvements are permanent and do not require any extra launches going forward.
|
||||
The CPU emulator, ARMeilleure, emulates an ARMv8 CPU and currently has support for most 64-bit ARMv8 and some of the ARMv7 (and older) instructions, including partial 32-bit support.
|
||||
It translates the ARM code to a custom IR, performs a few optimizations, and turns that into x86 code.
|
||||
There are three memory manager options available depending on the user's preference, leveraging both software-based (slower) and host-mapped modes (much faster).
|
||||
The fastest option (host, unchecked) is set by default.
|
||||
Ryujinx also features an optional Profiled Persistent Translation Cache, which essentially caches translated functions so that they do not need to be translated every time the game loads.
|
||||
The net result is a significant reduction in load times (the amount of time between launching a game and arriving at the title screen) for nearly every game.
|
||||
NOTE: This feature is enabled by default in the Options menu > System tab.
|
||||
You must launch the game at least twice to the title screen or beyond before performance improvements are unlocked on the third launch!
|
||||
These improvements are permanent and do not require any extra launches going forward.
|
||||
|
||||
- **GPU**
|
||||
|
||||
The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively. There are currently six graphics enhancements available to the end user in Ryujinx: Disk Shader Caching, Resolution Scaling, Anti-Aliasing, Scaling Filters (including FSR), Anisotropic Filtering and Aspect Ratio Adjustment. These enhancements can be adjusted or toggled as desired in the GUI.
|
||||
The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively.
|
||||
There are currently six graphics enhancements available to the end user in Ryujinx: Disk Shader Caching, Resolution Scaling, Anti-Aliasing, Scaling Filters (including FSR), Anisotropic Filtering and Aspect Ratio Adjustment.
|
||||
These enhancements can be adjusted or toggled as desired in the GUI.
|
||||
|
||||
- **Input**
|
||||
|
||||
We currently have support for keyboard, mouse, touch input, JoyCon input support, and nearly all controllers. Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
||||
In all scenarios, you can set up everything inside the input configuration menu.
|
||||
We currently have support for keyboard, mouse, touch input, JoyCon input support, and nearly all controllers.
|
||||
Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
||||
In all scenarios, you can set up everything inside the input configuration menu.
|
||||
|
||||
- **DLC & Modifications**
|
||||
|
||||
Ryujinx is able to manage add-on content/downloadable content through the GUI. Mods (romfs, exefs, and runtime mods such as cheats) are also supported; the GUI contains a shortcut to open the respective mods folder for a particular game.
|
||||
Ryujinx is able to manage add-on content/downloadable content through the GUI.
|
||||
Mods (romfs, exefs, and runtime mods such as cheats) are also supported;
|
||||
the GUI contains a shortcut to open the respective mods folder for a particular game.
|
||||
|
||||
- **Configuration**
|
||||
|
||||
The emulator has settings for enabling or disabling some logging, remapping controllers, and more. You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the user folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
||||
|
||||
The emulator has settings for enabling or disabling some logging, remapping controllers, and more.
|
||||
You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the user folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
||||
|
||||
## Contact
|
||||
|
||||
If you have contributions, suggestions, need emulator support or just want to get in touch with the team, join our [Discord server](https://discord.com/invite/Ryujinx). You may also review our [FAQ](https://github.com/Ryujinx/Ryujinx/wiki/Frequently-Asked-Questions).
|
||||
If you have contributions, suggestions, need emulator support or just want to get in touch with the team, join our [Discord server](https://discord.com/invite/Ryujinx).
|
||||
You may also review our [FAQ](https://github.com/Ryujinx/Ryujinx/wiki/Frequently-Asked-Questions).
|
||||
|
||||
## Donations
|
||||
|
||||
@@ -134,9 +158,10 @@ All funds received through Patreon are considered a donation to support the proj
|
||||
|
||||
## License
|
||||
|
||||
This software is licensed under the terms of the <a href="https://github.com/Ryujinx/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license.</a></i><br />
|
||||
This software is licensed under the terms of the [MIT license](LICENSE.txt).
|
||||
This project makes use of code authored by the libvpx project, licensed under BSD and the ffmpeg project, licensed under LGPLv3.
|
||||
See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY.md) for more details.
|
||||
|
||||
## Credits
|
||||
|
||||
- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system.
|
||||
|
@@ -71,7 +71,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmp
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Ava", "src\Ryujinx.Ava\Ryujinx.Ava.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Ui.Common", "src\Ryujinx.Ui.Common\Ryujinx.Ui.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.Common", "src\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
|
||||
EndProject
|
||||
@@ -79,7 +79,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spv.Generator", "src\Spv.Generator\Spv.Generator.csproj", "{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Ui.LocaleGenerator", "src\Ryujinx.Ui.LocaleGenerator\Ryujinx.Ui.LocaleGenerator.csproj", "{77D01AD9-2C98-478E-AE1D-8F7100738FB4}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.LocaleGenerator", "src\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj", "{77D01AD9-2C98-478E-AE1D-8F7100738FB4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Common", "src\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj", "{77F96ECE-4952-42DB-A528-DED25572A573}"
|
||||
EndProject
|
||||
|
@@ -4,7 +4,7 @@ Name=Ryujinx
|
||||
Type=Application
|
||||
Icon=Ryujinx
|
||||
Exec=Ryujinx.sh %f
|
||||
Comment=Plays Nintendo Switch applications
|
||||
Comment=A Nintendo Switch Emulator
|
||||
GenericName=Nintendo Switch Emulator
|
||||
Terminal=false
|
||||
Categories=Game;Emulator;
|
||||
|
15
distribution/linux/Ryujinx.sh
Normal file → Executable file
15
distribution/linux/Ryujinx.sh
Normal file → Executable file
@@ -1,14 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
SCRIPT_DIR=$(dirname "$(realpath "$0")")
|
||||
RYUJINX_BIN="Ryujinx"
|
||||
|
||||
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
|
||||
RYUJINX_BIN="Ryujinx.Headless.SDL2"
|
||||
fi
|
||||
|
||||
if [ -f "$SCRIPT_DIR/Ryujinx.Ava" ]; then
|
||||
RYUJINX_BIN="Ryujinx.Ava"
|
||||
fi
|
||||
|
||||
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
|
||||
RYUJINX_BIN="Ryujinx.Headless.SDL2"
|
||||
if [ -f "$SCRIPT_DIR/Ryujinx" ]; then
|
||||
RYUJINX_BIN="Ryujinx"
|
||||
fi
|
||||
|
||||
if [ -z "$RYUJINX_BIN" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
COMMAND="env DOTNET_EnableAlternateStackCheck=1"
|
||||
@@ -17,4 +24,4 @@ if command -v gamemoderun > /dev/null 2>&1; then
|
||||
COMMAND="$COMMAND gamemoderun"
|
||||
fi
|
||||
|
||||
$COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@"
|
||||
exec $COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@"
|
||||
|
@@ -10,14 +10,25 @@
|
||||
<string>Ryujinx</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>Ryujinx.icns</string>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>nca</string>
|
||||
<string>nro</string>
|
||||
<string>nso</string>
|
||||
<string>nsp</string>
|
||||
<string>xci</string>
|
||||
</array>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>nca</string>
|
||||
<string>nro</string>
|
||||
<string>nso</string>
|
||||
<string>nsp</string>
|
||||
<string>xci</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Nintendo Switch File</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Default</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.ryujinx.Ryujinx</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
|
8
distribution/macos/shortcut-launch-script.sh
Normal file
8
distribution/macos/shortcut-launch-script.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
launch_arch="$(uname -m)"
|
||||
if [ "$(sysctl -in sysctl.proc_translated)" = "1" ]
|
||||
then
|
||||
launch_arch="arm64"
|
||||
fi
|
||||
|
||||
arch -$launch_arch {0} {1}
|
@@ -9,7 +9,7 @@ namespace ARMeilleure.Common
|
||||
/// Represents a table of guest address to a value.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntry">Type of the value</typeparam>
|
||||
unsafe class AddressTable<TEntry> : IDisposable where TEntry : unmanaged
|
||||
public unsafe class AddressTable<TEntry> : IDisposable where TEntry : unmanaged
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a level in an <see cref="AddressTable{TEntry}"/>.
|
||||
|
@@ -517,7 +517,10 @@ namespace ARMeilleure.Decoders
|
||||
SetA64("0x00111100>>>xxx100111xxxxxxxxxx", InstName.Sqrshrn_V, InstEmit.Sqrshrn_V, OpCodeSimdShImm.Create);
|
||||
SetA64("0111111100>>>xxx100011xxxxxxxxxx", InstName.Sqrshrun_S, InstEmit.Sqrshrun_S, OpCodeSimdShImm.Create);
|
||||
SetA64("0x10111100>>>xxx100011xxxxxxxxxx", InstName.Sqrshrun_V, InstEmit.Sqrshrun_V, OpCodeSimdShImm.Create);
|
||||
SetA64("010111110>>>>xxx011101xxxxxxxxxx", InstName.Sqshl_Si, InstEmit.Sqshl_Si, OpCodeSimdShImm.Create);
|
||||
SetA64("0>001110<<1xxxxx010011xxxxxxxxxx", InstName.Sqshl_V, InstEmit.Sqshl_V, OpCodeSimdReg.Create);
|
||||
SetA64("0000111100>>>xxx011101xxxxxxxxxx", InstName.Sqshl_Vi, InstEmit.Sqshl_Vi, OpCodeSimdShImm.Create);
|
||||
SetA64("010011110>>>>xxx011101xxxxxxxxxx", InstName.Sqshl_Vi, InstEmit.Sqshl_Vi, OpCodeSimdShImm.Create);
|
||||
SetA64("0101111100>>>xxx100101xxxxxxxxxx", InstName.Sqshrn_S, InstEmit.Sqshrn_S, OpCodeSimdShImm.Create);
|
||||
SetA64("0x00111100>>>xxx100101xxxxxxxxxx", InstName.Sqshrn_V, InstEmit.Sqshrn_V, OpCodeSimdShImm.Create);
|
||||
SetA64("0111111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_S, InstEmit.Sqshrun_S, OpCodeSimdShImm.Create);
|
||||
@@ -872,6 +875,7 @@ namespace ARMeilleure.Decoders
|
||||
SetVfp("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||
SetVfp("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||
SetVfp("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||
SetVfp("<<<<11101x110110xxxx101x01x0xxxx", InstName.Vrintr, InstEmit32.Vrintr_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||
SetVfp("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||
SetVfp("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||
SetVfp("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create, OpCode32SimdSel.CreateT32);
|
||||
@@ -992,6 +996,7 @@ namespace ARMeilleure.Decoders
|
||||
SetAsimd("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
|
||||
SetAsimd("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||
SetAsimd("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||
SetAsimd("111100111x11<<00xxxx0110xxx0xxxx", InstName.Vpadal, InstEmit32.Vpadal, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||
SetAsimd("111100111x11<<00xxxx0010xxx0xxxx", InstName.Vpaddl, InstEmit32.Vpaddl, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||
SetAsimd("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||
SetAsimd("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||
|
@@ -1115,6 +1115,13 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
public static void Vpadal(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
EmitVectorPairwiseTernaryLongOpI32(context, (op1, op2, op3) => context.Add(context.Add(op1, op2), op3), op.Opc != 1);
|
||||
}
|
||||
|
||||
public static void Vpaddl(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
@@ -578,6 +578,22 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
// VRINTR (floating-point).
|
||||
public static void Vrintr_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, Intrinsic.Arm64FrintiS);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarUnaryOpF32(context, (op1) =>
|
||||
{
|
||||
return EmitRoundByRMode(context, op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// VRINTZ (floating-point).
|
||||
public static void Vrint_Z(ArmEmitterContext context)
|
||||
{
|
||||
|
@@ -673,6 +673,35 @@ namespace ARMeilleure.Instructions
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
|
||||
public static void EmitVectorPairwiseTernaryLongOpI32(ArmEmitterContext context, Func3I emit, bool signed)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
int elems = op.GetBytesCount() >> op.Size;
|
||||
int pairs = elems >> 1;
|
||||
|
||||
Operand res = GetVecA32(op.Qd);
|
||||
|
||||
for (int index = 0; index < pairs; index++)
|
||||
{
|
||||
int pairIndex = index * 2;
|
||||
Operand m1 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex, op.Size, signed);
|
||||
Operand m2 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex + 1, op.Size, signed);
|
||||
|
||||
if (op.Size == 2)
|
||||
{
|
||||
m1 = signed ? context.SignExtend32(OperandType.I64, m1) : context.ZeroExtend32(OperandType.I64, m1);
|
||||
m2 = signed ? context.SignExtend32(OperandType.I64, m2) : context.ZeroExtend32(OperandType.I64, m2);
|
||||
}
|
||||
|
||||
Operand d1 = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size + 1, signed);
|
||||
|
||||
res = EmitVectorInsert(context, res, emit(m1, m2, d1), op.Id + index, op.Size + 1);
|
||||
}
|
||||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
|
||||
// Narrow
|
||||
|
||||
public static void EmitVectorUnaryNarrowOp32(ArmEmitterContext context, Func1I emit, bool signed = false)
|
||||
|
@@ -116,7 +116,7 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
else if (shift >= eSize)
|
||||
{
|
||||
if ((op.RegisterSize == RegisterSize.Simd64))
|
||||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
Operand res = context.VectorZeroUpper64(GetVec(op.Rd));
|
||||
|
||||
@@ -359,6 +359,16 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqshl_Si(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlImmOp(context, signedDst: true, ShlRegFlags.Signed | ShlRegFlags.Scalar | ShlRegFlags.Saturating);
|
||||
}
|
||||
|
||||
public static void Sqshl_Vi(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlImmOp(context, signedDst: true, ShlRegFlags.Signed | ShlRegFlags.Saturating);
|
||||
}
|
||||
|
||||
public static void Sqshrn_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseAdvSimd)
|
||||
@@ -1593,6 +1603,99 @@ namespace ARMeilleure.Instructions
|
||||
Saturating = 1 << 3,
|
||||
}
|
||||
|
||||
private static void EmitShlImmOp(ArmEmitterContext context, bool signedDst, ShlRegFlags flags = ShlRegFlags.None)
|
||||
{
|
||||
bool scalar = flags.HasFlag(ShlRegFlags.Scalar);
|
||||
bool signed = flags.HasFlag(ShlRegFlags.Signed);
|
||||
bool saturating = flags.HasFlag(ShlRegFlags.Saturating);
|
||||
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
Operand res = context.VectorZero();
|
||||
|
||||
int elems = !scalar ? op.GetBytesCount() >> op.Size : 1;
|
||||
|
||||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size, signed);
|
||||
|
||||
Operand e = !saturating
|
||||
? EmitShlImm(context, ne, GetImmShl(op), op.Size)
|
||||
: EmitShlImmSatQ(context, ne, GetImmShl(op), op.Size, signed, signedDst);
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
||||
private static Operand EmitShlImm(ArmEmitterContext context, Operand op, int shiftLsB, int size)
|
||||
{
|
||||
int eSize = 8 << size;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
|
||||
Operand res = context.AllocateLocal(OperandType.I64);
|
||||
|
||||
if (shiftLsB >= eSize)
|
||||
{
|
||||
Operand shl = context.ShiftLeft(op, Const(shiftLsB));
|
||||
context.Copy(res, shl);
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand zeroL = Const(0L);
|
||||
context.Copy(res, zeroL);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static Operand EmitShlImmSatQ(ArmEmitterContext context, Operand op, int shiftLsB, int size, bool signedSrc, bool signedDst)
|
||||
{
|
||||
int eSize = 8 << size;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
|
||||
Operand lblEnd = Label();
|
||||
|
||||
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
|
||||
|
||||
if (shiftLsB >= eSize)
|
||||
{
|
||||
context.Copy(res, signedSrc
|
||||
? EmitSignedSignSatQ(context, op, size)
|
||||
: EmitUnsignedSignSatQ(context, op, size));
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand shl = context.ShiftLeft(op, Const(shiftLsB));
|
||||
if (eSize == 64)
|
||||
{
|
||||
Operand sarOrShr = signedSrc
|
||||
? context.ShiftRightSI(shl, Const(shiftLsB))
|
||||
: context.ShiftRightUI(shl, Const(shiftLsB));
|
||||
context.Copy(res, shl);
|
||||
context.BranchIf(lblEnd, sarOrShr, op, Comparison.Equal);
|
||||
context.Copy(res, signedSrc
|
||||
? EmitSignedSignSatQ(context, op, size)
|
||||
: EmitUnsignedSignSatQ(context, op, size));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Copy(res, signedSrc
|
||||
? EmitSignedSrcSatQ(context, shl, size, signedDst)
|
||||
: EmitUnsignedSrcSatQ(context, shl, size, signedDst));
|
||||
}
|
||||
}
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static void EmitShlRegOp(ArmEmitterContext context, ShlRegFlags flags = ShlRegFlags.None)
|
||||
{
|
||||
bool scalar = flags.HasFlag(ShlRegFlags.Scalar);
|
||||
|
@@ -384,7 +384,9 @@ namespace ARMeilleure.Instructions
|
||||
Sqrshrn_V,
|
||||
Sqrshrun_S,
|
||||
Sqrshrun_V,
|
||||
Sqshl_Si,
|
||||
Sqshl_V,
|
||||
Sqshl_Vi,
|
||||
Sqshrn_S,
|
||||
Sqshrn_V,
|
||||
Sqshrun_S,
|
||||
@@ -635,6 +637,7 @@ namespace ARMeilleure.Instructions
|
||||
Vorn,
|
||||
Vorr,
|
||||
Vpadd,
|
||||
Vpadal,
|
||||
Vpaddl,
|
||||
Vpmax,
|
||||
Vpmin,
|
||||
@@ -654,6 +657,7 @@ namespace ARMeilleure.Instructions
|
||||
Vrintm,
|
||||
Vrintn,
|
||||
Vrintp,
|
||||
Vrintr,
|
||||
Vrintx,
|
||||
Vrshr,
|
||||
Vrshrn,
|
||||
|
@@ -4,7 +4,5 @@ namespace ARMeilleure.Memory
|
||||
{
|
||||
IJitMemoryBlock Allocate(ulong size);
|
||||
IJitMemoryBlock Reserve(ulong size);
|
||||
|
||||
ulong GetPageSize();
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ namespace ARMeilleure.Memory
|
||||
|
||||
void Commit(ulong offset, ulong size);
|
||||
|
||||
void MapAsRw(ulong offset, ulong size);
|
||||
void MapAsRx(ulong offset, ulong size);
|
||||
void MapAsRwx(ulong offset, ulong size);
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ namespace ARMeilleure.Memory
|
||||
HostMappedUnsafe,
|
||||
}
|
||||
|
||||
static class MemoryManagerTypeExtensions
|
||||
public static class MemoryManagerTypeExtensions
|
||||
{
|
||||
public static bool IsHostMapped(this MemoryManagerType type)
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace ARMeilleure.Memory
|
||||
{
|
||||
class ReservedRegion
|
||||
public class ReservedRegion
|
||||
{
|
||||
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.
|
||||
|
||||
|
@@ -5,7 +5,7 @@ using System.Runtime.Versioning;
|
||||
namespace ARMeilleure.Native
|
||||
{
|
||||
[SupportedOSPlatform("macos")]
|
||||
internal static partial class JitSupportDarwin
|
||||
static partial class JitSupportDarwin
|
||||
{
|
||||
[LibraryImport("libarmeilleure-jitsupport", EntryPoint = "armeilleure_jit_memcpy")]
|
||||
public static partial void Copy(IntPtr dst, IntPtr src, ulong n);
|
||||
|
@@ -1,63 +1,14 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.Translation;
|
||||
using ARMeilleure.Translation.Cache;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.Signal
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct SignalHandlerRange
|
||||
public static class NativeSignalHandlerGenerator
|
||||
{
|
||||
public int IsActive;
|
||||
public nuint RangeAddress;
|
||||
public nuint RangeEndAddress;
|
||||
public IntPtr ActionPointer;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct SignalHandlerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// The byte offset of the faulting address in the SigInfo or ExceptionRecord struct.
|
||||
/// </summary>
|
||||
public int StructAddressOffset;
|
||||
|
||||
/// <summary>
|
||||
/// The byte offset of the write flag in the SigInfo or ExceptionRecord struct.
|
||||
/// </summary>
|
||||
public int StructWriteOffset;
|
||||
|
||||
/// <summary>
|
||||
/// The sigaction handler that was registered before this one. (unix only)
|
||||
/// </summary>
|
||||
public nuint UnixOldSigaction;
|
||||
|
||||
/// <summary>
|
||||
/// The type of the previous sigaction. True for the 3 argument variant. (unix only)
|
||||
/// </summary>
|
||||
public int UnixOldSigaction3Arg;
|
||||
|
||||
public SignalHandlerRange Range0;
|
||||
public SignalHandlerRange Range1;
|
||||
public SignalHandlerRange Range2;
|
||||
public SignalHandlerRange Range3;
|
||||
public SignalHandlerRange Range4;
|
||||
public SignalHandlerRange Range5;
|
||||
public SignalHandlerRange Range6;
|
||||
public SignalHandlerRange Range7;
|
||||
}
|
||||
|
||||
public static class NativeSignalHandler
|
||||
{
|
||||
private delegate void UnixExceptionHandler(int sig, IntPtr info, IntPtr ucontext);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
private delegate int VectoredExceptionHandler(IntPtr exceptionInfo);
|
||||
|
||||
private const int MaxTrackedRanges = 8;
|
||||
public const int MaxTrackedRanges = 8;
|
||||
|
||||
private const int StructAddressOffset = 0;
|
||||
private const int StructWriteOffset = 4;
|
||||
@@ -70,125 +21,10 @@ namespace ARMeilleure.Signal
|
||||
|
||||
private const uint EXCEPTION_ACCESS_VIOLATION = 0xc0000005;
|
||||
|
||||
private static ulong _pageSize;
|
||||
private static ulong _pageMask;
|
||||
|
||||
private static readonly IntPtr _handlerConfig;
|
||||
private static IntPtr _signalHandlerPtr;
|
||||
private static IntPtr _signalHandlerHandle;
|
||||
|
||||
private static readonly object _lock = new();
|
||||
private static bool _initialized;
|
||||
|
||||
static NativeSignalHandler()
|
||||
private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite, int rangeStructSize, ulong pageSize)
|
||||
{
|
||||
_handlerConfig = Marshal.AllocHGlobal(Unsafe.SizeOf<SignalHandlerConfig>());
|
||||
ref SignalHandlerConfig config = ref GetConfigRef();
|
||||
ulong pageMask = pageSize - 1;
|
||||
|
||||
config = new SignalHandlerConfig();
|
||||
}
|
||||
|
||||
public static void Initialize(IJitMemoryAllocator allocator)
|
||||
{
|
||||
JitCache.Initialize(allocator);
|
||||
}
|
||||
|
||||
public static void InitializeSignalHandler(ulong pageSize, Func<IntPtr, IntPtr, IntPtr> customSignalHandlerFactory = null)
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_pageSize = pageSize;
|
||||
_pageMask = pageSize - 1;
|
||||
|
||||
ref SignalHandlerConfig config = ref GetConfigRef();
|
||||
|
||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
{
|
||||
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateUnixSignalHandler(_handlerConfig));
|
||||
|
||||
if (customSignalHandlerFactory != null)
|
||||
{
|
||||
_signalHandlerPtr = customSignalHandlerFactory(UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr);
|
||||
}
|
||||
|
||||
var old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
|
||||
|
||||
config.UnixOldSigaction = (nuint)(ulong)old.sa_handler;
|
||||
config.UnixOldSigaction3Arg = old.sa_flags & 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.StructAddressOffset = 40; // ExceptionInformation1
|
||||
config.StructWriteOffset = 32; // ExceptionInformation0
|
||||
|
||||
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateWindowsSignalHandler(_handlerConfig));
|
||||
|
||||
if (customSignalHandlerFactory != null)
|
||||
{
|
||||
_signalHandlerPtr = customSignalHandlerFactory(IntPtr.Zero, _signalHandlerPtr);
|
||||
}
|
||||
|
||||
_signalHandlerHandle = WindowsSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe ref SignalHandlerConfig GetConfigRef()
|
||||
{
|
||||
return ref Unsafe.AsRef<SignalHandlerConfig>((void*)_handlerConfig);
|
||||
}
|
||||
|
||||
public static unsafe bool AddTrackedRegion(nuint address, nuint endAddress, IntPtr action)
|
||||
{
|
||||
var ranges = &((SignalHandlerConfig*)_handlerConfig)->Range0;
|
||||
|
||||
for (int i = 0; i < MaxTrackedRanges; i++)
|
||||
{
|
||||
if (ranges[i].IsActive == 0)
|
||||
{
|
||||
ranges[i].RangeAddress = address;
|
||||
ranges[i].RangeEndAddress = endAddress;
|
||||
ranges[i].ActionPointer = action;
|
||||
ranges[i].IsActive = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static unsafe bool RemoveTrackedRegion(nuint address)
|
||||
{
|
||||
var ranges = &((SignalHandlerConfig*)_handlerConfig)->Range0;
|
||||
|
||||
for (int i = 0; i < MaxTrackedRanges; i++)
|
||||
{
|
||||
if (ranges[i].IsActive == 1 && ranges[i].RangeAddress == address)
|
||||
{
|
||||
ranges[i].IsActive = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite)
|
||||
{
|
||||
Operand inRegionLocal = context.AllocateLocal(OperandType.I32);
|
||||
context.Copy(inRegionLocal, Const(0));
|
||||
|
||||
@@ -196,7 +32,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
for (int i = 0; i < MaxTrackedRanges; i++)
|
||||
{
|
||||
ulong rangeBaseOffset = (ulong)(RangeOffset + i * Unsafe.SizeOf<SignalHandlerRange>());
|
||||
ulong rangeBaseOffset = (ulong)(RangeOffset + i * rangeStructSize);
|
||||
|
||||
Operand nextLabel = Label();
|
||||
|
||||
@@ -210,13 +46,12 @@ namespace ARMeilleure.Signal
|
||||
// Is the fault address within this tracked region?
|
||||
Operand inRange = context.BitwiseAnd(
|
||||
context.ICompare(faultAddress, rangeAddress, Comparison.GreaterOrEqualUI),
|
||||
context.ICompare(faultAddress, rangeEndAddress, Comparison.LessUI)
|
||||
);
|
||||
context.ICompare(faultAddress, rangeEndAddress, Comparison.LessUI));
|
||||
|
||||
// Only call tracking if in range.
|
||||
context.BranchIfFalse(nextLabel, inRange, BasicBlockFrequency.Cold);
|
||||
|
||||
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~_pageMask));
|
||||
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~pageMask));
|
||||
|
||||
// Call the tracking action, with the pointer's relative offset to the base address.
|
||||
Operand trackingActionPtr = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 20));
|
||||
@@ -227,7 +62,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
// Tracking action should be non-null to call it, otherwise assume false return.
|
||||
context.BranchIfFalse(skipActionLabel, trackingActionPtr);
|
||||
Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(_pageSize), isWrite);
|
||||
Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(pageSize), isWrite);
|
||||
context.Copy(inRegionLocal, result);
|
||||
|
||||
context.MarkLabel(skipActionLabel);
|
||||
@@ -269,8 +104,7 @@ namespace ARMeilleure.Signal
|
||||
Operand esr = context.Load(OperandType.I64, context.Add(ctxPtr, Const(EsrOffset)));
|
||||
return context.BitwiseAnd(esr, Const(0x40ul));
|
||||
}
|
||||
|
||||
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
||||
else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
||||
{
|
||||
const ulong ErrOffset = 4; // __es.__err
|
||||
Operand err = context.Load(OperandType.I64, context.Add(ctxPtr, Const(ErrOffset)));
|
||||
@@ -310,8 +144,7 @@ namespace ARMeilleure.Signal
|
||||
Operand esr = context.Load(OperandType.I64, context.Add(auxPtr, Const(8ul)));
|
||||
return context.BitwiseAnd(esr, Const(0x40ul));
|
||||
}
|
||||
|
||||
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
||||
else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
||||
{
|
||||
const int ErrOffset = 192; // uc_mcontext.gregs[REG_ERR]
|
||||
Operand err = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(ErrOffset)));
|
||||
@@ -322,7 +155,7 @@ namespace ARMeilleure.Signal
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
private static UnixExceptionHandler GenerateUnixSignalHandler(IntPtr signalStructPtr)
|
||||
public static byte[] GenerateUnixSignalHandler(IntPtr signalStructPtr, int rangeStructSize, ulong pageSize)
|
||||
{
|
||||
EmitterContext context = new();
|
||||
|
||||
@@ -335,7 +168,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.
|
||||
|
||||
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite);
|
||||
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite, rangeStructSize, pageSize);
|
||||
|
||||
Operand endLabel = Label();
|
||||
|
||||
@@ -367,10 +200,10 @@ namespace ARMeilleure.Signal
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I32, OperandType.I64, OperandType.I64 };
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<UnixExceptionHandler>();
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
|
||||
}
|
||||
|
||||
private static VectoredExceptionHandler GenerateWindowsSignalHandler(IntPtr signalStructPtr)
|
||||
public static byte[] GenerateWindowsSignalHandler(IntPtr signalStructPtr, int rangeStructSize, ulong pageSize)
|
||||
{
|
||||
EmitterContext context = new();
|
||||
|
||||
@@ -399,7 +232,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.
|
||||
|
||||
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite);
|
||||
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite, rangeStructSize, pageSize);
|
||||
|
||||
Operand endLabel = Label();
|
||||
|
||||
@@ -421,7 +254,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<VectoredExceptionHandler>();
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@ using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using Ryujinx.Common.Memory.PartialUnmaps;
|
||||
using System;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.Signal
|
||||
@@ -10,8 +10,28 @@ namespace ARMeilleure.Signal
|
||||
/// <summary>
|
||||
/// Methods to handle signals caused by partial unmaps. See the structs for C# implementations of the methods.
|
||||
/// </summary>
|
||||
internal static class WindowsPartialUnmapHandler
|
||||
internal static partial class WindowsPartialUnmapHandler
|
||||
{
|
||||
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
|
||||
private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
|
||||
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
|
||||
|
||||
private static IntPtr _getCurrentThreadIdPtr;
|
||||
|
||||
public static IntPtr GetCurrentThreadIdFunc()
|
||||
{
|
||||
if (_getCurrentThreadIdPtr == IntPtr.Zero)
|
||||
{
|
||||
IntPtr handle = LoadLibrary("kernel32.dll");
|
||||
|
||||
_getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
|
||||
}
|
||||
|
||||
return _getCurrentThreadIdPtr;
|
||||
}
|
||||
|
||||
public static Operand EmitRetryFromAccessViolation(EmitterContext context)
|
||||
{
|
||||
IntPtr partialRemapStatePtr = PartialUnmapState.GlobalState;
|
||||
@@ -20,7 +40,7 @@ namespace ARMeilleure.Signal
|
||||
// Get the lock first.
|
||||
EmitNativeReaderLockAcquire(context, IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
|
||||
|
||||
IntPtr getCurrentThreadId = WindowsSignalHandlerRegistration.GetCurrentThreadIdFunc();
|
||||
IntPtr getCurrentThreadId = GetCurrentThreadIdFunc();
|
||||
Operand threadId = context.Call(Const((ulong)getCurrentThreadId), OperandType.I32);
|
||||
Operand threadIndex = EmitThreadLocalMapIntGetOrReserve(context, localCountsPtr, threadId, Const(0));
|
||||
|
||||
@@ -137,17 +157,6 @@ namespace ARMeilleure.Signal
|
||||
return context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset));
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0051 // Remove unused private member
|
||||
private static void EmitThreadLocalMapIntRelease(EmitterContext context, IntPtr threadLocalMapPtr, Operand threadId, Operand index)
|
||||
{
|
||||
Operand offset = context.Multiply(index, Const(sizeof(int)));
|
||||
Operand idsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.ThreadIdsOffset));
|
||||
Operand idPtr = context.Add(idsPtr, context.SignExtend32(OperandType.I64, offset));
|
||||
|
||||
context.CompareAndSwap(idPtr, threadId, Const(0));
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
|
||||
private static void EmitAtomicAddI32(EmitterContext context, Operand ptr, Operand additive)
|
||||
{
|
||||
Operand loop = Label();
|
||||
|
@@ -1,44 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Signal
|
||||
{
|
||||
unsafe partial class WindowsSignalHandlerRegistration
|
||||
{
|
||||
[LibraryImport("kernel32.dll")]
|
||||
private static partial IntPtr AddVectoredExceptionHandler(uint first, IntPtr handler);
|
||||
|
||||
[LibraryImport("kernel32.dll")]
|
||||
private static partial ulong RemoveVectoredExceptionHandler(IntPtr handle);
|
||||
|
||||
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
|
||||
private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
|
||||
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
|
||||
|
||||
private static IntPtr _getCurrentThreadIdPtr;
|
||||
|
||||
public static IntPtr RegisterExceptionHandler(IntPtr action)
|
||||
{
|
||||
return AddVectoredExceptionHandler(1, action);
|
||||
}
|
||||
|
||||
public static bool RemoveExceptionHandler(IntPtr handle)
|
||||
{
|
||||
return RemoveVectoredExceptionHandler(handle) != 0;
|
||||
}
|
||||
|
||||
public static IntPtr GetCurrentThreadIdFunc()
|
||||
{
|
||||
if (_getCurrentThreadIdPtr == IntPtr.Zero)
|
||||
{
|
||||
IntPtr handle = LoadLibrary("kernel32.dll");
|
||||
|
||||
_getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
|
||||
}
|
||||
|
||||
return _getCurrentThreadIdPtr;
|
||||
}
|
||||
}
|
||||
}
|
@@ -8,7 +8,7 @@ namespace ARMeilleure.Translation
|
||||
/// </summary>
|
||||
/// <typeparam name="TK">Key</typeparam>
|
||||
/// <typeparam name="TV">Value</typeparam>
|
||||
class IntervalTree<TK, TV> where TK : IComparable<TK>
|
||||
public class IntervalTree<TK, TV> where TK : IComparable<TK>
|
||||
{
|
||||
private const int ArrayGrowthSize = 32;
|
||||
|
||||
|
@@ -57,9 +57,6 @@ namespace ARMeilleure.Translation
|
||||
private Thread[] _backgroundTranslationThreads;
|
||||
private volatile int _threadCount;
|
||||
|
||||
// FIXME: Remove this once the init logic of the emulator will be redone.
|
||||
public static readonly ManualResetEvent IsReadyForTranslation = new(false);
|
||||
|
||||
public Translator(IJitMemoryAllocator allocator, IMemoryManager memory, bool for64Bits)
|
||||
{
|
||||
_allocator = allocator;
|
||||
@@ -76,14 +73,9 @@ namespace ARMeilleure.Translation
|
||||
CountTable = new EntryTable<uint>();
|
||||
Functions = new TranslatorCache<TranslatedFunction>();
|
||||
FunctionTable = new AddressTable<ulong>(for64Bits ? _levels64Bit : _levels32Bit);
|
||||
Stubs = new TranslatorStubs(this);
|
||||
Stubs = new TranslatorStubs(FunctionTable);
|
||||
|
||||
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
|
||||
|
||||
if (memory.Type.IsHostMapped())
|
||||
{
|
||||
NativeSignalHandler.InitializeSignalHandler(allocator.GetPageSize());
|
||||
}
|
||||
}
|
||||
|
||||
public IPtcLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled)
|
||||
@@ -105,8 +97,6 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
if (Interlocked.Increment(ref _threadCount) == 1)
|
||||
{
|
||||
IsReadyForTranslation.WaitOne();
|
||||
|
||||
if (_ptc.State == PtcState.Enabled)
|
||||
{
|
||||
Debug.Assert(Functions.Count == 0);
|
||||
|
@@ -1,3 +1,4 @@
|
||||
using ARMeilleure.Common;
|
||||
using ARMeilleure.Instructions;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
@@ -14,11 +15,11 @@ namespace ARMeilleure.Translation
|
||||
/// </summary>
|
||||
class TranslatorStubs : IDisposable
|
||||
{
|
||||
private static readonly Lazy<IntPtr> _slowDispatchStub = new(GenerateSlowDispatchStub, isThreadSafe: true);
|
||||
private readonly Lazy<IntPtr> _slowDispatchStub;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
private readonly Translator _translator;
|
||||
private readonly AddressTable<ulong> _functionTable;
|
||||
private readonly Lazy<IntPtr> _dispatchStub;
|
||||
private readonly Lazy<DispatcherFunction> _dispatchLoop;
|
||||
private readonly Lazy<WrapperFunction> _contextWrapper;
|
||||
@@ -83,13 +84,14 @@ namespace ARMeilleure.Translation
|
||||
/// Initializes a new instance of the <see cref="TranslatorStubs"/> class with the specified
|
||||
/// <see cref="Translator"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="translator"><see cref="Translator"/> instance to use</param>
|
||||
/// <param name="functionTable">Function table used to store pointers to the functions that the guest code will call</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
|
||||
public TranslatorStubs(Translator translator)
|
||||
public TranslatorStubs(AddressTable<ulong> functionTable)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(translator);
|
||||
ArgumentNullException.ThrowIfNull(functionTable);
|
||||
|
||||
_translator = translator;
|
||||
_functionTable = functionTable;
|
||||
_slowDispatchStub = new(GenerateSlowDispatchStub, isThreadSafe: true);
|
||||
_dispatchStub = new(GenerateDispatchStub, isThreadSafe: true);
|
||||
_dispatchLoop = new(GenerateDispatchLoop, isThreadSafe: true);
|
||||
_contextWrapper = new(GenerateContextWrapper, isThreadSafe: true);
|
||||
@@ -151,15 +153,15 @@ namespace ARMeilleure.Translation
|
||||
context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset())));
|
||||
|
||||
// Check if guest address is within range of the AddressTable.
|
||||
Operand masked = context.BitwiseAnd(guestAddress, Const(~_translator.FunctionTable.Mask));
|
||||
Operand masked = context.BitwiseAnd(guestAddress, Const(~_functionTable.Mask));
|
||||
context.BranchIfTrue(lblFallback, masked);
|
||||
|
||||
Operand index = default;
|
||||
Operand page = Const((long)_translator.FunctionTable.Base);
|
||||
Operand page = Const((long)_functionTable.Base);
|
||||
|
||||
for (int i = 0; i < _translator.FunctionTable.Levels.Length; i++)
|
||||
for (int i = 0; i < _functionTable.Levels.Length; i++)
|
||||
{
|
||||
ref var level = ref _translator.FunctionTable.Levels[i];
|
||||
ref var level = ref _functionTable.Levels[i];
|
||||
|
||||
// level.Mask is not used directly because it is more often bigger than 32-bits, so it will not
|
||||
// be encoded as an immediate on x86's bitwise and operation.
|
||||
@@ -167,7 +169,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
index = context.BitwiseAnd(context.ShiftRightUI(guestAddress, Const(level.Index)), mask);
|
||||
|
||||
if (i < _translator.FunctionTable.Levels.Length - 1)
|
||||
if (i < _functionTable.Levels.Length - 1)
|
||||
{
|
||||
page = context.Load(OperandType.I64, context.Add(page, context.ShiftLeft(index, Const(3))));
|
||||
context.BranchIfFalse(lblFallback, page);
|
||||
@@ -196,7 +198,7 @@ namespace ARMeilleure.Translation
|
||||
/// Generates a <see cref="SlowDispatchStub"/>.
|
||||
/// </summary>
|
||||
/// <returns>Generated <see cref="SlowDispatchStub"/></returns>
|
||||
private static IntPtr GenerateSlowDispatchStub()
|
||||
private IntPtr GenerateSlowDispatchStub()
|
||||
{
|
||||
var context = new EmitterContext();
|
||||
|
||||
@@ -205,8 +207,7 @@ namespace ARMeilleure.Translation
|
||||
Operand guestAddress = context.Load(OperandType.I64,
|
||||
context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset())));
|
||||
|
||||
MethodInfo getFuncAddress = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress));
|
||||
Operand hostAddress = context.Call(getFuncAddress, guestAddress);
|
||||
Operand hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
|
||||
context.Tailcall(hostAddress, nativeContext);
|
||||
|
||||
var cfg = context.GetControlFlowGraph();
|
||||
|
@@ -20,6 +20,25 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||
private bool _stillRunning;
|
||||
private readonly Thread _updaterThread;
|
||||
|
||||
private float _volume;
|
||||
|
||||
public float Volume
|
||||
{
|
||||
get
|
||||
{
|
||||
return _volume;
|
||||
}
|
||||
set
|
||||
{
|
||||
_volume = value;
|
||||
|
||||
foreach (OpenALHardwareDeviceSession session in _sessions.Keys)
|
||||
{
|
||||
session.UpdateMasterVolume(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public OpenALHardwareDeviceDriver()
|
||||
{
|
||||
_device = ALC.OpenDevice("");
|
||||
@@ -34,6 +53,8 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||
Name = "HardwareDeviceDriver.OpenAL",
|
||||
};
|
||||
|
||||
_volume = 1f;
|
||||
|
||||
_updaterThread.Start();
|
||||
}
|
||||
|
||||
@@ -52,7 +73,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||
}
|
||||
}
|
||||
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
||||
{
|
||||
if (channelCount == 0)
|
||||
{
|
||||
@@ -73,7 +94,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||
throw new ArgumentException($"{channelCount}");
|
||||
}
|
||||
|
||||
OpenALHardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount, volume);
|
||||
OpenALHardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount);
|
||||
|
||||
_sessions.TryAdd(session, 0);
|
||||
|
||||
|
@@ -16,10 +16,11 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||
private bool _isActive;
|
||||
private readonly Queue<OpenALAudioBuffer> _queuedBuffers;
|
||||
private ulong _playedSampleCount;
|
||||
private float _volume;
|
||||
|
||||
private readonly object _lock = new();
|
||||
|
||||
public OpenALHardwareDeviceSession(OpenALHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, float requestedVolume) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||
public OpenALHardwareDeviceSession(OpenALHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||
{
|
||||
_driver = driver;
|
||||
_queuedBuffers = new Queue<OpenALAudioBuffer>();
|
||||
@@ -27,7 +28,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||
_targetFormat = GetALFormat();
|
||||
_isActive = false;
|
||||
_playedSampleCount = 0;
|
||||
SetVolume(requestedVolume);
|
||||
SetVolume(1f);
|
||||
}
|
||||
|
||||
private ALFormat GetALFormat()
|
||||
@@ -85,17 +86,22 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||
|
||||
public override void SetVolume(float volume)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
AL.Source(_sourceId, ALSourcef.Gain, volume);
|
||||
}
|
||||
_volume = volume;
|
||||
|
||||
UpdateMasterVolume(_driver.Volume);
|
||||
}
|
||||
|
||||
public override float GetVolume()
|
||||
{
|
||||
AL.GetSource(_sourceId, ALSourcef.Gain, out float volume);
|
||||
return _volume;
|
||||
}
|
||||
|
||||
return volume;
|
||||
public void UpdateMasterVolume(float newVolume)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
AL.Source(_sourceId, ALSourcef.Gain, newVolume * _volume);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
|
@@ -20,6 +20,8 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
|
||||
private readonly bool _supportSurroundConfiguration;
|
||||
|
||||
public float Volume { get; set; }
|
||||
|
||||
// TODO: Add this to SDL2-CS
|
||||
// NOTE: We use a DllImport here because of marshaling issue for spec.
|
||||
#pragma warning disable SYSLIB1054
|
||||
@@ -48,6 +50,8 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
{
|
||||
_supportSurroundConfiguration = spec.channels >= 6;
|
||||
}
|
||||
|
||||
Volume = 1f;
|
||||
}
|
||||
|
||||
public static bool IsSupported => IsSupportedInternal();
|
||||
@@ -74,7 +78,7 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
return _pauseEvent;
|
||||
}
|
||||
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
||||
{
|
||||
if (channelCount == 0)
|
||||
{
|
||||
@@ -91,7 +95,7 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
throw new NotImplementedException("Input direction is currently not implemented on SDL2 backend!");
|
||||
}
|
||||
|
||||
SDL2HardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount, volume);
|
||||
SDL2HardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount);
|
||||
|
||||
_sessions.TryAdd(session, 0);
|
||||
|
||||
|
@@ -26,7 +26,7 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
private float _volume;
|
||||
private readonly ushort _nativeSampleFormat;
|
||||
|
||||
public SDL2HardwareDeviceSession(SDL2HardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, float requestedVolume) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||
public SDL2HardwareDeviceSession(SDL2HardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||
{
|
||||
_driver = driver;
|
||||
_updateRequiredEvent = _driver.GetUpdateRequiredEvent();
|
||||
@@ -37,7 +37,7 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
_nativeSampleFormat = SDL2HardwareDeviceDriver.GetSDL2Format(RequestedSampleFormat);
|
||||
_sampleCount = uint.MaxValue;
|
||||
_started = false;
|
||||
_volume = requestedVolume;
|
||||
_volume = 1f;
|
||||
}
|
||||
|
||||
private void EnsureAudioStreamSetup(AudioBuffer buffer)
|
||||
@@ -99,7 +99,7 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
streamSpan.Clear();
|
||||
|
||||
// Apply volume to written data
|
||||
SDL_MixAudioFormat(stream, pStreamSrc, _nativeSampleFormat, (uint)samples.Length, (int)(_volume * SDL_MIX_MAXVOLUME));
|
||||
SDL_MixAudioFormat(stream, pStreamSrc, _nativeSampleFormat, (uint)samples.Length, (int)(_driver.Volume * _volume * SDL_MIX_MAXVOLUME));
|
||||
}
|
||||
|
||||
ulong sampleCount = GetSampleCount(samples.Length);
|
||||
|
@@ -11,15 +11,15 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dll" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dll" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>libsoundio.dll</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win-x64'">
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.dylib" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>libsoundio.dylib</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||
<ContentWithTargetPath Include="Native\libsoundio\libs\libsoundio.so" Condition="'$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>libsoundio.so</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
|
@@ -19,6 +19,25 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||
private readonly ConcurrentDictionary<SoundIoHardwareDeviceSession, byte> _sessions;
|
||||
private int _disposeState;
|
||||
|
||||
private float _volume = 1f;
|
||||
|
||||
public float Volume
|
||||
{
|
||||
get
|
||||
{
|
||||
return _volume;
|
||||
}
|
||||
set
|
||||
{
|
||||
_volume = value;
|
||||
|
||||
foreach (SoundIoHardwareDeviceSession session in _sessions.Keys)
|
||||
{
|
||||
session.UpdateMasterVolume(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SoundIoHardwareDeviceDriver()
|
||||
{
|
||||
_audioContext = SoundIoContext.Create();
|
||||
@@ -122,7 +141,7 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||
return _pauseEvent;
|
||||
}
|
||||
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
||||
{
|
||||
if (channelCount == 0)
|
||||
{
|
||||
@@ -134,14 +153,12 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||
sampleRate = Constants.TargetSampleRate;
|
||||
}
|
||||
|
||||
volume = Math.Clamp(volume, 0, 1);
|
||||
|
||||
if (direction != Direction.Output)
|
||||
{
|
||||
throw new NotImplementedException("Input direction is currently not implemented on SoundIO backend!");
|
||||
}
|
||||
|
||||
SoundIoHardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount, volume);
|
||||
SoundIoHardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount);
|
||||
|
||||
_sessions.TryAdd(session, 0);
|
||||
|
||||
|
@@ -18,16 +18,18 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||
private readonly DynamicRingBuffer _ringBuffer;
|
||||
private ulong _playedSampleCount;
|
||||
private readonly ManualResetEvent _updateRequiredEvent;
|
||||
private float _volume;
|
||||
private int _disposeState;
|
||||
|
||||
public SoundIoHardwareDeviceSession(SoundIoHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, float requestedVolume) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||
public SoundIoHardwareDeviceSession(SoundIoHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||
{
|
||||
_driver = driver;
|
||||
_updateRequiredEvent = _driver.GetUpdateRequiredEvent();
|
||||
_queuedBuffers = new ConcurrentQueue<SoundIoAudioBuffer>();
|
||||
_ringBuffer = new DynamicRingBuffer();
|
||||
_volume = 1f;
|
||||
|
||||
SetupOutputStream(requestedVolume);
|
||||
SetupOutputStream(driver.Volume);
|
||||
}
|
||||
|
||||
private void SetupOutputStream(float requestedVolume)
|
||||
@@ -47,7 +49,7 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||
|
||||
public override float GetVolume()
|
||||
{
|
||||
return _outputStream.Volume;
|
||||
return _volume;
|
||||
}
|
||||
|
||||
public override void PrepareToClose() { }
|
||||
@@ -63,7 +65,14 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||
|
||||
public override void SetVolume(float volume)
|
||||
{
|
||||
_outputStream.SetVolume(volume);
|
||||
_volume = volume;
|
||||
|
||||
_outputStream.SetVolume(_driver.Volume * volume);
|
||||
}
|
||||
|
||||
public void UpdateMasterVolume(float newVolume)
|
||||
{
|
||||
_outputStream.SetVolume(newVolume * _volume);
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
|
@@ -16,6 +16,12 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
|
||||
public static bool IsSupported => true;
|
||||
|
||||
public float Volume
|
||||
{
|
||||
get => _realDriver.Volume;
|
||||
set => _realDriver.Volume = value;
|
||||
}
|
||||
|
||||
public CompatLayerHardwareDeviceDriver(IHardwareDeviceDriver realDevice)
|
||||
{
|
||||
_realDriver = realDevice;
|
||||
@@ -90,7 +96,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
throw new ArgumentException("No valid sample format configuration found!");
|
||||
}
|
||||
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
||||
{
|
||||
if (channelCount == 0)
|
||||
{
|
||||
@@ -102,8 +108,6 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
sampleRate = Constants.TargetSampleRate;
|
||||
}
|
||||
|
||||
volume = Math.Clamp(volume, 0, 1);
|
||||
|
||||
if (!_realDriver.SupportsDirection(direction))
|
||||
{
|
||||
if (direction == Direction.Input)
|
||||
@@ -119,7 +123,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
SampleFormat hardwareSampleFormat = SelectHardwareSampleFormat(sampleFormat);
|
||||
uint hardwareChannelCount = SelectHardwareChannelCount(channelCount);
|
||||
|
||||
IHardwareDeviceSession realSession = _realDriver.OpenDeviceSession(direction, memoryManager, hardwareSampleFormat, sampleRate, hardwareChannelCount, volume);
|
||||
IHardwareDeviceSession realSession = _realDriver.OpenDeviceSession(direction, memoryManager, hardwareSampleFormat, sampleRate, hardwareChannelCount);
|
||||
|
||||
if (hardwareChannelCount == channelCount && hardwareSampleFormat == sampleFormat)
|
||||
{
|
||||
|
@@ -31,7 +31,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
private const int Minus6dBInQ15 = (int)(0.501f * RawQ15One);
|
||||
private const int Minus12dBInQ15 = (int)(0.251f * RawQ15One);
|
||||
|
||||
private static readonly int[] _defaultSurroundToStereoCoefficients = new int[4]
|
||||
private static readonly long[] _defaultSurroundToStereoCoefficients = new long[4]
|
||||
{
|
||||
RawQ15One,
|
||||
Minus3dBInQ15,
|
||||
@@ -39,7 +39,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
Minus3dBInQ15,
|
||||
};
|
||||
|
||||
private static readonly int[] _defaultStereoToMonoCoefficients = new int[2]
|
||||
private static readonly long[] _defaultStereoToMonoCoefficients = new long[2]
|
||||
{
|
||||
Minus6dBInQ15,
|
||||
Minus6dBInQ15,
|
||||
@@ -62,19 +62,23 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static short DownMixStereoToMono(ReadOnlySpan<int> coefficients, short left, short right)
|
||||
private static short DownMixStereoToMono(ReadOnlySpan<long> coefficients, short left, short right)
|
||||
{
|
||||
return (short)((left * coefficients[0] + right * coefficients[1]) >> Q15Bits);
|
||||
return (short)Math.Clamp((left * coefficients[0] + right * coefficients[1]) >> Q15Bits, short.MinValue, short.MaxValue);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static short DownMixSurroundToStereo(ReadOnlySpan<int> coefficients, short back, short lfe, short center, short front)
|
||||
private static short DownMixSurroundToStereo(ReadOnlySpan<long> coefficients, short back, short lfe, short center, short front)
|
||||
{
|
||||
return (short)((coefficients[3] * back + coefficients[2] * lfe + coefficients[1] * center + coefficients[0] * front + RawQ15HalfOne) >> Q15Bits);
|
||||
return (short)Math.Clamp(
|
||||
(coefficients[3] * back +
|
||||
coefficients[2] * lfe +
|
||||
coefficients[1] * center +
|
||||
coefficients[0] * front + RawQ15HalfOne) >> Q15Bits, short.MinValue, short.MaxValue);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static short[] DownMixSurroundToStereo(ReadOnlySpan<int> coefficients, ReadOnlySpan<short> data)
|
||||
private static short[] DownMixSurroundToStereo(ReadOnlySpan<long> coefficients, ReadOnlySpan<short> data)
|
||||
{
|
||||
int samplePerChannelCount = data.Length / SurroundChannelCount;
|
||||
|
||||
@@ -94,7 +98,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static short[] DownMixStereoToMono(ReadOnlySpan<int> coefficients, ReadOnlySpan<short> data)
|
||||
private static short[] DownMixStereoToMono(ReadOnlySpan<long> coefficients, ReadOnlySpan<short> data)
|
||||
{
|
||||
int samplePerChannelCount = data.Length / StereoChannelCount;
|
||||
|
||||
|
@@ -14,13 +14,17 @@ namespace Ryujinx.Audio.Backends.Dummy
|
||||
|
||||
public static bool IsSupported => true;
|
||||
|
||||
public float Volume { get; set; }
|
||||
|
||||
public DummyHardwareDeviceDriver()
|
||||
{
|
||||
_updateRequiredEvent = new ManualResetEvent(false);
|
||||
_pauseEvent = new ManualResetEvent(true);
|
||||
|
||||
Volume = 1f;
|
||||
}
|
||||
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
||||
{
|
||||
if (sampleRate == 0)
|
||||
{
|
||||
@@ -34,7 +38,7 @@ namespace Ryujinx.Audio.Backends.Dummy
|
||||
|
||||
if (direction == Direction.Output)
|
||||
{
|
||||
return new DummyHardwareDeviceSessionOutput(this, memoryManager, sampleFormat, sampleRate, channelCount, volume);
|
||||
return new DummyHardwareDeviceSessionOutput(this, memoryManager, sampleFormat, sampleRate, channelCount);
|
||||
}
|
||||
|
||||
return new DummyHardwareDeviceSessionInput(this, memoryManager);
|
||||
|
@@ -13,9 +13,9 @@ namespace Ryujinx.Audio.Backends.Dummy
|
||||
|
||||
private ulong _playedSampleCount;
|
||||
|
||||
public DummyHardwareDeviceSessionOutput(IHardwareDeviceDriver manager, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount, float requestedVolume) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||
public DummyHardwareDeviceSessionOutput(IHardwareDeviceDriver manager, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||
{
|
||||
_volume = requestedVolume;
|
||||
_volume = 1f;
|
||||
_manager = manager;
|
||||
}
|
||||
|
||||
|
@@ -166,7 +166,6 @@ namespace Ryujinx.Audio.Input
|
||||
/// </summary>
|
||||
/// <param name="filtered">If true, filter disconnected devices</param>
|
||||
/// <returns>The list of all audio inputs name</returns>
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public string[] ListAudioIns(bool filtered)
|
||||
{
|
||||
if (filtered)
|
||||
@@ -176,7 +175,6 @@ namespace Ryujinx.Audio.Input
|
||||
|
||||
return new[] { Constants.DefaultDeviceInputName };
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
/// <summary>
|
||||
/// Open a new <see cref="AudioInputSystem"/>.
|
||||
@@ -188,8 +186,6 @@ namespace Ryujinx.Audio.Input
|
||||
/// <param name="inputDeviceName">The input device name wanted by the user</param>
|
||||
/// <param name="sampleFormat">The sample format to use</param>
|
||||
/// <param name="parameter">The user configuration</param>
|
||||
/// <param name="appletResourceUserId">The applet resource user id of the application</param>
|
||||
/// <param name="processHandle">The process handle of the application</param>
|
||||
/// <returns>A <see cref="ResultCode"/> reporting an error or a success</returns>
|
||||
public ResultCode OpenAudioIn(out string outputDeviceName,
|
||||
out AudioOutputConfiguration outputConfiguration,
|
||||
@@ -197,9 +193,7 @@ namespace Ryujinx.Audio.Input
|
||||
IVirtualMemoryManager memoryManager,
|
||||
string inputDeviceName,
|
||||
SampleFormat sampleFormat,
|
||||
ref AudioInputConfiguration parameter,
|
||||
ulong appletResourceUserId,
|
||||
uint processHandle)
|
||||
ref AudioInputConfiguration parameter)
|
||||
{
|
||||
int sessionId = AcquireSessionId();
|
||||
|
||||
|
@@ -13,9 +13,9 @@ namespace Ryujinx.Audio.Integration
|
||||
|
||||
private readonly byte[] _buffer;
|
||||
|
||||
public HardwareDeviceImpl(IHardwareDeviceDriver deviceDriver, uint channelCount, uint sampleRate, float volume)
|
||||
public HardwareDeviceImpl(IHardwareDeviceDriver deviceDriver, uint channelCount, uint sampleRate)
|
||||
{
|
||||
_session = deviceDriver.OpenDeviceSession(IHardwareDeviceDriver.Direction.Output, null, SampleFormat.PcmInt16, sampleRate, channelCount, volume);
|
||||
_session = deviceDriver.OpenDeviceSession(IHardwareDeviceDriver.Direction.Output, null, SampleFormat.PcmInt16, sampleRate, channelCount);
|
||||
_channelCount = channelCount;
|
||||
_sampleRate = sampleRate;
|
||||
_currentBufferTag = 0;
|
||||
|
@@ -16,7 +16,9 @@ namespace Ryujinx.Audio.Integration
|
||||
Output,
|
||||
}
|
||||
|
||||
IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume = 1f);
|
||||
float Volume { get; set; }
|
||||
|
||||
IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount);
|
||||
|
||||
ManualResetEvent GetUpdateRequiredEvent();
|
||||
ManualResetEvent GetPauseEvent();
|
||||
|
@@ -165,12 +165,10 @@ namespace Ryujinx.Audio.Output
|
||||
/// Get the list of all audio outputs name.
|
||||
/// </summary>
|
||||
/// <returns>The list of all audio outputs name</returns>
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public string[] ListAudioOuts()
|
||||
{
|
||||
return new[] { Constants.DefaultDeviceOutputName };
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
/// <summary>
|
||||
/// Open a new <see cref="AudioOutputSystem"/>.
|
||||
@@ -182,9 +180,6 @@ namespace Ryujinx.Audio.Output
|
||||
/// <param name="inputDeviceName">The input device name wanted by the user</param>
|
||||
/// <param name="sampleFormat">The sample format to use</param>
|
||||
/// <param name="parameter">The user configuration</param>
|
||||
/// <param name="appletResourceUserId">The applet resource user id of the application</param>
|
||||
/// <param name="processHandle">The process handle of the application</param>
|
||||
/// <param name="volume">The volume level to request</param>
|
||||
/// <returns>A <see cref="ResultCode"/> reporting an error or a success</returns>
|
||||
public ResultCode OpenAudioOut(out string outputDeviceName,
|
||||
out AudioOutputConfiguration outputConfiguration,
|
||||
@@ -192,16 +187,13 @@ namespace Ryujinx.Audio.Output
|
||||
IVirtualMemoryManager memoryManager,
|
||||
string inputDeviceName,
|
||||
SampleFormat sampleFormat,
|
||||
ref AudioInputConfiguration parameter,
|
||||
ulong appletResourceUserId,
|
||||
uint processHandle,
|
||||
float volume)
|
||||
ref AudioInputConfiguration parameter)
|
||||
{
|
||||
int sessionId = AcquireSessionId();
|
||||
|
||||
_sessionsBufferEvents[sessionId].Clear();
|
||||
|
||||
IHardwareDeviceSession deviceSession = _deviceDriver.OpenDeviceSession(IHardwareDeviceDriver.Direction.Output, memoryManager, sampleFormat, parameter.SampleRate, parameter.ChannelCount, volume);
|
||||
IHardwareDeviceSession deviceSession = _deviceDriver.OpenDeviceSession(IHardwareDeviceDriver.Direction.Output, memoryManager, sampleFormat, parameter.SampleRate, parameter.ChannelCount);
|
||||
|
||||
AudioOutputSystem audioOut = new(this, _lock, deviceSession, _sessionsBufferEvents[sessionId]);
|
||||
|
||||
@@ -234,41 +226,6 @@ namespace Ryujinx.Audio.Output
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the volume for all output devices.
|
||||
/// </summary>
|
||||
/// <param name="volume">The volume to set.</param>
|
||||
public void SetVolume(float volume)
|
||||
{
|
||||
if (_sessions != null)
|
||||
{
|
||||
foreach (AudioOutputSystem session in _sessions)
|
||||
{
|
||||
session?.SetVolume(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the volume for all output devices.
|
||||
/// </summary>
|
||||
/// <returns>A float indicating the volume level.</returns>
|
||||
public float GetVolume()
|
||||
{
|
||||
if (_sessions != null)
|
||||
{
|
||||
foreach (AudioOutputSystem session in _sessions)
|
||||
{
|
||||
if (session != null)
|
||||
{
|
||||
return session.GetVolume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
|
@@ -45,7 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
_event = new ManualResetEvent(false);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0051 // Remove unused private member
|
||||
private static uint GetHardwareChannelCount(IHardwareDeviceDriver deviceDriver)
|
||||
{
|
||||
// Get the real device driver (In case the compat layer is on top of it).
|
||||
@@ -59,9 +58,8 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
// NOTE: We default to stereo as this will get downmixed to mono by the compat layer if it's not compatible.
|
||||
return 2;
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
|
||||
public void Start(IHardwareDeviceDriver deviceDriver, float volume)
|
||||
public void Start(IHardwareDeviceDriver deviceDriver)
|
||||
{
|
||||
OutputDevices = new IHardwareDevice[Constants.AudioRendererSessionCountMax];
|
||||
|
||||
@@ -70,7 +68,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
for (int i = 0; i < OutputDevices.Length; i++)
|
||||
{
|
||||
// TODO: Don't hardcode sample rate.
|
||||
OutputDevices[i] = new HardwareDeviceImpl(deviceDriver, channelCount, Constants.TargetSampleRate, volume);
|
||||
OutputDevices[i] = new HardwareDeviceImpl(deviceDriver, channelCount, Constants.TargetSampleRate);
|
||||
}
|
||||
|
||||
_mailbox = new Mailbox<MailboxMessage>();
|
||||
@@ -231,33 +229,6 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
_mailbox.SendResponse(MailboxMessage.Stop);
|
||||
}
|
||||
|
||||
public float GetVolume()
|
||||
{
|
||||
if (OutputDevices != null)
|
||||
{
|
||||
foreach (IHardwareDevice outputDevice in OutputDevices)
|
||||
{
|
||||
if (outputDevice != null)
|
||||
{
|
||||
return outputDevice.GetVolume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public void SetVolume(float volume)
|
||||
{
|
||||
if (OutputDevices != null)
|
||||
{
|
||||
foreach (IHardwareDevice outputDevice in OutputDevices)
|
||||
{
|
||||
outputDevice?.SetVolume(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
@@ -269,6 +240,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
if (disposing)
|
||||
{
|
||||
_event.Dispose();
|
||||
_mailbox?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -177,12 +177,12 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
/// <summary>
|
||||
/// Start the <see cref="AudioProcessor"/> and worker thread.
|
||||
/// </summary>
|
||||
private void StartLocked(float volume)
|
||||
private void StartLocked()
|
||||
{
|
||||
_isRunning = true;
|
||||
|
||||
// TODO: virtual device mapping (IAudioDevice)
|
||||
Processor.Start(_deviceDriver, volume);
|
||||
Processor.Start(_deviceDriver);
|
||||
|
||||
_workerThread = new Thread(SendCommands)
|
||||
{
|
||||
@@ -254,7 +254,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
/// Register a new <see cref="AudioRenderSystem"/>.
|
||||
/// </summary>
|
||||
/// <param name="renderer">The <see cref="AudioRenderSystem"/> to register.</param>
|
||||
private void Register(AudioRenderSystem renderer, float volume)
|
||||
private void Register(AudioRenderSystem renderer)
|
||||
{
|
||||
lock (_sessionLock)
|
||||
{
|
||||
@@ -265,7 +265,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
{
|
||||
if (!_isRunning)
|
||||
{
|
||||
StartLocked(volume);
|
||||
StartLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -312,8 +312,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
ulong appletResourceUserId,
|
||||
ulong workBufferAddress,
|
||||
ulong workBufferSize,
|
||||
uint processHandle,
|
||||
float volume)
|
||||
uint processHandle)
|
||||
{
|
||||
int sessionId = AcquireSessionId();
|
||||
|
||||
@@ -338,7 +337,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
{
|
||||
renderer = audioRenderer;
|
||||
|
||||
Register(renderer, volume);
|
||||
Register(renderer);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -350,21 +349,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
return result;
|
||||
}
|
||||
|
||||
public float GetVolume()
|
||||
{
|
||||
if (Processor != null)
|
||||
{
|
||||
return Processor.GetVolume();
|
||||
}
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public void SetVolume(float volume)
|
||||
{
|
||||
Processor?.SetVolume(volume);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
|
@@ -8,11 +8,10 @@ using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.Ava
|
||||
{
|
||||
@@ -43,9 +42,9 @@ namespace Ryujinx.Ava
|
||||
{
|
||||
ApplyConfiguredTheme();
|
||||
|
||||
ConfigurationState.Instance.Ui.BaseStyle.Event += ThemeChanged_Event;
|
||||
ConfigurationState.Instance.Ui.CustomThemePath.Event += ThemeChanged_Event;
|
||||
ConfigurationState.Instance.Ui.EnableCustomTheme.Event += CustomThemeChanged_Event;
|
||||
ConfigurationState.Instance.UI.BaseStyle.Event += ThemeChanged_Event;
|
||||
ConfigurationState.Instance.UI.CustomThemePath.Event += ThemeChanged_Event;
|
||||
ConfigurationState.Instance.UI.EnableCustomTheme.Event += CustomThemeChanged_Event;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,15 +88,13 @@ namespace Ryujinx.Ava
|
||||
{
|
||||
try
|
||||
{
|
||||
string baseStyle = ConfigurationState.Instance.Ui.BaseStyle;
|
||||
string themePath = ConfigurationState.Instance.Ui.CustomThemePath;
|
||||
bool enableCustomTheme = ConfigurationState.Instance.Ui.EnableCustomTheme;
|
||||
string baseStyle = ConfigurationState.Instance.UI.BaseStyle;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(baseStyle))
|
||||
{
|
||||
ConfigurationState.Instance.Ui.BaseStyle.Value = "Dark";
|
||||
ConfigurationState.Instance.UI.BaseStyle.Value = "Dark";
|
||||
|
||||
baseStyle = ConfigurationState.Instance.Ui.BaseStyle;
|
||||
baseStyle = ConfigurationState.Instance.UI.BaseStyle;
|
||||
}
|
||||
|
||||
RequestedThemeVariant = baseStyle switch
|
||||
@@ -106,24 +103,6 @@ namespace Ryujinx.Ava
|
||||
"Dark" => ThemeVariant.Dark,
|
||||
_ => ThemeVariant.Default,
|
||||
};
|
||||
|
||||
if (enableCustomTheme)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(themePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
var themeContent = File.ReadAllText(themePath);
|
||||
var customStyle = AvaloniaRuntimeXamlLoader.Parse<IStyle>(themeContent);
|
||||
|
||||
Styles.Add(customStyle);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to Apply Custom Theme. Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
@@ -1,4 +1,3 @@
|
||||
using ARMeilleure.Translation;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
@@ -35,10 +34,10 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.HLE;
|
||||
using Ryujinx.Ui.App.Common;
|
||||
using Ryujinx.Ui.Common;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using Ryujinx.UI.Common;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using Silk.NET.Vulkan;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats.Png;
|
||||
@@ -916,7 +915,6 @@ namespace Ryujinx.Ava
|
||||
{
|
||||
Device.Gpu.SetGpuThread();
|
||||
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
|
||||
Translator.IsReadyForTranslation.Set();
|
||||
|
||||
_renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
|
||||
|
||||
@@ -980,7 +978,7 @@ namespace Ryujinx.Ava
|
||||
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
|
||||
LocaleManager.Instance[LocaleKeys.Game] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
|
||||
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
|
||||
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}"));
|
||||
$"GPU: {_renderer.GetHardwareInfo().GpuDriver}"));
|
||||
}
|
||||
|
||||
public async Task ShowExitPrompt()
|
||||
@@ -1072,7 +1070,7 @@ namespace Ryujinx.Ava
|
||||
case KeyboardHotkeyState.Screenshot:
|
||||
ScreenshotRequested = true;
|
||||
break;
|
||||
case KeyboardHotkeyState.ShowUi:
|
||||
case KeyboardHotkeyState.ShowUI:
|
||||
_viewModel.ShowMenuAndStatusBar = !_viewModel.ShowMenuAndStatusBar;
|
||||
break;
|
||||
case KeyboardHotkeyState.Pause:
|
||||
@@ -1088,10 +1086,11 @@ namespace Ryujinx.Ava
|
||||
case KeyboardHotkeyState.ToggleMute:
|
||||
if (Device.IsAudioMuted())
|
||||
{
|
||||
Device.SetVolume(ConfigurationState.Instance.System.AudioVolume);
|
||||
Device.SetVolume(_viewModel.VolumeBeforeMute);
|
||||
}
|
||||
else
|
||||
{
|
||||
_viewModel.VolumeBeforeMute = Device.GetVolume();
|
||||
Device.SetVolume(0);
|
||||
}
|
||||
|
||||
@@ -1161,9 +1160,9 @@ namespace Ryujinx.Ava
|
||||
{
|
||||
state = KeyboardHotkeyState.Screenshot;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi))
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUI))
|
||||
{
|
||||
state = KeyboardHotkeyState.ShowUi;
|
||||
state = KeyboardHotkeyState.ShowUI;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause))
|
||||
{
|
||||
|
155
src/Ryujinx.Ava/Assets/Icons/Controller_JoyConLeft.svg
Normal file
155
src/Ryujinx.Ava/Assets/Icons/Controller_JoyConLeft.svg
Normal file
@@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1000 355.6" style="enable-background:new 0 0 1000 355.6;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#00BBDB;stroke:#000000;}
|
||||
.st1{fill:#333333;stroke:#000000;stroke-width:0.93;}
|
||||
.st2{fill:#333333;stroke:#000000;stroke-width:0.96;}
|
||||
.st3{fill:#333333;stroke:#000000;stroke-width:0.85;}
|
||||
.st4{fill:#1A1A1A;stroke:#000000;}
|
||||
.st5{fill:#333333;stroke:#000000;}
|
||||
.st6{fill:#1A1A1A;stroke:#1A1A1A;}
|
||||
.st7{fill:#1A1A1A;stroke:#4D4D4D;}
|
||||
.st8{stroke:#4D4D4D;}
|
||||
.st9{stroke:#000000;}
|
||||
</style>
|
||||
<g id="g344">
|
||||
<path id="path66-7" d="M906.6,6.5v7.9c0,3.6-2.9,6.4-6.5,6.5H71.2c-3.6,0-6.4-2.9-6.5-6.5V6.5c0-3.6,2.9-6.4,6.5-6.5L207,0
|
||||
c4.9,0,9.6,1.2,14,3.4l13,6.7h79.2l13-6.7c4.3-2.2,9.1-3.4,13.9-3.4l269.7,0c4.9,0,9.6,1.2,14,3.4l13,6.7H716l13-6.7
|
||||
c4.3-2.2,9.1-3.4,13.9-3.4l157.2,0C903.7,0,906.6,2.9,906.6,6.5L906.6,6.5L906.6,6.5z M65.7,14.4c0,3,2.4,5.5,5.5,5.5h828.9
|
||||
c3,0,5.5-2.4,5.5-5.5V6.5c0-3-2.4-5.5-5.5-5.5H742.9c-4.7,0-9.3,1.1-13.5,3.3l-13.1,6.8c-0.1,0-0.2,0.1-0.2,0.1h-79.5
|
||||
c-0.1,0-0.2,0-0.2-0.1l-13.1-6.8c-4.2-2.2-8.8-3.3-13.5-3.3H340.1c-4.7,0-9.3,1.1-13.5,3.3l-13.1,6.8c-0.1,0-0.2,0.1-0.2,0.1h-79.5
|
||||
c-0.1,0-0.2,0-0.2-0.1l-13.1-6.8C216.3,2.1,211.7,1,207,1L71.2,1c-3,0-5.5,2.4-5.5,5.5L65.7,14.4L65.7,14.4z"/>
|
||||
<path id="path68-5" d="M858.9,20.3v11.2c0,0.3-0.2,0.5-0.5,0.5H72c-0.3,0-0.5-0.2-0.5-0.5V20.3c0-0.3,0.2-0.5,0.5-0.5h786.4
|
||||
C858.7,19.8,858.9,20,858.9,20.3z M857.9,31V20.8H72.5V31H857.9z"/>
|
||||
<path id="path70-3" d="M1000,37.5v106.2c0,117-94.8,211.9-211.9,211.9l0,0H220.9c-116.8,0-211.8-95.1-211.8-211.9V37.5
|
||||
c0-3.6,2.9-6.5,6.5-6.5h978C997.1,31,1000,33.9,1000,37.5L1000,37.5L1000,37.5z M10.1,143.7c0,116.3,94.6,210.9,210.8,210.9h567.2
|
||||
C904.4,354.6,999,260,999,143.7V37.5c0-3-2.4-5.5-5.5-5.5h-978c-3,0-5.5,2.4-5.5,5.5v106.2L10.1,143.7L10.1,143.7z"/>
|
||||
<path id="path98" d="M717.1,6.5v4.2c0,0.6-0.4,1-1,1l0,0h-79.5c-0.6,0-1-0.4-1-1V6.5c0-3.8,3.1-6.9,7-7h67.6
|
||||
C714-0.5,717.1,2.6,717.1,6.5z M715.1,9.7V6.5c0-2.7-2.2-5-5-5h-67.6c-2.7,0-5,2.2-5,5v3.2H715.1z"/>
|
||||
<path id="path100" d="M314.3,6.5v4.2c0,0.6-0.4,1-1,1h-79.5c-0.6,0-1-0.4-1-1V6.5c0-3.8,3.1-6.9,7-7h67.6
|
||||
C311.2-0.5,314.3,2.6,314.3,6.5z M312.3,9.7V6.5c0-2.7-2.2-5-5-5h-67.6c-2.7,0-5,2.2-5,5v3.2H312.3z"/>
|
||||
<path id="path1144" class="st0" d="M997.9,162.4c-3,26.2-8.5,49.9-21,75.1c-10.9,21.9-25.7,41.1-42.5,57.5
|
||||
c-33.2,32.3-77.8,53.7-126.7,59c-3.4,0.4-30.5,0.1-72.2,0.3c-158.5,1.1-520.6,0.9-534.4-0.5c-17.7-1.8-36.5-6.1-52.4-12
|
||||
c-7.5-2.8-15.8-7.1-23.1-10.7C61.8,299.6,21.2,238.8,12,168.6C9.6,150.4,8.7,35.5,11,33.1c0.1-0.1,2.3-0.9,7-1
|
||||
c11.1-0.4,36-0.4,79.4-1.3c32.7-0.7,76.3,0,132.5-0.1c70.3-0.2,160.2,1.6,274.8,1.6c484.5,0,491.2-1.4,492.4,0.9
|
||||
c0.2,0.3,1.7,2.5,1.8,5.3c1.1,21.9-0.5,119.2-0.7,120.6L997.9,162.4L997.9,162.4z"/>
|
||||
<polygon id="polygon80" class="st1" points="470.2,195 470.2,168.3 448.1,181.7 "/>
|
||||
<polygon id="polygon82" class="st2" points="627.3,181.3 605.6,194.1 605.6,168.5 "/>
|
||||
<polygon id="polygon84" class="st1" points="538.1,271.6 551.5,249.7 524.7,249.7 "/>
|
||||
<polygon id="polygon86" class="st3" points="551.6,114.8 524.1,114.8 537.9,89.2 "/>
|
||||
<path id="path102" d="M139.3,338.3c0,0.3-0.1,0.5-0.3,0.7l-3.4,3.4c-2,2-5.1,2.6-7.8,1.5C50.1,309.1,0.1,231.9,0,146.7l0-51.2
|
||||
c0-3.8,3.1-6.9,7-7h2.6c0.6,0,1,0.4,1,1v54.2C10.5,228.2,61,304.5,138.7,337.4c0.3,0.1,0.5,0.4,0.6,0.7L139.3,338.3L139.3,338.3z
|
||||
M2,146.7c0.1,84.4,49.7,160.9,126.7,195.4c1.9,0.8,4.1,0.4,5.5-1.1l2.4-2.4C58.8,305,8.5,228.3,8.6,143.6V90.4H7c-2.7,0-5,2.2-5,5
|
||||
L2,146.7L2,146.7z"/>
|
||||
<path id="path104" d="M116.1,60v46.9c0,2.2-1.8,4-4,4h-11.7c-2.2,0-4-1.8-4-4V60c0-2.2,1.8-4,4-4h11.7
|
||||
C114.3,56,116.1,57.8,116.1,60z M98.5,106.9c0,1.1,0.9,2,2,2h11.7c1.1,0,2-0.9,2-2V60c0-1.1-0.9-2-2-2h-11.7c-1.1,0-2,0.9-2,2
|
||||
V106.9z"/>
|
||||
<path id="path106" d="M502.9,181.7c0,21.2-17.2,38.5-38.5,38.5s-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5S502.9,160.4,502.9,181.7
|
||||
L502.9,181.7z M428,181.7c0,20.1,16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5s-16.3-36.5-36.5-36.5S428,161.5,428,181.7L428,181.7z"/>
|
||||
<path id="path108" d="M649.8,181.7c0,21.2-17.2,38.5-38.5,38.5s-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5S649.8,160.4,649.8,181.7
|
||||
L649.8,181.7z M574.9,181.7c0,20.1,16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5s-16.3-36.5-36.5-36.5l0,0
|
||||
C591.2,145.2,574.9,161.5,574.9,181.7L574.9,181.7z"/>
|
||||
<path id="path110" d="M576.3,108.2c0,21.2-17.2,38.5-38.5,38.5s-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5l0,0
|
||||
C559.1,69.8,576.3,87,576.3,108.2z M501.4,108.2c0,20.1,16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5s-16.3-36.5-36.5-36.5l0,0
|
||||
C517.7,71.8,501.4,88.1,501.4,108.2L501.4,108.2L501.4,108.2z"/>
|
||||
<path id="path112" d="M576.3,255.1c0,21.2-17.2,38.5-38.5,38.5s-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5l0,0
|
||||
C559.1,216.7,576.3,233.9,576.3,255.1z M501.4,255.1c0,20.1,16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5s-16.3-36.5-36.5-36.5l0,0
|
||||
C517.7,218.7,501.4,235,501.4,255.1L501.4,255.1L501.4,255.1z"/>
|
||||
<path id="path114" d="M753.7,105.5v45c0,5.5-4.4,9.9-9.9,9.9h-45c-5.5,0-9.9-4.4-9.9-9.9v-45c0-5.5,4.4-9.9,9.9-9.9h45
|
||||
C749.3,95.6,753.7,100.1,753.7,105.5z M690.9,150.5c0,4.4,3.6,7.9,7.9,7.9h45c4.4,0,7.9-3.6,7.9-7.9v-45c0-4.4-3.6-7.9-7.9-7.9h-45
|
||||
c-4.4,0-7.9,3.6-7.9,7.9V150.5z"/>
|
||||
<path id="path116" d="M741.7,128c0,11.3-9.2,20.4-20.4,20.4s-20.4-9.2-20.4-20.4s9.2-20.4,20.4-20.4l0,0
|
||||
C732.6,107.6,741.7,116.7,741.7,128z M702.8,128c0,10.2,8.3,18.4,18.4,18.4s18.4-8.3,18.4-18.4s-8.3-18.4-18.4-18.4
|
||||
S702.9,117.8,702.8,128z"/>
|
||||
<path id="path118" d="M260.2,244.8v12.3c0,0.6-0.4,1-1,1l0,0c-39.6-1.7-71.3-33.4-73-73c0-0.3,0.1-0.5,0.3-0.7s0.4-0.3,0.7-0.3
|
||||
h12.3c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9C257.6,238.4,260.2,241.3,260.2,244.8L260.2,244.8z M258.2,256v-11.2
|
||||
c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-11.2C190.3,223.4,220.8,253.9,258.2,256L258.2,256z
|
||||
"/>
|
||||
<path id="path120" d="M338.9,185L338.9,185c-1.7,39.6-33.4,71.3-73,73c-0.6,0-1-0.4-1-1v-12.3c0-3.5,2.6-6.4,6-6.9
|
||||
c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6H338C338.5,184,338.9,184.5,338.9,185L338.9,185z M266.9,256
|
||||
c37.4-2.2,67.8-32.6,70-70h-11.2c-2.5,0-4.6,1.8-4.9,4.3c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9V256L266.9,256z"/>
|
||||
<path id="path122" d="M338.9,178.3c0,0.6-0.4,1-1,1h-12.3c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9
|
||||
c-3.4-0.5-6-3.4-6-6.9v-12.3c0-0.6,0.4-1,1-1l0,0C305.5,107,337.2,138.7,338.9,178.3L338.9,178.3L338.9,178.3z M266.9,118.6
|
||||
c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h11.2c-2.2-37.4-32.6-67.8-70-70V118.6z"/>
|
||||
<path id="path124" d="M260.2,106.3v12.3c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-12.3
|
||||
c-0.3,0-0.5-0.1-0.7-0.3s-0.3-0.5-0.3-0.7c1.7-39.6,33.4-71.3,73-73C259.7,105.3,260.2,105.7,260.2,106.3L260.2,106.3L260.2,106.3z
|
||||
M188.2,177.3h11.2c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2
|
||||
C220.8,109.5,190.3,140,188.2,177.3L188.2,177.3L188.2,177.3z"/>
|
||||
<path id="path126" d="M339,181.7c0,1.2,0,2.3-0.1,3.4c0,0.5-0.5,0.9-1,0.9h-12.3c-2.5,0-4.6,1.8-4.9,4.3
|
||||
c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v12.3c0,0.5-0.4,1-0.9,1c-1.1,0.1-2.2,0.1-3.4,0.1s-2.3,0-3.4-0.1
|
||||
c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-12.3
|
||||
c-0.5,0-1-0.4-1-0.9c-0.1-2.3-0.1-4.5,0-6.8c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6
|
||||
c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1c1.1-0.1,2.2-0.1,3.4-0.1s2.3,0,3.4,0.1c0.5,0,0.9,0.5,0.9,1v12.3
|
||||
c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h12.3c0.5,0,1,0.4,1,0.9C339,179.4,339,180.5,339,181.7
|
||||
L339,181.7z M337,184c0.1-1.5,0.1-3.1,0-4.7h-11.3c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3
|
||||
h-4.6v11.4c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-11.3c-0.1,1.5-0.1,3.1,0,4.7h11.3
|
||||
c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9v11.3h4.6v-11.3c0-3.5,2.6-6.4,6-6.9
|
||||
c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6L337,184L337,184z"/>
|
||||
<path id="path179" class="st4" d="M574.3,261.6c-3.2,14.7-12.7,24.9-27.1,29c-3.4,1-6.3,1.2-11.7,0.9c-6.5-0.3-7.8-0.7-13.5-3.5
|
||||
c-22.9-11.4-27.9-40.7-10-58.6c19.4-19.4,51.9-12,60.8,13.9C574.5,248.5,575.3,257.1,574.3,261.6L574.3,261.6L574.3,261.6z
|
||||
M538,249c-7.3,0-13.4,0.2-13.4,0.4c0,0.9,13.2,23.3,13.5,23c0.7-0.7,13.1-22.2,13.2-22.8C551.3,249.2,545.4,249,538,249L538,249
|
||||
L538,249z"/>
|
||||
<path id="path181" class="st4" d="M500.6,187.1c-0.9,6.9-5,15-10.4,20.5c-14.5,14.6-36.9,14.6-51.4-0.1c-22.9-23-7-62.3,25.4-62.3
|
||||
c10.4,0,18.8,3.5,26,10.7C498.4,164.3,502.1,175.2,500.6,187.1L500.6,187.1L500.6,187.1z M469.9,168.5
|
||||
c-2.4,0.9-22.4,12.8-22.4,13.3c0,0.4,9,5.9,19.9,12l3.6,2v-13.9C471,169.7,470.9,168.1,469.9,168.5L469.9,168.5L469.9,168.5z"/>
|
||||
<path id="path185" class="st4" d="M647,190.4c-3.5,12.9-13.7,23.1-26.6,26.5c-22.7,5.9-45.2-11.6-45.3-35.2
|
||||
c0-7.4,0.9-11.3,4.5-18.1c8.8-16.9,30.4-23.9,47.9-15.4C643,155.8,651.4,173.9,647,190.4L647,190.4L647,190.4z M616.9,174.2
|
||||
c-6.3-3.6-11.6-6.5-11.8-6.3s-0.3,6.4-0.1,13.8l0.2,13.5l11.6-6.7c6.4-3.7,11.6-6.9,11.6-7.2C628.4,181.1,623.2,177.8,616.9,174.2
|
||||
L616.9,174.2z"/>
|
||||
<path id="path187" class="st4" d="M574.2,111.7c0,0.3-0.3,1.6-0.5,2.9c-2.2,11.2-9.7,20.9-20.1,26.2c-5.6,2.8-12.2,4.2-17.9,3.8
|
||||
c-14.8-1.1-27.7-11.3-32.5-25.6c-2.9-8.8-2.2-18,2.2-26.7s12.1-15.5,21.3-18.6c15.3-5.3,32.2,0.7,41.6,14.7c4,6,6.3,13.4,6.2,20.2
|
||||
C574.3,109.9,574.3,111.4,574.2,111.7L574.2,111.7L574.2,111.7z M551.1,112.4c-0.4-0.7-1.6-3-2.8-5.1c-4.8-8.7-9.2-15.6-10-16.2
|
||||
c-0.4-0.3-0.5-0.3-0.9,0c-1.3,0.9-13.5,21.5-13.5,22.9c0,0.3,0.1,0.6,0.2,0.7c0.5,0.4,4.8,0.6,13.9,0.6c9.1,0,13-0.2,13.5-0.6
|
||||
C551.9,114.3,551.8,113.8,551.1,112.4L551.1,112.4L551.1,112.4z"/>
|
||||
<path id="path189" class="st5" d="M739.1,131.6c-0.2,1-1,3-1.6,4.4c-1,2.1-1.6,2.9-3.5,4.8c-1.9,1.9-2.7,2.5-4.8,3.5
|
||||
c-5.5,2.7-10.6,2.7-16.1,0c-2.1-1-2.8-1.6-4.8-3.5c-3.6-3.6-5.3-7.7-5.3-12.7c0-8.4,5.7-15.7,13.9-17.8c2-0.5,6.2-0.5,8.3,0
|
||||
c6.3,1.5,11.5,6.3,13.4,12.7C739.4,125.4,739.6,129.2,739.1,131.6L739.1,131.6L739.1,131.6z"/>
|
||||
<path id="path191" class="st4" d="M751.3,152.4c-0.4,1.6-1.3,3-2.6,4.1c-2.1,1.8-0.9,1.7-27.4,1.7s-25.3,0.1-27.5-1.9
|
||||
c-0.7-0.6-1.5-1.7-1.9-2.5l-0.7-1.5v-48.3l0.9-1.8c0.6-1.3,1.2-2,2.1-2.7c2.3-1.8,1.3-1.7,27.8-1.6c23.8,0.1,23.9,0.1,25.1,0.6
|
||||
c1.6,0.7,3.1,2.3,3.9,3.9l0.7,1.3l0,23.8C751.6,145.6,751.5,151.4,751.3,152.4L751.3,152.4L751.3,152.4z M741.6,125.1
|
||||
c-1.5-10.6-10.7-18.1-21.4-17.5c-3.4,0.2-5.3,0.7-8.1,2c-9.3,4.6-13.7,15.5-10.2,25.3c1,2.8,2.2,4.7,4.3,7c2.8,3,6.3,5.1,10.3,6
|
||||
c2.2,0.5,7.2,0.5,9.4,0c3.9-0.9,7.4-3,10.2-6c2.1-2.2,3.3-4.2,4.3-6.7C741.7,131.9,742.1,128.5,741.6,125.1L741.6,125.1
|
||||
L741.6,125.1z"/>
|
||||
<path id="path1082" class="st6" d="M330.4,183.8c-6,0-6.5,0.1-7.9,0.7c-2.1,1.1-3.4,2.9-3.9,5.6c-2.7,15.1-10.1,27.5-21.9,36.5
|
||||
c-6.5,5-15.1,8.8-23.2,10.4c-4.3,0.8-5.7,1.4-7,3c-1.5,1.8-1.8,3.3-1.8,10v5.9h-4.2v-6.3c0-6.1,0-6.3-0.9-8
|
||||
c-1.2-2.4-2.7-3.3-7.3-4.2c-23.2-4.6-41-22.4-45.4-45.6c-0.8-4.2-1.6-5.6-3.8-6.9c-1.5-0.9-1.6-0.9-8.1-1l-6.6-0.1v-4.2h6.3
|
||||
c6.2,0,6.3,0,8-0.9c2.6-1.3,3.4-2.6,4.4-7.6c3.8-19.4,17-35.1,35.4-42.3c2.7-1,5.9-1.9,12-3.3c2.6-0.6,4.2-1.7,5.2-3.6
|
||||
c0.6-1.1,0.7-2,0.8-7.9l0.1-6.6h4.2v6.3c0,6.1,0,6.3,0.9,8c1.1,2.2,2.9,3.4,5.9,3.9c23.8,4.1,42.3,22.2,46.8,46
|
||||
c0.8,4.2,1.7,5.7,4.1,7c1.5,0.8,1.9,0.8,8,0.9l6.4,0.1v4.2L330.4,183.8L330.4,183.8z"/>
|
||||
<path id="path1084" class="st7" d="M257.3,255.8c-0.5-0.1-1.9-0.3-3.2-0.4c-3.9-0.4-10.1-1.7-14.8-3.3c-24.1-8-42.7-28.1-48.9-52.7
|
||||
c-0.8-3.1-1.6-7.6-1.9-11.3l-0.2-2h5.9c8.5,0,9.1,0.4,10.4,6.5c3.7,18.4,15.2,33.7,31.9,41.9c5.1,2.6,10.1,4.1,17,5.5
|
||||
c2.4,0.5,4,1.8,4.4,3.7c0.2,0.7,0.3,3.8,0.3,6.8v5.5L257.3,255.8L257.3,255.8z"/>
|
||||
<path id="path1086" class="st7" d="M336.4,189.8c-3,27-21.4,50.8-46.9,60.9c-6,2.4-13.4,4.2-18.7,4.7c-1.3,0.1-2.7,0.3-3.1,0.4
|
||||
l-0.8,0.2l0.1-6.3c0.1-5.8,0.2-6.4,0.8-7.2c1.2-1.6,2.2-2,6.2-2.9c5.8-1.2,9.4-2.4,14.8-5.2c5.7-2.9,9.8-5.7,14.2-9.9
|
||||
c9.1-8.6,15.2-19.7,17.5-31.7c0.7-3.6,1.2-4.6,2.7-5.8c0.8-0.6,1.4-0.7,7.2-0.8c5.9-0.1,6.3-0.1,6.3,0.5
|
||||
C336.7,187,336.6,188.4,336.4,189.8L336.4,189.8L336.4,189.8z"/>
|
||||
<path id="path1088" class="st7" d="M257.7,119.9c-0.9,2.4-1.6,2.8-6.5,3.8c-18.2,3.7-33.5,15.4-41.6,32c-2.4,4.8-3.7,8.6-4.7,13.5
|
||||
c-1,4.7-1.6,6.2-2.9,7.1c-1.1,0.7-1.4,0.7-7.4,0.7c-3.5,0-6.3-0.1-6.3-0.3s0.2-1.9,0.5-4c1.5-12,5.6-22.9,12.4-32.8
|
||||
c3-4.4,5.6-7.4,9.9-11.6c9.6-9.3,20.7-15.5,33.5-18.8c3.6-0.9,10.9-2.1,12.9-2.1c0.6,0,0.6,0.3,0.6,5.6
|
||||
C258.1,116.9,258,119.1,257.7,119.9L257.7,119.9L257.7,119.9z"/>
|
||||
<path id="path1090" class="st7" d="M330.5,177.3c-5.8-0.1-6.4-0.2-7.2-0.8c-1.6-1.2-2-2.2-2.9-6.3c-4.7-23.5-23.3-41.9-47-46.4
|
||||
c-3.5-0.7-4.5-1.1-5.6-2.7c-0.6-0.8-0.7-1.4-0.8-7.2l-0.1-6.3l1.7,0.2c10.5,1.2,18,3.3,26.4,7.5c22.6,11.2,38.1,32.9,41.3,58
|
||||
c0.3,2.1,0.5,3.9,0.5,4S333.9,177.3,330.5,177.3L330.5,177.3L330.5,177.3z"/>
|
||||
<path id="path1092" class="st4" d="M113.5,108c-0.6,0.5-1.8,0.7-7.2,0.7c-4.5,0-6.7-0.2-7-0.5c-0.4-0.4-0.5-6.4-0.5-24.6
|
||||
c0-21.3,0.1-24.2,0.7-24.8c0.6-0.5,1.8-0.7,7-0.7c6.1,0,6.4,0,7,1c0.6,0.8,0.7,3.9,0.7,24.6S114,107.4,113.5,108z"/>
|
||||
<path id="path1094" class="st8" d="M134.2,340.6c-2.8,2.4-3.7,2.2-12.6-2.3c-21.7-10.8-39.6-23.6-56.5-40.5
|
||||
c-31.4-31.4-52.2-71.6-59.8-115.3c-2.6-15.1-2.7-16.5-2.9-54L2.3,93.7l1.2-1.4c0.9-1,1.7-1.4,3-1.6l1.8-0.2l0.2,33.8
|
||||
c0.2,36.2,0.3,38.8,2.7,53.3c6.2,38.4,22,72.9,47.3,103.3c5.7,6.8,18.3,19.5,25.2,25.2c10,8.4,21.7,16.5,32.4,22.5
|
||||
c5.4,3.1,18.7,9.6,19.5,9.6C136.4,338.3,136,339.1,134.2,340.6L134.2,340.6L134.2,340.6z"/>
|
||||
<path id="path1150" class="st9" d="M616,21.1c-216,0-634,0-526-0.1c108-0.1,614.3-0.3,722.4-0.1c29.2,0,43.2,0.1,45,0.1
|
||||
C862.4,21.1,773.6,21.1,616,21.1L616,21.1L616,21.1z"/>
|
||||
<path id="path1152" class="st4" d="M903.2,19c-2.1,1.5-44.2,0.8-417.6,0.8S70.3,20.6,68.2,19.1c-2-1.4-2.2-3.4-2.2-8.5
|
||||
c0-1.8-0.1-3.8,0.2-5.4c0.3-1.4,2-3.2,2.4-3.5c0.5-0.5,4.3-0.3,16.4-0.4c11.3-0.1,29,0.2,55.3,0.2c44.7,0,61.8-0.6,69.8-0.1
|
||||
c4.4,0.3,6.1,1.2,8.1,1.9c3.1,1.2,8.2,3.9,10.9,5.6l5,3.2l40.4-0.4c37.6-0.4,39,0.2,41.7-1.6c1.5-1.1,6.1-3,9.3-4.6l5.8-3l7.9-1.3
|
||||
l19.8,0.1l15.8,0.1l97.9,0.2c93.1,0.2,126.7-1.2,141.1,0.3c4.2,0.4,6.5,1.6,8.5,2.3c2.7,0.9,4.9,2.1,7.8,3.9l6.1,3.7l15.6-0.4
|
||||
l25.1-0.1c26.5-0.1,40.4-0.6,40.9-1.3c0.4-0.6,4-2.7,8.5-4.3l9-3.3l9-1.1l15.9,0.2l57.9,0.2c61.9,0.2,84.5-0.4,85.5,0.5
|
||||
c0.9,0.8,2.4,4.5,2.4,8.4C905.8,15.4,905.1,17.6,903.2,19L903.2,19L903.2,19z"/>
|
||||
<path id="path1154" class="st4" d="M464.9,30.8l-5.2,0l-387-0.4v-8.5h392.2l393-1.1l0.2,5.3l-0.2,4.9L464.9,30.8L464.9,30.8z"/>
|
||||
<path id="path1156" class="st0" d="M273.3,9.7h-38.6v-3c0-1.7,0.9-3.6,2.1-4.3c2.8-1.7,70.3-1.7,73.1,0c1.2,0.7,2.1,2.6,2.1,4.3v3
|
||||
H273.3L273.3,9.7z"/>
|
||||
<path id="path1158" class="st0" d="M676.2,9.7h-38.7v-3c0-1.8,0.9-3.6,2.1-4.3c2.8-1.7,70.3-1.7,73.2,0c1.2,0.7,2.1,2.6,2.1,4.3v3
|
||||
H676.2L676.2,9.7z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 15 KiB |
341
src/Ryujinx.Ava/Assets/Icons/Controller_JoyConPair.svg
Normal file
341
src/Ryujinx.Ava/Assets/Icons/Controller_JoyConPair.svg
Normal file
@@ -0,0 +1,341 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1000 1000.2" style="enable-background:new 0 0 1000 1000.2;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#00BBDB;stroke:#000000;}
|
||||
.st1{fill:#333333;stroke:#000000;stroke-width:0.93;}
|
||||
.st2{fill:#333333;stroke:#000000;stroke-width:0.96;}
|
||||
.st3{fill:#333333;stroke:#000000;stroke-width:0.85;}
|
||||
.st4{fill:#1A1A1A;stroke:#000000;}
|
||||
.st5{fill:#333333;stroke:#000000;}
|
||||
.st6{fill:#1A1A1A;stroke:#1A1A1A;}
|
||||
.st7{fill:#1A1A1A;stroke:#4D4D4D;}
|
||||
.st8{stroke:#4D4D4D;}
|
||||
.st9{stroke:#000000;}
|
||||
.st10{opacity:0.1;}
|
||||
.st11{fill:#FF5F55;}
|
||||
.st12{fill:#FF5F53;}
|
||||
.st13{fill:#FFFFFF;}
|
||||
.st14{fill:#999595;stroke:#000000;stroke-width:2.39;stroke-linecap:round;stroke-linejoin:round;}
|
||||
.st15{fill:#3A3D40;stroke:#000000;stroke-width:2.73;stroke-linecap:round;stroke-linejoin:round;}
|
||||
</style>
|
||||
<g id="layer1">
|
||||
<g id="g344">
|
||||
<path id="path66-7" d="M349.1,906.6h-7.9c-3.6,0-6.4-2.9-6.5-6.5V71.2c0-3.6,2.9-6.4,6.5-6.5h7.9c3.6,0,6.4,2.9,6.5,6.5V207
|
||||
c0,4.9-1.2,9.6-3.4,14l-6.7,13v79.2l6.7,13c2.2,4.3,3.4,9.1,3.4,13.9v269.7c0,4.9-1.2,9.6-3.4,14l-6.7,13V716l6.7,13
|
||||
c2.2,4.3,3.4,9.1,3.4,13.9v157.2C355.6,903.7,352.7,906.6,349.1,906.6L349.1,906.6L349.1,906.6z M341.2,65.7c-3,0-5.5,2.4-5.5,5.5
|
||||
v828.9c0,3,2.4,5.5,5.5,5.5h7.9c3,0,5.5-2.4,5.5-5.5V742.9c0-4.7-1.1-9.3-3.3-13.5l-6.8-13.1c0-0.1-0.1-0.2-0.1-0.2v-79.5
|
||||
c0-0.1,0-0.2,0.1-0.2l6.8-13.1c2.2-4.2,3.3-8.8,3.3-13.5V340.1c0-4.7-1.1-9.3-3.3-13.5l-6.8-13.1c0-0.1-0.1-0.2-0.1-0.2v-79.5
|
||||
c0-0.1,0-0.2,0.1-0.2l6.8-13.1c2.2-4.2,3.3-8.8,3.3-13.5V71.2c0-3-2.4-5.5-5.5-5.5L341.2,65.7L341.2,65.7z"/>
|
||||
<path id="path68-5" d="M335.3,858.9h-11.2c-0.3,0-0.5-0.2-0.5-0.5V72c0-0.3,0.2-0.5,0.5-0.5h11.2c0.3,0,0.5,0.2,0.5,0.5v786.4
|
||||
C335.8,858.7,335.6,858.9,335.3,858.9z M324.6,857.9h10.2V72.5h-10.2V857.9z"/>
|
||||
<path id="path70-3" d="M318.1,1000H211.9C94.9,1000,0,905.2,0,788.1l0,0V220.9C0,104.1,95.1,9.1,211.9,9.1h106.2
|
||||
c3.6,0,6.5,2.9,6.5,6.5v978C324.6,997.1,321.7,1000,318.1,1000L318.1,1000L318.1,1000z M211.9,10.1C95.6,10.1,1,104.7,1,220.9
|
||||
v567.2C1,904.4,95.6,999,211.9,999h106.2c3,0,5.5-2.4,5.5-5.5v-978c0-3-2.4-5.5-5.5-5.5H211.9L211.9,10.1L211.9,10.1z"/>
|
||||
<path id="path98" d="M349.1,717.1h-4.2c-0.6,0-1-0.4-1-1l0,0v-79.5c0-0.6,0.4-1,1-1h4.2c3.8,0,6.9,3.1,7,7v67.6
|
||||
C356.1,714,353,717.1,349.1,717.1z M345.9,715.1h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V715.1z"/>
|
||||
<path id="path100" d="M349.1,314.3h-4.2c-0.6,0-1-0.4-1-1v-79.5c0-0.6,0.4-1,1-1h4.2c3.8,0,6.9,3.1,7,7v67.6
|
||||
C356.1,311.2,353,314.3,349.1,314.3z M345.9,312.3h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V312.3z"/>
|
||||
<path id="path1144" class="st0" d="M193.2,997.9c-26.2-3-49.9-8.5-75.1-21C96.2,966,77,951.2,60.7,934.4
|
||||
C28.4,901.1,7,856.6,1.7,807.7c-0.4-3.4-0.1-30.5-0.3-72.2C0.3,576.9,0.4,214.9,1.8,201c1.8-17.7,6.1-36.5,12-52.4
|
||||
c2.8-7.5,7.1-15.8,10.7-23.1C55.9,61.8,116.8,21.2,187,12c18.2-2.4,133.1-3.3,135.5-0.9c0.1,0.1,0.9,2.3,1,7
|
||||
c0.4,11.1,0.4,36,1.3,79.4c0.7,32.7,0,76.3,0.1,132.5c0.2,70.3-1.6,160.2-1.6,274.8c0,484.5,1.4,491.2-0.9,492.4
|
||||
c-0.3,0.2-2.5,1.7-5.3,1.8c-21.9,1.1-119.2-0.5-120.6-0.7L193.2,997.9L193.2,997.9z"/>
|
||||
<polygon id="polygon80" class="st1" points="173.9,448.1 160.6,470.2 187.3,470.2 "/>
|
||||
<polygon id="polygon82" class="st2" points="187.1,605.6 174.3,627.3 161.5,605.6 "/>
|
||||
<polygon id="polygon84" class="st1" points="105.9,524.7 84,538.1 105.9,551.5 "/>
|
||||
<polygon id="polygon86" class="st3" points="266.4,537.9 240.8,551.6 240.8,524.1 "/>
|
||||
<path id="path102" d="M17.3,139.3c-0.3,0-0.5-0.1-0.7-0.3l-3.4-3.4c-2-2-2.6-5.1-1.5-7.8C46.5,50.1,123.7,0.1,208.9,0h51.2
|
||||
c3.8,0,6.9,3.1,7,7v2.6c0,0.6-0.4,1-1,1h-54.2C127.4,10.5,51.1,61,18.2,138.7c-0.1,0.3-0.4,0.5-0.7,0.6L17.3,139.3L17.3,139.3z
|
||||
M208.9,2C124.5,2.1,48,51.7,13.5,128.7c-0.8,1.9-0.4,4.1,1.1,5.5l2.4,2.4C50.6,58.8,127.3,8.5,212,8.6h53.2V7c0-2.7-2.2-5-5-5
|
||||
L208.9,2L208.9,2z"/>
|
||||
<path id="path104" d="M295.6,116.1h-46.9c-2.2,0-4-1.8-4-4v-11.7c0-2.2,1.8-4,4-4h46.9c2.2,0,4,1.8,4,4v11.7
|
||||
C299.6,114.3,297.8,116.1,295.6,116.1z M248.7,98.5c-1.1,0-2,0.9-2,2v11.7c0,1.1,0.9,2,2,2h46.9c1.1,0,2-0.9,2-2v-11.7
|
||||
c0-1.1-0.9-2-2-2H248.7z"/>
|
||||
<path id="path106" d="M173.9,502.9c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5S195.2,502.9,173.9,502.9
|
||||
L173.9,502.9z M173.9,428c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5S194.1,428,173.9,428L173.9,428z"
|
||||
/>
|
||||
<path id="path108" d="M173.9,649.8c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5S195.2,649.8,173.9,649.8
|
||||
L173.9,649.8z M173.9,574.9c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5l0,0
|
||||
C210.4,591.2,194.1,574.9,173.9,574.9L173.9,574.9z"/>
|
||||
<path id="path110" d="M247.4,576.3c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0
|
||||
C285.8,559.1,268.6,576.3,247.4,576.3z M247.4,501.4c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5l0,0
|
||||
C283.8,517.7,267.5,501.4,247.4,501.4L247.4,501.4L247.4,501.4z"/>
|
||||
<path id="path112" d="M100.5,576.3c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0
|
||||
C138.9,559.1,121.7,576.3,100.5,576.3z M100.5,501.4c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5l0,0
|
||||
C136.9,517.7,120.6,501.4,100.5,501.4L100.5,501.4L100.5,501.4z"/>
|
||||
<path id="path114" d="M250.1,753.7h-45c-5.5,0-9.9-4.4-9.9-9.9v-45c0-5.5,4.4-9.9,9.9-9.9h45c5.5,0,9.9,4.4,9.9,9.9v45
|
||||
C260,749.3,255.5,753.7,250.1,753.7z M205.1,690.9c-4.4,0-7.9,3.6-7.9,7.9v45c0,4.4,3.6,7.9,7.9,7.9h45c4.4,0,7.9-3.6,7.9-7.9v-45
|
||||
c0-4.4-3.6-7.9-7.9-7.9H205.1z"/>
|
||||
<path id="path116" d="M227.6,741.7c-11.3,0-20.4-9.2-20.4-20.4s9.2-20.4,20.4-20.4s20.4,9.2,20.4,20.4l0,0
|
||||
C248,732.6,238.9,741.7,227.6,741.7z M227.6,702.8c-10.2,0-18.4,8.3-18.4,18.4s8.3,18.4,18.4,18.4s18.4-8.3,18.4-18.4
|
||||
S237.8,702.9,227.6,702.8z"/>
|
||||
<path id="path118" d="M110.8,260.2H98.5c-0.6,0-1-0.4-1-1l0,0c1.7-39.6,33.4-71.3,73-73c0.3,0,0.5,0.1,0.7,0.3s0.3,0.4,0.3,0.7
|
||||
v12.3c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9C117.2,257.6,114.3,260.2,110.8,260.2L110.8,260.2z M99.6,258.2h11.2
|
||||
c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2C132.2,190.3,101.7,220.8,99.6,258.2L99.6,258.2
|
||||
z"/>
|
||||
<path id="path120" d="M170.6,338.9L170.6,338.9c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1h12.3c3.5,0,6.4,2.6,6.9,6
|
||||
c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9V338C171.6,338.5,171.1,338.9,170.6,338.9L170.6,338.9z M99.6,266.9
|
||||
c2.2,37.4,32.6,67.8,70,70v-11.2c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3H99.6L99.6,266.9z"
|
||||
/>
|
||||
<path id="path122" d="M177.3,338.9c-0.6,0-1-0.4-1-1v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6
|
||||
h12.3c0.6,0,1,0.4,1,1l0,0C248.6,305.5,216.9,337.2,177.3,338.9L177.3,338.9L177.3,338.9z M237,266.9c-2.5,0-4.6,1.8-4.9,4.3
|
||||
c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v11.2c37.4-2.2,67.8-32.6,70-70H237z"/>
|
||||
<path id="path124" d="M249.3,260.2H237c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-12.3
|
||||
c0-0.3,0.1-0.5,0.3-0.7s0.5-0.3,0.7-0.3c39.6,1.7,71.3,33.4,73,73C250.3,259.7,249.9,260.2,249.3,260.2L249.3,260.2L249.3,260.2z
|
||||
M178.3,188.2v11.2c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h11.2
|
||||
C246.1,220.8,215.6,190.3,178.3,188.2L178.3,188.2L178.3,188.2z"/>
|
||||
<path id="path126" d="M173.9,339c-1.2,0-2.3,0-3.4-0.1c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9
|
||||
c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3H98.5c-0.5,0-1-0.4-1-0.9c-0.1-1.1-0.1-2.2-0.1-3.4s0-2.3,0.1-3.4
|
||||
c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1
|
||||
c2.3-0.1,4.5-0.1,6.8,0c0.5,0,0.9,0.5,0.9,1v12.3c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h12.3
|
||||
c0.5,0,1,0.4,1,0.9c0.1,1.1,0.1,2.2,0.1,3.4s0,2.3-0.1,3.4c0,0.5-0.5,0.9-1,0.9H237c-2.5,0-4.6,1.8-4.9,4.3
|
||||
c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v12.3c0,0.5-0.4,1-0.9,1C176.2,339,175.1,339,173.9,339L173.9,339z
|
||||
M171.6,337c1.5,0.1,3.1,0.1,4.7,0v-11.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6h11.3v-4.6H237
|
||||
c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3c-1.5-0.1-3.1-0.1-4.7,0v11.3
|
||||
c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6H99.4v4.6h11.3c3.5,0,6.4,2.6,6.9,6
|
||||
c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9L171.6,337L171.6,337z"/>
|
||||
<path id="path179" class="st4" d="M94,574.3c-14.7-3.2-24.9-12.7-29-27.1c-1-3.4-1.2-6.3-0.9-11.7c0.3-6.5,0.7-7.8,3.5-13.5
|
||||
c11.4-22.9,40.7-27.9,58.6-10c19.4,19.4,12,51.9-13.9,60.8C107.1,574.5,98.5,575.3,94,574.3L94,574.3L94,574.3z M106.6,538
|
||||
c0-7.3-0.2-13.4-0.4-13.4c-0.9,0-23.3,13.2-23,13.5c0.7,0.7,22.2,13.1,22.8,13.2C106.4,551.3,106.6,545.4,106.6,538L106.6,538
|
||||
L106.6,538z"/>
|
||||
<path id="path181" class="st4" d="M168.5,500.6c-6.9-0.9-15-5-20.5-10.4c-14.6-14.5-14.6-36.9,0.1-51.4c23-22.9,62.3-7,62.3,25.4
|
||||
c0,10.4-3.5,18.8-10.7,26C191.3,498.4,180.4,502.1,168.5,500.6L168.5,500.6L168.5,500.6z M187.1,469.9
|
||||
c-0.9-2.4-12.8-22.4-13.3-22.4c-0.4,0-5.9,9-12,19.9l-2,3.6h13.9C185.9,471,187.5,470.9,187.1,469.9L187.1,469.9L187.1,469.9z"/>
|
||||
<path id="path185" class="st4" d="M165.2,647c-12.9-3.5-23.1-13.7-26.5-26.6c-5.9-22.7,11.6-45.2,35.2-45.3
|
||||
c7.4,0,11.3,0.9,18.1,4.5c16.9,8.8,23.9,30.4,15.4,47.9C199.8,643,181.7,651.4,165.2,647L165.2,647L165.2,647z M181.4,616.9
|
||||
c3.6-6.3,6.5-11.6,6.3-11.8s-6.4-0.3-13.8-0.1l-13.5,0.2l6.7,11.6c3.7,6.4,6.9,11.6,7.2,11.6C174.5,628.4,177.8,623.2,181.4,616.9
|
||||
L181.4,616.9z"/>
|
||||
<path id="path187" class="st4" d="M243.9,574.2c-0.3,0-1.6-0.3-2.9-0.5c-11.2-2.2-20.9-9.7-26.2-20.1c-2.8-5.6-4.2-12.2-3.8-17.9
|
||||
c1.1-14.8,11.3-27.7,25.6-32.5c8.8-2.9,18-2.2,26.7,2.2s15.5,12.1,18.6,21.3c5.3,15.3-0.7,32.2-14.7,41.6c-6,4-13.4,6.3-20.2,6.2
|
||||
C245.7,574.3,244.2,574.3,243.9,574.2L243.9,574.2L243.9,574.2z M243.2,551.1c0.7-0.4,3-1.6,5.1-2.8c8.7-4.8,15.6-9.2,16.2-10
|
||||
c0.3-0.4,0.3-0.5,0-0.9c-0.9-1.3-21.5-13.5-22.9-13.5c-0.3,0-0.6,0.1-0.7,0.2c-0.4,0.5-0.6,4.8-0.6,13.9c0,9.1,0.2,13,0.6,13.5
|
||||
C241.3,551.9,241.8,551.8,243.2,551.1L243.2,551.1L243.2,551.1z"/>
|
||||
<path id="path189" class="st5" d="M224,739.1c-1-0.2-3-1-4.4-1.6c-2.1-1-2.9-1.6-4.8-3.5c-1.9-1.9-2.5-2.7-3.5-4.8
|
||||
c-2.7-5.5-2.7-10.6,0-16.1c1-2.1,1.6-2.8,3.5-4.8c3.6-3.6,7.7-5.3,12.7-5.3c8.4,0,15.7,5.7,17.8,13.9c0.5,2,0.5,6.2,0,8.3
|
||||
c-1.5,6.3-6.3,11.5-12.7,13.4C230.2,739.4,226.4,739.6,224,739.1L224,739.1L224,739.1z"/>
|
||||
<path id="path191" class="st4" d="M203.2,751.3c-1.6-0.4-3-1.3-4.1-2.6c-1.8-2.1-1.7-0.9-1.7-27.4s-0.1-25.3,1.9-27.5
|
||||
c0.6-0.7,1.7-1.5,2.5-1.9l1.5-0.7h48.3l1.8,0.9c1.3,0.6,2,1.2,2.7,2.1c1.8,2.3,1.7,1.3,1.6,27.8c-0.1,23.8-0.1,23.9-0.6,25.1
|
||||
c-0.7,1.6-2.3,3.1-3.9,3.9l-1.3,0.7l-23.8,0C210,751.6,204.2,751.5,203.2,751.3L203.2,751.3L203.2,751.3z M230.5,741.6
|
||||
c10.6-1.5,18.1-10.7,17.5-21.4c-0.2-3.4-0.7-5.3-2-8.1c-4.6-9.3-15.5-13.7-25.3-10.2c-2.8,1-4.7,2.2-7,4.3c-3,2.8-5.1,6.3-6,10.3
|
||||
c-0.5,2.2-0.5,7.2,0,9.4c0.9,3.9,3,7.4,6,10.2c2.2,2.1,4.2,3.3,6.7,4.3C223.7,741.7,227.1,742.1,230.5,741.6L230.5,741.6
|
||||
L230.5,741.6z"/>
|
||||
<path id="path1082" class="st6" d="M171.8,330.4c0-6-0.1-6.5-0.7-7.9c-1.1-2.1-2.9-3.4-5.6-3.9c-15.1-2.7-27.5-10.1-36.5-21.9
|
||||
c-5-6.5-8.8-15.1-10.4-23.2c-0.8-4.3-1.4-5.7-3-7c-1.8-1.5-3.3-1.8-10-1.8h-5.9v-4.2h6.3c6.1,0,6.3,0,8-0.9
|
||||
c2.4-1.2,3.3-2.7,4.2-7.3c4.6-23.2,22.4-41,45.6-45.4c4.2-0.8,5.6-1.6,6.9-3.8c0.9-1.5,0.9-1.6,1-8.1l0.1-6.6h4.2v6.3
|
||||
c0,6.2,0,6.3,0.9,8c1.3,2.6,2.6,3.4,7.6,4.4c19.4,3.8,35.1,17,42.3,35.4c1,2.7,1.9,5.9,3.3,12c0.6,2.6,1.7,4.2,3.6,5.2
|
||||
c1.1,0.6,2,0.7,7.9,0.8l6.6,0.1v4.2h-6.3c-6.1,0-6.3,0-8,0.9c-2.2,1.1-3.4,2.9-3.9,5.9c-4.1,23.8-22.2,42.3-46,46.8
|
||||
c-4.2,0.8-5.7,1.7-7,4.1c-0.8,1.5-0.8,1.9-0.9,8l-0.1,6.4h-4.2L171.8,330.4L171.8,330.4z"/>
|
||||
<path id="path1084" class="st7" d="M99.8,257.3c0.1-0.5,0.3-1.9,0.4-3.2c0.4-3.9,1.7-10.1,3.3-14.8c8-24.1,28.1-42.7,52.7-48.9
|
||||
c3.1-0.8,7.6-1.6,11.3-1.9l2-0.2v5.9c0,8.5-0.4,9.1-6.5,10.4c-18.4,3.7-33.7,15.2-41.9,31.9c-2.6,5.1-4.1,10.1-5.5,17
|
||||
c-0.5,2.4-1.8,4-3.7,4.4c-0.7,0.2-3.8,0.3-6.8,0.3h-5.5L99.8,257.3L99.8,257.3z"/>
|
||||
<path id="path1086" class="st7" d="M165.8,336.4c-27-3-50.8-21.4-60.9-46.9c-2.4-6-4.2-13.4-4.7-18.7c-0.1-1.3-0.3-2.7-0.4-3.1
|
||||
l-0.2-0.8l6.3,0.1c5.8,0.1,6.4,0.2,7.2,0.8c1.6,1.2,2,2.2,2.9,6.2c1.2,5.8,2.4,9.4,5.2,14.8c2.9,5.7,5.7,9.8,9.9,14.2
|
||||
c8.6,9.1,19.7,15.2,31.7,17.5c3.6,0.7,4.6,1.2,5.8,2.7c0.6,0.8,0.7,1.4,0.8,7.2c0.1,5.9,0.1,6.3-0.5,6.3
|
||||
C168.6,336.7,167.2,336.6,165.8,336.4L165.8,336.4L165.8,336.4z"/>
|
||||
<path id="path1088" class="st7" d="M235.7,257.7c-2.4-0.9-2.8-1.6-3.8-6.5c-3.7-18.2-15.4-33.5-32-41.6c-4.8-2.4-8.6-3.7-13.5-4.7
|
||||
c-4.7-1-6.2-1.6-7.1-2.9c-0.7-1.1-0.7-1.4-0.7-7.4c0-3.5,0.1-6.3,0.3-6.3s1.9,0.2,4,0.5c12,1.5,22.9,5.6,32.8,12.4
|
||||
c4.4,3,7.4,5.6,11.6,9.9c9.3,9.6,15.5,20.7,18.8,33.5c0.9,3.6,2.1,10.9,2.1,12.9c0,0.6-0.3,0.6-5.6,0.6
|
||||
C238.7,258.1,236.5,258,235.7,257.7L235.7,257.7L235.7,257.7z"/>
|
||||
<path id="path1090" class="st7" d="M178.3,330.5c0.1-5.8,0.2-6.4,0.8-7.2c1.2-1.6,2.2-2,6.3-2.9c23.5-4.7,41.9-23.3,46.4-47
|
||||
c0.7-3.5,1.1-4.5,2.7-5.6c0.8-0.6,1.4-0.7,7.2-0.8l6.3-0.1l-0.2,1.7c-1.2,10.5-3.3,18-7.5,26.4c-11.2,22.6-32.9,38.1-58,41.3
|
||||
c-2.1,0.3-3.9,0.5-4,0.5S178.3,333.9,178.3,330.5L178.3,330.5L178.3,330.5z"/>
|
||||
<path id="path1092" class="st4" d="M247.6,113.5c-0.5-0.6-0.7-1.8-0.7-7.2c0-4.5,0.2-6.7,0.5-7c0.4-0.4,6.4-0.5,24.6-0.5
|
||||
c21.3,0,24.2,0.1,24.8,0.7c0.5,0.6,0.7,1.8,0.7,7c0,6.1,0,6.4-1,7c-0.8,0.6-3.9,0.7-24.6,0.7S248.2,114,247.6,113.5z"/>
|
||||
<path id="path1094" class="st8" d="M15,134.2c-2.3-2.8-2.2-3.7,2.3-12.6C28,99.9,40.9,82,57.8,65.1C89.1,33.7,129.4,12.8,173,5.3
|
||||
c15.1-2.6,16.5-2.7,54-2.9l34.8-0.2l1.4,1.2c1,0.9,1.4,1.7,1.6,3l0.2,1.8l-33.8,0.2C195,8.6,192.5,8.8,178,11.1
|
||||
c-38.4,6.2-72.9,22-103.3,47.3c-6.8,5.7-19.5,18.3-25.2,25.2c-8.4,10-16.5,21.7-22.5,32.4c-3.1,5.4-9.6,18.7-9.6,19.5
|
||||
C17.3,136.4,16.5,136,15,134.2L15,134.2L15,134.2z"/>
|
||||
<path id="path1150" class="st9" d="M334.4,616c0-216,0-634,0.1-526c0.1,108,0.3,614.3,0.1,722.4c0,29.2-0.1,43.2-0.1,45
|
||||
C334.5,862.4,334.5,773.6,334.4,616L334.4,616L334.4,616z"/>
|
||||
<path id="path1152" class="st4" d="M336.6,903.2c-1.5-2.1-0.8-44.2-0.8-417.6S335,70.3,336.5,68.2c1.4-2,3.4-2.2,8.5-2.2
|
||||
c1.8,0,3.8-0.1,5.4,0.2c1.4,0.3,3.2,2,3.5,2.4c0.5,0.5,0.3,4.3,0.4,16.4c0.1,11.3-0.2,29-0.2,55.3c0,44.7,0.6,61.8,0.1,69.8
|
||||
c-0.3,4.4-1.2,6.1-1.9,8.1c-1.2,3.1-3.9,8.2-5.6,10.9l-3.2,5l0.4,40.4c0.4,37.6-0.2,39,1.6,41.7c1.1,1.5,3,6.1,4.6,9.3l3,5.8
|
||||
l1.3,7.9l-0.1,19.8l-0.1,15.8l-0.2,97.9c-0.2,93.1,1.2,126.7-0.3,141.1c-0.4,4.2-1.6,6.5-2.3,8.5c-0.9,2.7-2.1,4.9-3.9,7.8
|
||||
l-3.7,6.1l0.4,15.6l0.1,25.1c0.1,26.5,0.6,40.4,1.3,40.9c0.6,0.4,2.7,4,4.3,8.5l3.3,9l1.1,9l-0.2,15.9l-0.2,57.9
|
||||
c-0.2,61.9,0.4,84.5-0.5,85.5c-0.8,0.9-4.5,2.4-8.4,2.4C340.2,905.8,338,905.1,336.6,903.2L336.6,903.2L336.6,903.2z"/>
|
||||
<path id="path1154" class="st4" d="M325.2,464.9V72.7h8.5v392.2l1.1,393l-5.3,0.2l-4.9-0.2L325.2,464.9L325.2,464.9z"/>
|
||||
<path id="path1156" class="st0" d="M345.9,273.3v-38.6h3c1.7,0,3.6,0.9,4.3,2.1c1.7,2.8,1.7,70.3,0,73.1c-0.7,1.2-2.6,2.1-4.3,2.1
|
||||
h-3V273.3L345.9,273.3z"/>
|
||||
<path id="path1158" class="st0" d="M345.9,676.2v-38.7h3c1.8,0,3.6,0.9,4.3,2.1c1.7,2.8,1.7,70.3,0,73.2c-0.7,1.2-2.6,2.1-4.3,2.1
|
||||
h-3V676.2L345.9,676.2z"/>
|
||||
</g>
|
||||
<g id="g315">
|
||||
<g id="g64" class="st10">
|
||||
<path id="path36" class="st11" d="M654.6,233.9v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6h4.2V233.9z"/>
|
||||
<path id="path38" class="st11" d="M654.6,636.6v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6L654.6,636.6L654.6,636.6z"/>
|
||||
<path id="path40" class="st11" d="M985.7,134.9l-3.4,3.4C949.1,60.3,872.5,9.6,787.6,9.6h-54.2V7c0-3.3,2.7-6,6-6h51.2
|
||||
C875.4,1,952.3,50.8,987,128.2C988,130.5,987.5,133.1,985.7,134.9L985.7,134.9L985.7,134.9z"/>
|
||||
<path id="path42" class="st11" d="M736.2,94.5V82.8c0-1.6-1.3-3-3-3h-11.7c-1.6,0-3,1.3-3,3l0,0v11.7c0,1.6-1.3,3-3,3h-11.7
|
||||
c-1.6,0-3,1.3-3,3l0,0v11.7c0,1.6,1.3,3,3,3h11.7c1.6,0,3,1.3,3,3l0,0v11.7c0,1.6,1.3,3,3,3h11.7c1.6,0,3-1.3,3-3l0,0v-11.7
|
||||
c0-1.6,1.3-3,3-3h11.7c1.6,0,3-1.3,3-3l0,0v-11.7c0-1.6-1.3-3-3-3h-11.7C737.5,97.5,736.2,96.1,736.2,94.5L736.2,94.5z"/>
|
||||
<circle id="circle44" class="st11" cx="825.6" cy="333.9" r="37.5"/>
|
||||
<circle id="circle46" class="st11" cx="825.6" cy="187.1" r="37.5"/>
|
||||
<circle id="circle48" class="st11" cx="899" cy="260.5" r="37.5"/>
|
||||
<circle id="circle50" class="st11" cx="752.2" cy="260.5" r="37.5"/>
|
||||
<circle id="circle52" class="st11" cx="771.7" cy="721.3" r="27.9"/>
|
||||
<path id="path54" class="st11" d="M822.3,460.3v12.3c0,3-2.2,5.5-5.2,5.9c-25.2,3.7-45,23.5-48.7,48.7c-0.4,2.9-2.9,5.1-5.9,5.2
|
||||
h-12.3C751.9,493.3,783.2,462,822.3,460.3L822.3,460.3L822.3,460.3z"/>
|
||||
<path id="path56" class="st11" d="M822.3,598.8v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2
|
||||
c3.7,25.2,23.5,45,48.7,48.7C820.1,593.3,822.3,595.8,822.3,598.8L822.3,598.8L822.3,598.8z"/>
|
||||
<path id="path58" class="st11" d="M901,539c-1.7,39.1-33,70.3-72.1,72v-12.3c0-3,2.2-5.5,5.2-5.9c25.2-3.7,45-23.5,48.7-48.7
|
||||
c0.4-2.9,2.9-5.1,5.9-5.2L901,539L901,539z"/>
|
||||
<path id="path60" class="st11" d="M901,532.4h-12.3c-3,0-5.5-2.2-5.9-5.2c-3.7-25.2-23.5-45-48.7-48.7c-2.9-0.4-5.1-2.9-5.2-5.9
|
||||
v-12.3C868,462,899.3,493.3,901,532.4L901,532.4L901,532.4z"/>
|
||||
<path id="path62" class="st11" d="M901.1,535.7c0,1.1,0,2.2-0.1,3.3h-12.3c-3,0-5.5,2.2-5.9,5.2c-3.7,25.2-23.5,45-48.7,48.7
|
||||
c-2.9,0.4-5.1,2.9-5.2,5.9v12.3c-1.1,0.1-2.2,0.1-3.3,0.1s-2.2,0-3.3-0.1v-12.3c0-3-2.2-5.5-5.2-5.9c-25.2-3.7-45-23.5-48.7-48.7
|
||||
c-0.4-2.9-2.9-5.1-5.9-5.2h-12.3c-0.1-1.1-0.1-2.2-0.1-3.3s0-2.2,0.1-3.3h12.3c3,0,5.5-2.2,5.9-5.2c3.7-25.2,23.5-45,48.7-48.7
|
||||
c2.9-0.4,5.1-2.9,5.2-5.9v-12.3c1.1-0.1,2.2-0.1,3.3-0.1s2.2,0,3.3,0.1v12.3c0,3,2.2,5.5,5.2,5.9c25.2,3.7,45,23.5,48.7,48.7
|
||||
c0.4,2.9,2.9,5.1,5.9,5.2H901C901,533.5,901.1,534.6,901.1,535.7L901.1,535.7z"/>
|
||||
</g>
|
||||
<path id="path72" d="M658.3,906.6h-7.9c-3.6,0-6.4-2.9-6.5-6.5V742.9c0-4.9,1.2-9.6,3.4-13.9l6.7-13v-79.2l-6.7-13
|
||||
c-2.2-4.3-3.4-9.1-3.4-14V340.1c0-4.9,1.2-9.6,3.4-13.9l6.7-13V234l-6.7-13c-2.2-4.3-3.4-9.1-3.4-14V71.2c0-3.6,2.9-6.4,6.5-6.5
|
||||
h7.9c3.6,0,6.4,2.9,6.5,6.5c1.1,276.3,1.2,552.6,0,828.9C664.7,903.7,661.8,906.6,658.3,906.6L658.3,906.6L658.3,906.6z
|
||||
M650.4,65.7c-3,0-5.5,2.4-5.5,5.5V207c0,4.7,1.1,9.3,3.3,13.5l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2
|
||||
l-6.8,13.1c-2.2,4.2-3.3,8.8-3.3,13.5v269.7c0,4.7,1.1,9.3,3.3,13.5l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2
|
||||
l-6.8,13.1c-2.2,4.2-3.3,8.8-3.3,13.5v157.2c0,3,2.4,5.5,5.5,5.5h7.9c3,0,5.5-2.4,5.5-5.5V71.2c0-3-2.4-5.5-5.5-5.5L650.4,65.7
|
||||
L650.4,65.7z"/>
|
||||
<path id="path74" d="M675.5,858.9h-11.3c-0.3,0-0.5-0.2-0.5-0.5l0,0L664.5,72c0-0.3,0.2-0.5,0.5-0.5h11.3c0.3,0-0.3,0.2-0.3,0.5
|
||||
v786.4C676,858.7,675.8,858.9,675.5,858.9z M665.6,857.9h9.4l0.8-785.4h-10.3l1,8.8c-0.6,256.1,4.5,511.8-1.1,768.3
|
||||
C665.3,852.3,665.6,855.1,665.6,857.9L665.6,857.9z"/>
|
||||
<path id="path76" d="M787.4,1000.2H681.2c-3.6,0-6.5-2.9-6.5-6.5v-978c0-3.6,2.9-6.5,6.5-6.5h106.2
|
||||
c116.8,0,211.9,95.1,211.9,211.9v567.2C999.3,905.3,904.5,1000.2,787.4,1000.2L787.4,1000.2z M681.2,10.4c-3,0-5.5,2.4-5.5,5.5
|
||||
v978c0,3,2.4,5.5,5.5,5.5h106.2c116.3,0,210.9-94.6,210.9-210.9V221.1c0-116.3-94.6-210.9-210.9-210.9L681.2,10.4z"/>
|
||||
<path id="path128" d="M654.6,314.3h-4.2c-3.8,0-6.9-3.1-7-7v-67.6c0-3.8,3.1-6.9,7-7h4.2c0.6,0,1,0.4,1,1l0,0v79.5
|
||||
C655.6,313.9,655.1,314.3,654.6,314.3L654.6,314.3z M650.4,234.8c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5h3.2v-77.5h-3.2V234.8z"/>
|
||||
<path id="path130" d="M654.6,717.1h-4.2c-3.8,0-6.9-3.1-7-7v-67.6c0-3.8,3.1-6.9,7-7h4.2c0.6,0,1,0.4,1,1l0,0V716
|
||||
C655.6,716.6,655.1,717.1,654.6,717.1L654.6,717.1z M650.4,637.6c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5h3.2v-77.5L650.4,637.6
|
||||
L650.4,637.6z"/>
|
||||
<path id="path1240" class="st12" d="M805.5,998.7c26.6-2.4,50.5-9.2,75.9-21.8c5.1-2.5,10-5.2,14.9-8
|
||||
c19.1-11.3,36.3-27.1,49.6-41.7c25.5-28,45.5-70.1,51.4-116.5c0.1-0.7,0.4-4.3,0.4-6.8c-0.1-6.9,0.7-20,0.8-38.3
|
||||
c0.7-77.5,1.1-244,1.1-376.4c0-101.2-0.3-182.5-1-188.9c-2.7-26.1-9.3-49.1-20.8-72.1c-31.8-63.9-93-107.4-164-116.7
|
||||
c-11.4-1.5-60.7-1.6-96.6-1.3c-7.7,0.1-14.1-0.1-20.1,0.1c-7.5,0.2-12.9-0.1-16.2,0.2c-1.7,0.2-3,0.8-3.2,1
|
||||
c-0.1,0.1-1.4,1.4-1.5,3.3c-0.3,5.2-0.3,17.1-0.4,38c0,4.2-0.1,8.8-0.1,13.8c0,4.9,0.1,10.1,0.1,15.8c-0.1,8.8,0.1,18.6,0.1,29.2
|
||||
c0,9.8-0.2,20.5,0,32c0.2,9,0.2,18.4,0.2,28.4c-0.1,15.1,0.6,31.1,0.3,49c-0.2,15,0.1,30,0,46.9c-0.1,11.1,0.1,22.6,0,34.6
|
||||
c-0.1,7.2,0,14.5-0.1,22.1c-0.5,52.1,0,112.2,0,180.3c0,254.3-0.3,376.1,0,435.2c0,7.7-0.2,14.5-0.1,20.2c0,2.2,0,4.3,0,6.2
|
||||
c0,3.3,0,6.6,0,9.3c0,2.9-0.1,5.8,0,8c0.1,5,0.1,8.1,0.3,10c0.3,2.8,1.3,3.6,1.6,3.8c0.2,0.2,1.3,0.9,3.1,1.1
|
||||
c4.5,0.4,14.6,0.3,27.1,0.2c9.9-0.1,21.3-0.2,32.8-0.2C772.7,998.8,805.8,999,805.5,998.7L805.5,998.7L805.5,998.7z"/>
|
||||
<path id="path78" d="M771.7,763.2c-23.1,0-41.9-18.7-41.9-41.9s18.7-41.9,41.9-41.9c23.2,0,41.9,18.7,41.9,41.9l0,0
|
||||
C813.5,744.4,794.8,763.1,771.7,763.2z M771.7,680.4c-22.6,0-40.9,18.3-40.9,40.9s18.3,40.9,40.9,40.9c22.6,0,40.9-18.3,40.9-40.9
|
||||
l0,0C812.5,698.7,794.3,680.4,771.7,680.4z"/>
|
||||
<path id="path88" class="st13" d="M838.9,203.2h-5.5l-7.6-10.9l-8,10.9h-5.4l10.6-16.3l-9.8-15.6h5.2l7.4,10.6l7.3-10.6h5
|
||||
l-9.8,15.4L838.9,203.2L838.9,203.2z"/>
|
||||
<path id="path90" class="st13" d="M765.9,244.5l-11.6,20.6v11.4h-4.4V265l-11.6-20.5h5.3l6.4,11.7l2.1,3l2.4-2.6l6.4-12.1H765.9
|
||||
L765.9,244.5z"/>
|
||||
<path id="path92" class="st13" d="M912.6,276.5h-4.7l-2.2-7l-12.4,0.3l-3.2,6.7h-4.5l9.9-35.2l6.7,3.2L912.6,276.5z M903.9,265.2
|
||||
l-4.9-14.6l-4.6,14.8L903.9,265.2L903.9,265.2z"/>
|
||||
<path id="path132" d="M982.3,139.3h-0.2c-0.3-0.1-0.6-0.3-0.7-0.6C948.4,61,872.1,10.5,787.6,10.6h-54.2c-0.6,0-1-0.4-1-1l0,0V7
|
||||
c0-3.8,3.1-6.9,7-7h51.2C875.8,0.1,953,50.1,987.9,127.8c1.2,2.6,0.6,5.7-1.5,7.8L983,139C982.8,139.2,982.5,139.3,982.3,139.3
|
||||
L982.3,139.3z M734.4,8.6h53.2c84.7-0.1,161.3,50.2,195,128l2.4-2.4l0,0c1.5-1.4,1.9-3.6,1.1-5.5C951.5,51.7,875,2.1,790.6,2
|
||||
h-51.2c-2.7,0-5,2.2-5,5V8.6z"/>
|
||||
<path id="path134" d="M733.2,133.7h-11.7c-2.2,0-4-1.8-4-4V118c0-1.1-0.9-2-2-2h-11.7c-2.2,0-4-1.8-4-4v-11.7c0-2.2,1.8-4,4-4
|
||||
h11.7c1.1,0,2-0.9,2-2V82.8c0-2.2,1.8-4,4-4h11.7c2.2,0,4,1.8,4,4v11.7c0,1.1,0.9,2,2,2h11.7c2.2,0,4,1.8,4,4v11.7
|
||||
c0,2.2-1.8,4-4,4h-11.7c-1.1,0-2,0.9-2,2v11.7C737.2,131.9,735.4,133.7,733.2,133.7z M703.9,98.5c-1.1,0-2,0.9-2,2v11.7
|
||||
c0,1.1,0.9,2,2,2h11.7c2.2,0,4,1.8,4,4v11.7c0,1.1,0.9,2,2,2h11.7c1.1,0,2-0.9,2-2v-11.7c0-2.2,1.8-4,4-4H751c1.1,0,2-0.9,2-2
|
||||
v-11.7c0-1.1-0.9-2-2-2h-11.7c-2.2,0-4-1.8-4-4V82.8c0-1.1-0.9-2-2-2h-11.7c-1.1,0-2,0.9-2,2v11.7c0,2.2-1.8,4-4,4H703.9z"/>
|
||||
<path id="path136" d="M825.6,372.4c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5c21.3,0,38.5,17.2,38.5,38.5
|
||||
C864,355.2,846.8,372.4,825.6,372.4z M825.6,297.5c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5c20.2,0,36.5-16.3,36.5-36.5
|
||||
C862,313.8,845.7,297.5,825.6,297.5z"/>
|
||||
<path id="path138" d="M825.6,225.5c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5c21.3,0,38.5,17.2,38.5,38.5
|
||||
C864,208.3,846.8,225.5,825.6,225.5z M825.6,150.6c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5c20.2,0,36.5-16.3,36.5-36.5
|
||||
C862,166.9,845.7,150.6,825.6,150.6z"/>
|
||||
<path id="path140" d="M899,299c-21.2,0-38.5-17.2-38.5-38.5S877.7,222,899,222c21.3,0,38.5,17.2,38.5,38.5S920.3,298.9,899,299z
|
||||
M899,224c-20.1,0-36.5,16.3-36.5,36.5S878.8,297,899,297c20.2,0,36.5-16.3,36.5-36.5S919.2,224,899,224z"/>
|
||||
<path id="path142" d="M752.2,299c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5c21.3,0,38.5,17.2,38.5,38.5
|
||||
C790.6,281.7,773.4,298.9,752.2,299z M752.2,224c-20.1,0-36.5,16.3-36.5,36.5s16.2,36.2,36.4,36.2s36.6-16,36.6-36.2
|
||||
C788.6,240.4,772.3,224,752.2,224z"/>
|
||||
<path id="path144" d="M771.7,750.2c-16,0-28.9-13-28.9-28.9s13-28.9,28.9-28.9s28.9,13,28.9,28.9l0,0
|
||||
C800.6,737.3,787.7,750.2,771.7,750.2z M771.7,694.3c-14.9,0-26.9,12.1-26.9,26.9s12.1,26.9,26.9,26.9s26.9-12.1,26.9-26.9
|
||||
S786.6,694.4,771.7,694.3z"/>
|
||||
<path id="path146" d="M762.5,533.4h-12.3c-0.6,0-1-0.4-1-1l0,0c1.7-39.6,33.4-71.3,73-73c0.3,0,0.5,0.1,0.7,0.3
|
||||
c0.2,0.2,0.3,0.4,0.3,0.7v12.3c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9C768.9,530.8,766,533.4,762.5,533.4z
|
||||
M751.3,531.4h11.2c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2
|
||||
C783.9,463.5,753.4,494,751.3,531.4z"/>
|
||||
<path id="path148" d="M822.3,612.1C822.3,612.1,822.2,612.1,822.3,612.1c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1h12.3
|
||||
c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9v12.3C823.3,611.6,822.8,612.1,822.3,612.1L822.3,612.1
|
||||
L822.3,612.1z M751.3,540c2.2,37.4,32.6,67.8,70,70v-11.2c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6
|
||||
c-0.3-2.5-2.4-4.3-4.9-4.3H751.3z"/>
|
||||
<path id="path150" d="M828.9,612.1c-0.6,0-1-0.4-1-1l0,0v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9
|
||||
c0.5-3.4,3.4-6,6.9-6H901c0.6,0,1,0.4,1,1l0,0C900.2,578.7,868.6,610.3,828.9,612.1C829,612.1,829,612.1,828.9,612.1L828.9,612.1
|
||||
L828.9,612.1z M888.7,540c-2.5,0-4.6,1.8-4.9,4.3c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9V610
|
||||
c37.4-2.2,67.8-32.6,70-70H888.7z"/>
|
||||
<path id="path152" d="M901,533.4h-12.3c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-12.3
|
||||
c0-0.3,0.1-0.5,0.3-0.7c0.2-0.2,0.5-0.3,0.7-0.3c39.6,1.7,71.3,33.4,73,73C902,532.9,901.6,533.3,901,533.4L901,533.4L901,533.4z
|
||||
M829.9,461.4v11.2c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h11.2
|
||||
C897.8,494,867.3,463.5,829.9,461.4z"/>
|
||||
<path id="path154" d="M825.6,612.2c-1.2,0-2.3,0-3.4-0.1c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9
|
||||
c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-12.3c-0.5,0-1-0.4-1-0.9c-0.1-1.1-0.1-2.2-0.1-3.4s0-2.3,0.1-3.4
|
||||
c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1
|
||||
c2.3-0.1,4.5-0.1,6.8,0c0.5,0,0.9,0.5,0.9,1v12.3c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3H901
|
||||
c0.5,0,1,0.4,1,0.9c0.1,1.1,0.1,2.2,0.1,3.4s0,2.3-0.1,3.4c0,0.5-0.5,0.9-1,0.9h-12.3c-2.5,0-4.6,1.8-4.9,4.3
|
||||
c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v12.3c0,0.5-0.4,1-0.9,1C827.9,612.1,826.8,612.2,825.6,612.2L825.6,612.2
|
||||
L825.6,612.2z M823.3,610.1c1.5,0.1,3.1,0.1,4.7,0v-11.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6
|
||||
h11.3v-4.6h-11.4c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3c-1.5-0.1-3.1-0.1-4.7,0v11.3
|
||||
c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-11.3v4.6h11.3c3.5,0,6.4,2.6,6.9,6
|
||||
c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9L823.3,610.1L823.3,610.1L823.3,610.1z"/>
|
||||
<path id="path1462" class="st4" d="M743,295.5c-6.3-1.7-11.3-3.9-16.5-9.1c-7.7-7.7-11.3-17-10.8-27.7c0.6-13.5,8-25,20-31
|
||||
c10.5-5.2,22.6-5.3,32.7-0.3c7.9,3.9,12.8,10,16.6,18c5.2,10.8,4.2,24.4-2.4,34.6c-5,7.6-13.5,13.7-22,15.7
|
||||
C755.7,296.8,747.8,296.7,743,295.5L743,295.5L743,295.5z"/>
|
||||
<path id="path1464" class="st4" d="M819.4,222.9c0-0.3-3.7-0.9-5.7-1.6c-3-1.1-5.9-2.6-8-4c-6.9-4.6-11.7-10.9-14.5-18.9
|
||||
c-1.3-3.8-2.1-5.2-2.1-11.4s0.7-7.2,2.1-11c3.9-11.1,11.8-19.1,22.8-23c4.2-1.5,5.2-2.3,11.6-2.3c6.4,0,7.3,0.8,11.6,2.3
|
||||
c14.5,5.2,24,17.6,24.7,32.9c0.5,10.6-2.7,19.5-10.2,26.9c-7.6,7.5-14.4,10.7-24.6,11C823.6,223.7,820.2,223,819.4,222.9
|
||||
L819.4,222.9L819.4,222.9z"/>
|
||||
<path id="path1466" class="st4" d="M891.7,296.5c-6.7-1-15.6-5.8-20.8-12.9c-3-4.1-6.2-10.7-7.3-15.7
|
||||
c-2.8-13.2,2.6-27.9,13.3-35.9c20-15.1,48.1-6.7,56.4,17c1.9,5.3,3,13.3,1.7,19.2c-1.5,6.8-4.9,12.9-10.2,18.2
|
||||
c-5.3,5.2-9.9,8-16.4,9.6C903.5,297.2,896.3,297.2,891.7,296.5L891.7,296.5L891.7,296.5z"/>
|
||||
<path id="path1468" class="st4" d="M820.4,369.9c-8.1-1.3-14.2-4-20.6-10.3c-3.8-3.7-5.4-6.2-7.2-10c-7.6-15.8-3-33.1,10.8-44.1
|
||||
c6.4-5.1,13.6-7.6,22.1-7.6c29.9,0,46.7,33.8,28.7,58c-2.8,3.8-6.3,7.5-10.5,9.8C836.7,369.8,828.1,371.1,820.4,369.9L820.4,369.9
|
||||
L820.4,369.9z"/>
|
||||
<path id="path1500" class="st6" d="M823.6,602.7c-0.3-8.9-0.8-9.7-10.1-11.9c-21.1-4.8-37.2-20.1-42.6-41.3
|
||||
c-0.6-2.2-1.1-5.2-1.1-5.9s-1-2.2-2.2-3.5l-2.3-2l-6.9-0.3h-7v-4h5.9c6.6,0,9.9-1,11.2-3.4c0.4-0.8,1.5-3.9,2-7
|
||||
c2.7-16.3,14.9-30.7,29.5-38c4.7-2.4,11.4-4.6,15.5-5.4c6.6-1.1,8.2-3.6,8.2-12.8v-5.9h4v6.9c0,6.6,0.1,7,1.8,8.8
|
||||
c1.5,1.6,3.9,1.7,9.5,3.1c20.4,5,35.3,20.5,40.7,40.1c0.8,2.9,1.8,6.4,2.2,7.8c1.2,4.3,3.8,5.6,11.7,5.6h6.5v4h-6.6
|
||||
c-7,0-9.9,0.8-10.8,3.1c-0.3,0.7-1.3,4.6-2.1,8c-5.4,21.4-21.3,36.7-42.1,41.5c-9.9,2.3-10.7,3.2-10.7,12.8v6.3h-3.8L823.6,602.7
|
||||
L823.6,602.7z"/>
|
||||
<path id="path1504" class="st7" d="M752.2,526.5c1.8-15.3,8.9-31.2,20.4-43c11.9-12.2,27.5-19.2,45.7-21.6l2.8-0.4v6.2
|
||||
c0,7.9-0.1,8.9-6.8,10.2c-22.3,4.6-41.8,22.1-46.1,44.2c-1.8,9.1-2.4,9.1-11.1,9.1h-5.4L752.2,526.5L752.2,526.5z"/>
|
||||
<path id="path1506" class="st7" d="M811.2,608.2c-32.2-6.9-55.7-32.9-59.4-65.6l-0.2-2.1h6.4c6.9,0,6.8,0,7.8,1
|
||||
c1.3,1.4,1.5,3.8,2.4,7.9c4.8,21.2,24.2,39.1,46.6,44c6.9,1.5,6.4,2.7,6.4,10.3v5.9l-2.1,0C817.8,609.5,814.3,608.9,811.2,608.2
|
||||
L811.2,608.2L811.2,608.2z"/>
|
||||
<path id="path1508" class="st7" d="M830,603c-0.3-7.3,1-8.2,5.3-9c4.8-0.8,11.1-2.9,16.3-5.5c15.8-7.7,27.1-22,31.6-39.9
|
||||
c1-4,1.6-7.2,2.2-7.7c0.7-0.5,3.9-0.5,7.8-0.5h6.2l-0.4,3.8c-3.8,33.2-31.8,61.3-64.8,65l-4,0.5L830,603L830,603z"/>
|
||||
<path id="path1510" class="st7" d="M885.4,529.8c-1.2-1.1-1.3-3-2.1-6.7c-4.4-20.5-19-36.6-39.3-43.5c-2.4-0.8-5.8-1.7-7.5-2
|
||||
c-1.9-0.3-3.9-0.6-4.8-1.5c-1.4-1.4-1.3-2.6-1.3-8.2v-6.2l2.5,0.3c19,2.5,32.7,9.2,45.4,22.1c10.4,10.5,17.4,23.8,20.2,38.1
|
||||
c0.6,2.9,1,6.1,1,7.1v1.9h-5.9C888.3,531.3,886.8,531.1,885.4,529.8L885.4,529.8L885.4,529.8z"/>
|
||||
<path id="path1512" class="st4" d="M720.3,131c-0.5-0.6-0.6-1.7-0.6-7.6v-6.9l-1.1-1.2l-1.1-1.2l-7.1-0.1
|
||||
c-4.1-0.1-6.5,0.5-7.6-0.2c-1.3-0.8-0.9-3.1-0.9-7.6s0.1-6.3,0.5-6.8c0.5-0.7,1.1-0.7,7.3-0.8c3.7-0.1,7.1-0.2,7.6-0.3
|
||||
c0.5-0.1,1.2-0.7,1.6-1.4c0.7-1.1,0.7-1.9,0.7-7.8c0-3.8,0.2-6.8,0.4-7.3c0.4-0.7,0.9-0.7,7.3-0.7s7,0.1,7.3,0.7
|
||||
c0.2,0.4,0.4,3.5,0.4,7.3c0,5.8,0.1,6.7,0.7,7.8c0.4,0.7,1.1,1.3,1.6,1.4s3.9,0.2,7.6,0.3c6.2,0.1,6.8,0.2,7.3,0.8
|
||||
c0.4,0.6,0.5,2.2,0.5,6.8s0.7,7.2-0.9,7.9c-1.2,0.5-3.8-0.1-7.6-0.1l-7.1,0.1l-1.1,1.2l-1.1,1.2v6.9c0,6.2-0.1,7-0.7,7.6
|
||||
c-0.6,0.5-1.7,0.6-7.1,0.6C721.7,131.7,720.9,131.6,720.3,131L720.3,131L720.3,131z"/>
|
||||
<path id="path1514" class="st7" d="M766.6,726.4v-5.3h10.5v10.5h-10.5V726.4L766.6,726.4z"/>
|
||||
<path id="path1518" class="st7" d="M766,761.6c-14.8-2.3-27.2-12.3-32.4-26.2c-7.5-20,2.3-43,22-51.4c6.1-2.6,8-3.5,15.7-3.5
|
||||
c6.5,0,7.9,0.6,11.3,1.6c14.4,4.4,24.6,14.9,28.6,29.4c0.8,2.9,1.1,5.2,1.1,10.7c0,5.5-0.3,6.2-1.1,9c-4.8,17.7-20,30-38.1,30.5
|
||||
C770.5,761.9,767.4,761.8,766,761.6L766,761.6L766,761.6z M778.1,749.7c11.9-2.6,21.3-13,22.5-25.1c2.2-21.5-18.1-37.7-38.5-30.7
|
||||
c-4.2,1.4-7,3.3-10.8,7.1c-2.8,2.8-3.8,4.1-5.3,7.2c-2.6,5.1-3.3,8.7-3,14.6c0.3,6.8,2.2,11.7,6.3,16.9
|
||||
C755.9,748,767.4,752,778.1,749.7L778.1,749.7L778.1,749.7z"/>
|
||||
<path id="path1520" class="st9" d="M648.2,714.3c-1.3-0.8-2.3-0.9-2.5-5.3c-0.2-4.3,0.1-13.5,0.1-32.6c0-32.8-0.5-35.2,0.6-36.3
|
||||
c0.1-0.1,0.1-0.2,0.2-0.2c1.1-1.5,2.7-2.1,4.9-2.1h1.9V715h-2C650.1,715,648.9,714.8,648.2,714.3L648.2,714.3L648.2,714.3z"/>
|
||||
<path id="path1522" class="st9" d="M649.6,312.1c-0.5-0.1-1.3-0.4-1.8-0.8c-0.8-0.5-1.5-0.8-1.8-2.7c-0.5-3.2-0.2-11.4-0.2-35.1
|
||||
c0-19.3-0.5-28.4-0.4-32.5c0.1-2.7,0.8-3.2,1-3.6c0.9-1.6,2.4-2.3,4.8-2.3h2.1v77.3l-1.4,0C651.2,312.3,650.1,312.2,649.6,312.1
|
||||
L649.6,312.1L649.6,312.1z"/>
|
||||
<path id="path1524" class="st8" d="M978,126.4c-10.1-20.6-21.9-37.2-38.2-53.9c-34.8-35.7-78.7-57-129.6-63.1
|
||||
c-5.1-0.6-13.1-0.8-40.9-1l-34.6-0.2V6.9c0-1,0-3,1.4-3.7l2.1-1.1l30.4,0.2c16.9,0.1,33.6,0.2,37,0.5
|
||||
c50.8,3.9,97.1,24.6,133.3,59.5c17.6,16.9,31.5,35.7,42.8,57.9c4.3,8.4,4.9,10.1,4.2,11.8c-0.4,1.1-2.7,4.2-3.2,4.1
|
||||
C982.6,136.1,980.5,131.5,978,126.4L978,126.4L978,126.4z"/>
|
||||
<path id="path1530" class="st4" d="M646.8,903.8c-0.6-0.5-1.7-1.2-1.6-5c0.3-6.7-0.2-27.2-0.1-79.1l0.3-82.6l2.6-6.5l7.9-15
|
||||
l0.1-39.4l-0.4-39.6l-7.1-13.2l-2.9-7.7l-0.4-7.3l0.1-48l-0.1-22.1l0.1-34.1l0.1-10.5V483l-0.1-8.6l0-25.6v-19.4l-0.2-27.5
|
||||
l0.1-21.6l0-11l0.1-19.6l0-10.2l0.5-5.7l1.9-5.8l3-5.5l5.3-9.8v-39.5l-0.4-39.6l-5.3-9.8l-2.7-5.3l-1.8-5.1l-0.7-7.6l0.2-13.3
|
||||
l-0.1-12.2v-11.1l-0.1-10.9l0-9.9V142l0-2.9l0.1-17.4l0-21.5V89.4l-0.1-8.4l0-5.1l-0.2-5.9l2.2-3.1l3.2-1.1l3.2,0.1
|
||||
c1.4,0,2.7,0.1,3.9,0.2c0.9,0.1,1.8,0.1,2.6,0.4c1,0.4,1.7,1,2,1.3c0.2,0.2,1.2,1.7,1.3,4.8c0.1,2.1,0,4.7,0,8.3
|
||||
c0,4.1,0.1,9.7,0,16.4c-0.1,10,0,23.1-0.1,40.4c0,13.2,0.2,28.7,0.1,47c-0.2,62.8-0.2,158-0.2,301l0,416.2l-1.3,1.8
|
||||
C660.4,906.2,649.5,906.5,646.8,903.8L646.8,903.8L646.8,903.8z"/>
|
||||
<path id="path1532" class="st4" d="M665.8,465.1V72.7h8.6v784.7h-8.6V465.1L665.8,465.1z"/>
|
||||
<ellipse id="path3879" class="st14" cx="771.6" cy="721.1" rx="40.3" ry="40.3"/>
|
||||
<ellipse id="path3881" class="st15" cx="771.7" cy="721.4" rx="34.1" ry="34.5"/>
|
||||
<path id="path96" d="M771.7,694.3l-26.8,26.4h7.7v22.5h38.5v-22.5h7.2L771.7,694.3L771.7,694.3z M779.5,735.2h-15.2v-14.5h15.2
|
||||
V735.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 32 KiB |
185
src/Ryujinx.Ava/Assets/Icons/Controller_JoyConRight.svg
Normal file
185
src/Ryujinx.Ava/Assets/Icons/Controller_JoyConRight.svg
Normal file
@@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1000.4 356.1" style="enable-background:new 0 0 1000.4 356.1;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{opacity:0.1;}
|
||||
.st1{fill:#FF5F55;}
|
||||
.st2{fill:#FF5F53;}
|
||||
.st3{fill:#FFFFFF;}
|
||||
.st4{fill:#1A1A1A;stroke:#000000;}
|
||||
.st5{fill:#1A1A1A;stroke:#1A1A1A;}
|
||||
.st6{fill:#1A1A1A;stroke:#4D4D4D;}
|
||||
.st7{stroke:#000000;}
|
||||
.st8{stroke:#4D4D4D;}
|
||||
.st9{fill:#999595;stroke:#000000;stroke-width:2.39;stroke-linecap:round;stroke-linejoin:round;}
|
||||
.st10{fill:#3A3D40;stroke:#000000;stroke-width:2.73;stroke-linecap:round;stroke-linejoin:round;}
|
||||
</style>
|
||||
<g id="g315">
|
||||
<g id="g64" class="st0">
|
||||
<path id="path36" class="st1" d="M766.5,11.2H687V7c0-3.3,2.7-6,6-6h67.6c3.3,0,6,2.7,6,6L766.5,11.2L766.5,11.2z"/>
|
||||
<path id="path38" class="st1" d="M363.8,11.2h-79.5V7c0-3.3,2.7-6,6-6h67.6c3.3,0,6,2.7,6,6L363.8,11.2L363.8,11.2z"/>
|
||||
<path id="path40" class="st1" d="M865.5,342.3l-3.4-3.4c78-33.2,128.7-109.8,128.7-194.7V90h2.6c3.3,0,6,2.7,6,6v51.2
|
||||
c0,84.8-49.8,161.7-127.2,196.4C869.9,344.6,867.3,344.1,865.5,342.3L865.5,342.3L865.5,342.3z"/>
|
||||
<path id="path42" class="st1" d="M905.9,92.8h11.7c1.6,0,3-1.3,3-3V78.1c0-1.6-1.3-3-3-3l0,0h-11.7c-1.6,0-3-1.3-3-3V60.4
|
||||
c0-1.6-1.3-3-3-3l0,0h-11.7c-1.6,0-3,1.3-3,3v11.7c0,1.6-1.3,3-3,3l0,0h-11.7c-1.6,0-3,1.3-3,3v11.7c0,1.6,1.3,3,3,3l0,0h11.7
|
||||
c1.6,0,3,1.3,3,3v11.7c0,1.6,1.3,3,3,3l0,0h11.7c1.6,0,3-1.3,3-3V95.8C902.9,94.1,904.3,92.8,905.9,92.8L905.9,92.8z"/>
|
||||
<circle id="circle44" class="st1" cx="666.5" cy="182.2" r="37.5"/>
|
||||
<circle id="circle46" class="st1" cx="813.3" cy="182.2" r="37.5"/>
|
||||
<circle id="circle48" class="st1" cx="739.9" cy="255.6" r="37.5"/>
|
||||
<circle id="circle50" class="st1" cx="739.9" cy="108.8" r="37.5"/>
|
||||
<circle id="circle52" class="st1" cx="279.1" cy="128.3" r="27.9"/>
|
||||
<path id="path54" class="st1" d="M540.1,178.9h-12.3c-3,0-5.5-2.2-5.9-5.2c-3.7-25.2-23.5-45-48.7-48.7c-2.9-0.4-5.1-2.9-5.2-5.9
|
||||
v-12.3C507.1,108.5,538.4,139.8,540.1,178.9L540.1,178.9L540.1,178.9z"/>
|
||||
<path id="path56" class="st1" d="M401.6,178.9h-12.3c1.7-39.1,33-70.3,72-72.1v12.3c0,3-2.2,5.5-5.2,5.9
|
||||
c-25.2,3.7-45,23.5-48.7,48.7C407.1,176.7,404.6,178.9,401.6,178.9L401.6,178.9L401.6,178.9z"/>
|
||||
<path id="path58" class="st1" d="M461.4,257.6c-39.1-1.7-70.3-33-72-72.1h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7
|
||||
c2.9,0.4,5.1,2.9,5.2,5.9L461.4,257.6L461.4,257.6z"/>
|
||||
<path id="path60" class="st1" d="M468,257.6v-12.3c0-3,2.2-5.5,5.2-5.9c25.2-3.7,45-23.5,48.7-48.7c0.4-2.9,2.9-5.1,5.9-5.2h12.3
|
||||
C538.4,224.6,507.1,255.9,468,257.6L468,257.6L468,257.6z"/>
|
||||
<path id="path62" class="st1" d="M464.7,257.7c-1.1,0-2.2,0-3.3-0.1v-12.3c0-3-2.2-5.5-5.2-5.9c-25.2-3.7-45-23.5-48.7-48.7
|
||||
c-0.4-2.9-2.9-5.1-5.9-5.2h-12.3c-0.1-1.1-0.1-2.2-0.1-3.3s0-2.2,0.1-3.3h12.3c3,0,5.5-2.2,5.9-5.2c3.7-25.2,23.5-45,48.7-48.7
|
||||
c2.9-0.4,5.1-2.9,5.2-5.9v-12.3c1.1-0.1,2.2-0.1,3.3-0.1s2.2,0,3.3,0.1v12.3c0,3,2.2,5.5,5.2,5.9c25.2,3.7,45,23.5,48.7,48.7
|
||||
c0.4,2.9,2.9,5.1,5.9,5.2h12.3c0.1,1.1,0.1,2.2,0.1,3.3s0,2.2-0.1,3.3h-12.3c-3,0-5.5,2.2-5.9,5.2c-3.7,25.2-23.5,45-48.7,48.7
|
||||
c-2.9,0.4-5.1,2.9-5.2,5.9v12.3C466.9,257.6,465.8,257.7,464.7,257.7L464.7,257.7z"/>
|
||||
</g>
|
||||
<path id="path72" d="M93.8,14.9V7c0-3.6,2.9-6.4,6.5-6.5h157.2c4.9,0,9.6,1.2,13.9,3.4l13,6.7h79.2l13-6.7c4.3-2.2,9.1-3.4,14-3.4
|
||||
h269.7c4.9,0,9.6,1.2,13.9,3.4l13,6.7h79.2l13-6.7c4.3-2.2,9.1-3.4,14-3.4h135.8c3.6,0,6.4,2.9,6.5,6.5v7.9c0,3.6-2.9,6.4-6.5,6.5
|
||||
c-276.3,1.1-552.6,1.2-828.9,0C96.7,21.3,93.8,18.4,93.8,14.9L93.8,14.9L93.8,14.9z M934.7,7c0-3-2.4-5.5-5.5-5.5H793.4
|
||||
c-4.7,0-9.3,1.1-13.5,3.3l-13.1,6.8c-0.1,0-0.1,0.1-0.2,0.1h-79.5c-0.1,0-0.2,0-0.2-0.1l-13.1-6.8c-4.2-2.2-8.8-3.3-13.5-3.3H390.6
|
||||
c-4.7,0-9.3,1.1-13.5,3.3L364,11.6c-0.1,0-0.1,0.1-0.2,0.1h-79.5c-0.1,0-0.2,0-0.2-0.1L271,4.8c-4.2-2.2-8.8-3.3-13.5-3.3H100.3
|
||||
c-3,0-5.5,2.4-5.5,5.5v7.9c0,3,2.4,5.5,5.5,5.5h828.9c3,0,5.5-2.4,5.5-5.5L934.7,7L934.7,7z"/>
|
||||
<path id="path74" d="M141.5,32.1V20.8c0-0.3,0.2-0.5,0.5-0.5l0,0l786.4,0.8c0.3,0,0.5,0.2,0.5,0.5v11.3c0,0.3-0.2-0.3-0.5-0.3H142
|
||||
C141.7,32.6,141.5,32.4,141.5,32.1z M142.5,22.2v9.4L928,32.4V22.1l-8.8,1c-256.1-0.6-511.8,4.5-768.3-1.1
|
||||
C148.1,21.9,145.3,22.2,142.5,22.2L142.5,22.2z"/>
|
||||
<path id="path76" d="M0.2,144V37.8c0-3.6,2.9-6.5,6.5-6.5h978c3.6,0,6.5,2.9,6.5,6.5V144c0,116.8-95.1,211.9-211.9,211.9H212.1
|
||||
C95.1,355.9,0.2,261.1,0.2,144L0.2,144L0.2,144z M990.1,37.8c0-3-2.4-5.5-5.5-5.5H6.6c-3,0-5.5,2.4-5.5,5.5V144
|
||||
c0,116.3,94.6,210.9,210.9,210.9h567.3c116.3,0,210.9-94.6,210.9-210.9L990.1,37.8L990.1,37.8z"/>
|
||||
<path id="path128" d="M686.1,11.2V7c0-3.8,3.1-6.9,7-7h67.6c3.8,0,6.9,3.1,7,7v4.2c0,0.6-0.4,1-1,1l0,0h-79.5
|
||||
C686.5,12.2,686.1,11.7,686.1,11.2L686.1,11.2z M765.6,7c0-2.7-2.2-5-5-5H693c-2.7,0-5,2.2-5,5v3.2h77.5L765.6,7L765.6,7z"/>
|
||||
<path id="path130" d="M283.3,11.2V7c0-3.8,3.1-6.9,7-7h67.6c3.8,0,6.9,3.1,7,7v4.2c0,0.6-0.4,1-1,1l0,0h-79.5
|
||||
C283.8,12.2,283.3,11.7,283.3,11.2L283.3,11.2z M362.8,7c0-2.7-2.2-5-5-5h-67.6c-2.7,0-5,2.2-5,5v3.2h77.5L362.8,7L362.8,7z"/>
|
||||
<path id="path1240" class="st2" d="M1.8,162.1c2.4,26.6,9.2,50.5,21.8,76c2.5,5.1,5.2,10,8,14.9c11.3,19.1,27.1,36.3,41.7,49.6
|
||||
c28,25.5,70.1,45.5,116.5,51.4c0.7,0.1,4.3,0.4,6.8,0.4c6.9-0.1,20,0.7,38.3,0.8c77.5,0.7,244,1.1,376.4,1.1
|
||||
c101.2,0,182.5-0.3,188.9-1c26.1-2.7,49.1-9.3,72.1-20.8c63.9-31.8,107.4-93,116.7-164c1.5-11.4,1.6-60.7,1.3-96.6
|
||||
c-0.1-7.7,0.1-14.1-0.1-20.1c-0.2-7.5,0.1-12.9-0.2-16.2c-0.2-1.7-0.8-3-1-3.2c-0.1-0.1-1.4-1.4-3.3-1.5c-5.2-0.3-17.1-0.3-38-0.4
|
||||
c-4.2,0-8.8-0.1-13.8-0.1c-4.9,0-10.1,0.1-15.8,0.1c-8.8,0-18.6,0.1-29.2,0.1c-9.8,0-20.5-0.2-32,0c-9,0.2-18.4,0.2-28.4,0.2
|
||||
c-15.1-0.1-31.1,0.6-49,0.3c-15-0.2-30,0.1-46.9,0c-11.1-0.1-22.6,0.1-34.6,0c-7.2-0.1-14.5,0-22.1-0.1c-52.1-0.5-112.2,0-180.3,0
|
||||
c-254.3,0-376.1-0.3-435.2,0c-7.7,0-14.5-0.2-20.2-0.1c-2.2,0-4.3,0-6.2,0c-3.3,0-6.6,0-9.3,0c-2.9,0-5.8-0.1-8,0
|
||||
c-5,0.1-8.1,0.1-10,0.3c-2.8,0.3-3.6,1.3-3.8,1.6c-0.2,0.2-0.9,1.3-1.1,3.1c-0.4,4.5-0.3,14.6-0.2,27.1c0.1,9.9,0.2,21.3,0.2,32.8
|
||||
C1.7,129.3,1.5,162.4,1.8,162.1L1.8,162.1L1.8,162.1z"/>
|
||||
<path id="path78" d="M237.2,128.3c0-23.1,18.7-41.9,41.9-41.9s41.9,18.7,41.9,41.9s-18.7,41.9-41.9,41.9l0,0
|
||||
C256,170.1,237.3,151.4,237.2,128.3z M320,128.3c0-22.6-18.3-40.9-40.9-40.9s-40.9,18.3-40.9,40.9s18.3,40.9,40.9,40.9l0,0
|
||||
C301.7,169.1,320,150.9,320,128.3z"/>
|
||||
<path id="path92" class="st3" d="M723.9,269.2v-4.7l7-2.2l-0.3-12.4l-6.7-3.2v-4.5l35.2,9.9l-3.2,6.7L723.9,269.2z M735.2,260.5
|
||||
l14.6-4.9L735,251L735.2,260.5L735.2,260.5z"/>
|
||||
<path id="path132" d="M861.1,338.9v-0.2c0.1-0.3,0.3-0.6,0.6-0.7c77.7-33,128.2-109.3,128.1-193.8V90c0-0.6,0.4-1,1-1l0,0h2.6
|
||||
c3.8,0,6.9,3.1,7,7v51.2c-0.1,85.2-50.1,162.4-127.8,197.3c-2.6,1.2-5.7,0.6-7.8-1.5l-3.4-3.4C861.2,339.4,861.1,339.1,861.1,338.9
|
||||
L861.1,338.9z M991.8,91v53.2c0.1,84.7-50.2,161.3-128,195l2.4,2.4l0,0c1.4,1.5,3.6,1.9,5.5,1.1c77-34.6,126.6-111.1,126.7-195.5
|
||||
V96c0-2.7-2.2-5-5-5H991.8z"/>
|
||||
<path id="path134" d="M866.7,89.8V78.1c0-2.2,1.8-4,4-4h11.7c1.1,0,2-0.9,2-2V60.4c0-2.2,1.8-4,4-4h11.7c2.2,0,4,1.8,4,4v11.7
|
||||
c0,1.1,0.9,2,2,2h11.5c2.2,0,4,1.8,4,4v11.7c0,2.2-1.8,4-4,4h-11.7c-1.1,0-2,0.9-2,2v11.7c0,2.2-1.8,4-4,4h-11.7c-2.2,0-4-1.8-4-4
|
||||
V95.8c0-1.1-0.9-2-2-2h-11.7C868.5,93.8,866.7,92,866.7,89.8z M901.9,60.5c0-1.1-0.9-2-2-2h-11.7c-1.1,0-2,0.9-2,2v11.7
|
||||
c0,2.2-1.8,4-4,4h-11.7c-1.1,0-2,0.9-2,2v11.7c0,1.1,0.9,2,2,2h11.7c2.2,0,4,1.8,4,4v11.7c0,1.1,0.9,2,2,2h11.7c1.1,0,2-0.9,2-2
|
||||
V95.9c0-2.2,1.8-4,4-4h11.7c1.1,0,2-0.9,2-2V78.2c0-1.1-0.9-2-2-2h-11.7c-2.2,0-4-1.8-4-4V60.5z"/>
|
||||
<path id="path136" d="M628,182.2c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5s-17.2,38.5-38.5,38.5
|
||||
C645.2,220.6,628,203.4,628,182.2z M702.9,182.2c0-20.1-16.3-36.5-36.5-36.5s-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5
|
||||
C686.6,218.6,702.9,202.3,702.9,182.2z"/>
|
||||
<path id="path138" d="M774.9,182.2c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5s-17.2,38.5-38.5,38.5
|
||||
C792.1,220.6,774.9,203.4,774.9,182.2z M849.8,182.2c0-20.1-16.3-36.5-36.5-36.5c-20.2,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5
|
||||
C833.5,218.6,849.8,202.3,849.8,182.2z"/>
|
||||
<path id="path140" d="M701.4,255.6c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5s-17.2,38.5-38.5,38.5S701.5,276.9,701.4,255.6z
|
||||
M776.4,255.6c0-20.1-16.3-36.5-36.5-36.5s-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5S776.4,275.8,776.4,255.6z"/>
|
||||
<path id="path142" d="M701.4,108.8c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5s-17.2,38.5-38.5,38.5
|
||||
C718.7,147.2,701.5,130,701.4,108.8z M776.4,108.8c0-20.1-16.3-36.5-36.5-36.5s-36.2,16.2-36.2,36.4s16,36.6,36.2,36.6
|
||||
C760,145.2,776.4,128.9,776.4,108.8z"/>
|
||||
<path id="path144" d="M250.2,128.3c0-16,13-28.9,28.9-28.9s28.9,13,28.9,28.9s-13,28.9-28.9,28.9l0,0
|
||||
C263.1,157.2,250.2,144.3,250.2,128.3z M306.1,128.3c0-14.9-12.1-26.9-26.9-26.9s-26.9,12.1-26.9,26.9s12.1,26.9,26.9,26.9
|
||||
S306,143.2,306.1,128.3z"/>
|
||||
<path id="path146" d="M467,119.1v-12.3c0-0.6,0.4-1,1-1l0,0c39.6,1.7,71.3,33.4,73,73c0,0.3-0.1,0.5-0.3,0.7s-0.4,0.3-0.7,0.3
|
||||
h-12.3c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9C469.6,125.5,467,122.6,467,119.1z M469,107.9v11.2
|
||||
c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3H539C536.9,140.5,506.4,110,469,107.9z"/>
|
||||
<path id="path148" d="M388.3,178.9C388.3,178.9,388.3,178.8,388.3,178.9c1.7-39.6,33.4-71.3,73-73c0.6,0,1,0.4,1,1v12.3
|
||||
c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-12.3C388.8,179.9,388.3,179.4,388.3,178.9L388.3,178.9
|
||||
L388.3,178.9z M460.4,107.9c-37.4,2.2-67.8,32.6-70,70h11.2c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6
|
||||
c2.5-0.3,4.3-2.4,4.3-4.9V107.9z"/>
|
||||
<path id="path150" d="M388.3,185.5c0-0.6,0.4-1,1-1l0,0h12.3c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9
|
||||
c3.4,0.5,6,3.4,6,6.9v12.3c0,0.6-0.4,1-1,1l0,0C421.7,256.8,390.1,225.2,388.3,185.5C388.3,185.6,388.3,185.6,388.3,185.5
|
||||
L388.3,185.5L388.3,185.5z M460.4,245.3c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-11.2
|
||||
c2.2,37.4,32.6,67.8,70,70V245.3z"/>
|
||||
<path id="path152" d="M467,257.6v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6h12.3
|
||||
c0.3,0,0.5,0.1,0.7,0.3s0.3,0.5,0.3,0.7c-1.7,39.6-33.4,71.3-73,73C467.5,258.6,467.1,258.2,467,257.6L467,257.6L467,257.6z
|
||||
M539,186.5h-11.2c-2.5,0-4.6,1.8-4.9,4.3c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v11.2
|
||||
C506.4,254.4,536.9,223.9,539,186.5z"/>
|
||||
<path id="path154" d="M388.2,182.2c0-1.2,0-2.3,0.1-3.4c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3
|
||||
c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1c1.1-0.1,2.2-0.1,3.4-0.1s2.3,0,3.4,0.1
|
||||
c0.5,0,0.9,0.5,0.9,1v12.3c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h12.3c0.5,0,1,0.4,1,0.9
|
||||
c0.1,2.3,0.1,4.5,0,6.8c0,0.5-0.5,0.9-1,0.9h-12.3c-2.5,0-4.6,1.8-4.9,4.3c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9
|
||||
v12.3c0,0.5-0.4,1-0.9,1c-1.1,0.1-2.2,0.1-3.4,0.1s-2.3,0-3.4-0.1c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9
|
||||
c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-12.3c-0.5,0-1-0.4-1-0.9C388.3,184.5,388.2,183.4,388.2,182.2L388.2,182.2
|
||||
L388.2,182.2z M390.3,179.9c-0.1,1.5-0.1,3.1,0,4.7h11.3c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9
|
||||
v11.3h4.6v-11.4c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6h11.3c0.1-1.5,0.1-3.1,0-4.7h-11.3
|
||||
c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3h-4.6V119c0,3.5-2.6,6.4-6,6.9
|
||||
c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-11.3V179.9L390.3,179.9z"/>
|
||||
<path id="path1462" class="st4" d="M705,99.6c1.7-6.3,3.9-11.3,9.1-16.5c7.7-7.7,17-11.3,27.7-10.8c13.5,0.6,25,8,31,20
|
||||
c5.2,10.5,5.3,22.5,0.3,32.7c-4,7.9-10,12.8-18,16.6c-10.8,5.2-24.4,4.2-34.6-2.4c-7.7-5-13.7-13.5-15.7-22
|
||||
C703.6,112.3,703.7,104.4,705,99.6L705,99.6L705,99.6z"/>
|
||||
<path id="path1464" class="st4" d="M777.6,176c0.3,0,0.9-3.7,1.6-5.7c1.1-3,2.6-5.9,4-8c4.6-6.9,10.9-11.7,18.9-14.5
|
||||
c3.8-1.3,5.2-2.1,11.5-2.1s7.2,0.7,11,2.1c11.1,3.9,19.1,11.8,23,22.8c1.5,4.2,2.3,5.2,2.3,11.6s-0.8,7.3-2.3,11.6
|
||||
c-5.2,14.5-17.6,24-32.9,24.7c-10.6,0.5-19.5-2.7-26.9-10.2c-7.5-7.6-10.7-14.4-11-24.6C776.7,180.2,777.4,176.7,777.6,176
|
||||
L777.6,176L777.6,176z"/>
|
||||
<path id="path1466" class="st4" d="M704,248.2c1-6.7,5.8-15.6,12.9-20.8c4.1-3,10.7-6.2,15.7-7.3c13.2-2.8,27.9,2.6,35.9,13.3
|
||||
c15.2,20,6.7,48.1-17,56.4c-5.3,1.9-13.3,3-19.2,1.7c-6.8-1.5-12.9-4.9-18.2-10.2c-5.2-5.3-8-9.9-9.6-16.4
|
||||
C703.3,260.1,703.3,252.9,704,248.2L704,248.2L704,248.2z"/>
|
||||
<path id="path1468" class="st4" d="M630.6,177c1.3-8.1,4-14.2,10.3-20.6c3.7-3.8,6.2-5.4,10-7.2c15.8-7.6,33.1-3,44.1,10.8
|
||||
c5.1,6.4,7.6,13.6,7.6,22.1c0,29.9-33.8,46.7-58,28.7c-3.8-2.8-7.5-6.3-9.8-10.5C630.7,193.3,629.4,184.7,630.6,177L630.6,177
|
||||
L630.6,177z"/>
|
||||
<path id="path1500" class="st5" d="M397.8,180.2c8.9-0.3,9.7-0.8,11.9-10.1c4.8-21.1,20.1-37.2,41.3-42.6c2.2-0.5,5.2-1.1,5.9-1.1
|
||||
s2.2-1,3.5-2.2l2-2.3l0.3-6.9v-7h4v5.9c0,6.6,1,9.9,3.4,11.2c0.8,0.4,3.9,1.5,7,2c16.3,2.7,30.7,14.9,38,29.5
|
||||
c2.4,4.7,4.6,11.4,5.4,15.5c1.1,6.6,3.6,8.2,12.8,8.2h5.9v4H532c-6.6,0-7,0.1-8.8,1.8c-1.6,1.5-1.7,3.9-3.1,9.5
|
||||
c-5,20.4-20.5,35.3-40.2,40.7c-2.9,0.8-6.4,1.8-7.8,2.2c-4.3,1.2-5.6,3.8-5.6,11.7v6.5h-4V250c0-7-0.8-9.9-3.1-10.8
|
||||
c-0.7-0.3-4.6-1.3-8-2.1c-21.4-5.4-36.7-21.3-41.5-42.1c-2.3-10-3.2-10.7-12.8-10.7h-6.3v-3.8L397.8,180.2L397.8,180.2z"/>
|
||||
<path id="path1504" class="st6" d="M473.9,108.8c15.3,1.8,31.2,8.9,43,20.4c12.2,12,19.2,27.5,21.6,45.7l0.4,2.8h-6.2
|
||||
c-7.9,0-8.9-0.1-10.2-6.8c-4.6-22.3-22.1-41.8-44.2-46.1c-9.1-1.8-9.1-2.4-9.1-11.1v-5.4L473.9,108.8L473.9,108.8z"/>
|
||||
<path id="path1506" class="st6" d="M392.2,167.8c6.9-32.2,32.9-55.7,65.6-59.4l2.1-0.2v6.4c0,6.9,0,6.8-1,7.8
|
||||
c-1.4,1.3-3.8,1.5-7.9,2.4c-21.2,4.8-39.1,24.2-44,46.6c-1.5,6.9-2.7,6.4-10.3,6.4h-5.9l0-2.1C391,174.4,391.5,170.9,392.2,167.8
|
||||
L392.2,167.8L392.2,167.8z"/>
|
||||
<path id="path1508" class="st6" d="M397.4,186.6c7.3-0.3,8.2,1,9,5.3c0.8,4.8,2.9,11.1,5.5,16.3c7.7,15.8,22,27.1,39.9,31.6
|
||||
c4,1,7.2,1.6,7.7,2.2c0.5,0.7,0.5,3.9,0.5,7.8v6.2l-3.8-0.4c-33.2-3.8-61.3-31.8-65-64.8l-0.5-4L397.4,186.6L397.4,186.6z"/>
|
||||
<path id="path1510" class="st6" d="M470.6,242c1.1-1.2,3-1.3,6.7-2.1c20.5-4.4,36.6-19,43.5-39.3c0.8-2.4,1.7-5.8,2-7.5
|
||||
c0.3-1.9,0.6-3.9,1.5-4.8c1.4-1.4,2.6-1.3,8.2-1.3h6.2l-0.3,2.5c-2.5,19-9.2,32.7-22.1,45.4c-10.6,10.4-23.8,17.4-38.2,20.2
|
||||
c-2.9,0.5-6.1,1-7.1,1h-1.9v-5.9C469.2,244.9,469.3,243.4,470.6,242L470.6,242L470.6,242z"/>
|
||||
<path id="path1512" class="st4" d="M869.4,76.9c0.6-0.5,1.7-0.6,7.5-0.6h6.9l1.2-1.1l1.2-1.1l0.1-7.1c0.1-4.1-0.5-6.5,0.2-7.6
|
||||
c0.8-1.3,3.1-0.9,7.6-0.9s6.3,0.1,6.8,0.5c0.7,0.5,0.7,1.1,0.8,7.3c0,3.7,0.2,7.1,0.3,7.6c0.1,0.5,0.7,1.2,1.4,1.6
|
||||
c1.1,0.7,1.9,0.7,7.8,0.7c3.8,0,6.9,0.2,7.3,0.4c0.7,0.4,0.7,0.9,0.7,7.3s0,7-0.7,7.3c-0.4,0.2-3.5,0.4-7.3,0.4
|
||||
c-5.8,0-6.7,0.1-7.8,0.7c-0.7,0.4-1.3,1.1-1.4,1.6s-0.2,3.9-0.3,7.6c-0.1,6.2-0.2,6.8-0.8,7.3c-0.6,0.4-2.2,0.5-6.8,0.5
|
||||
c-4.7,0-7.2,0.7-7.9-0.9c-0.5-1.2,0.1-3.8,0.1-7.5l-0.1-7.1l-1.2-1.1l-1.2-1.1h-6.9c-6.2,0-7-0.1-7.5-0.7c-0.5-0.6-0.6-1.7-0.6-7.1
|
||||
C868.7,78.2,868.8,77.5,869.4,76.9L869.4,76.9L869.4,76.9z"/>
|
||||
<path id="path1514" class="st6" d="M274,123.2h5.3v10.5h-10.5v-10.5H274L274,123.2z"/>
|
||||
<path id="path1518" class="st6" d="M238.8,122.6c2.3-14.8,12.3-27.2,26.2-32.4c20-7.5,43,2.3,51.4,22c2.6,6.1,3.5,8,3.5,15.7
|
||||
c0,6.5-0.6,7.9-1.6,11.3c-4.4,14.4-14.9,24.6-29.4,28.6c-2.9,0.8-5.2,1.1-10.7,1.1c-5.5,0-6.2-0.3-9-1.1
|
||||
c-17.7-4.8-29.9-20-30.5-38.1C238.5,127.1,238.6,124,238.8,122.6L238.8,122.6L238.8,122.6z M250.8,134.7
|
||||
c2.6,11.9,13,21.3,25.1,22.5c21.5,2.2,37.7-18.1,30.7-38.5c-1.4-4.2-3.3-7-7.1-10.8c-2.8-2.8-4.1-3.8-7.2-5.3
|
||||
c-5.1-2.6-8.7-3.3-14.6-3c-6.8,0.3-11.7,2.2-16.9,6.3C252.4,112.5,248.4,124,250.8,134.7L250.8,134.7L250.8,134.7z"/>
|
||||
<path id="path1520" class="st7" d="M286.1,4.8c0.8-1.3,0.9-2.3,5.3-2.5c4.3-0.2,13.5,0.1,32.6,0.1c32.8,0,35.2-0.5,36.3,0.6
|
||||
c0.1,0.1,0.2,0.1,0.2,0.2c1.5,1.1,2.1,2.7,2.1,4.9v1.9h-77.3v-2C285.4,6.6,285.7,5.5,286.1,4.8L286.1,4.8L286.1,4.8z"/>
|
||||
<path id="path1522" class="st7" d="M688.3,6.2c0.1-0.5,0.4-1.3,0.8-1.8c0.5-0.8,0.8-1.5,2.7-1.8c3.2-0.5,11.4-0.2,35.1-0.2
|
||||
c19.3,0,28.3-0.5,32.5-0.4c2.7,0.1,3.2,0.8,3.6,1c1.6,0.9,2.3,2.4,2.3,4.8v2.1h-77.3l0-1.4C688.1,7.7,688.2,6.7,688.3,6.2
|
||||
L688.3,6.2L688.3,6.2z"/>
|
||||
<path id="path1524" class="st8" d="M874,334.6c20.6-10.1,37.2-21.9,53.9-38.2c35.7-34.8,57-78.7,63.1-129.7
|
||||
c0.6-5.1,0.8-13.1,1-40.9l0.2-34.6h1.4c1,0,3,0,3.7,1.4l1.1,2.1l-0.2,30.4c-0.1,16.9-0.2,33.5-0.5,37
|
||||
c-3.9,50.8-24.6,97.1-59.5,133.3c-16.9,17.6-35.7,31.5-57.9,42.8c-8.4,4.3-10.1,4.9-11.8,4.2c-1.1-0.4-4.2-2.7-4.1-3.2
|
||||
C864.4,339.2,869,337.1,874,334.6L874,334.6L874,334.6z"/>
|
||||
<path id="path1530" class="st4" d="M96.7,3.4c0.5-0.6,1.2-1.7,5-1.6c6.7,0.3,27.2-0.2,79.1-0.1L263.4,2l6.5,2.6l15,7.9l39.4,0.1
|
||||
l39.6-0.4l13.2-7.1l7.7-2.9l7.3-0.4l48,0.1l22.1-0.1l34.1,0.1l10.5,0.1h10.5l8.6-0.1l25.6,0h19.4l27.5-0.2L620,1.8l11,0l19.6,0.1
|
||||
l10.2,0l5.7,0.5l5.8,1.9l5.5,3l9.8,5.3h39.5l39.6-0.4l9.8-5.3l5.3-2.7l5.1-1.8l7.6-0.7l13.3,0.2l12.2-0.1h11.1l10.9,0l9.9,0h6.5
|
||||
l2.9,0l17.4,0.1l21.5,0h10.8l8.4-0.1l5.1,0l5.9-0.2l3.1,2.2l1.1,3.2l-0.1,3.2c0,1.4-0.1,2.7-0.2,3.9c-0.1,0.9-0.1,1.8-0.4,2.6
|
||||
c-0.4,1-1,1.7-1.3,2c-0.2,0.2-1.7,1.2-4.8,1.3c-2.1,0.1-4.7,0-8.3,0c-4.1,0-9.7,0.1-16.4,0c-10-0.1-23.1,0-40.4-0.1
|
||||
c-13.2,0-28.7,0.2-47,0.1c-62.8-0.2-158-0.2-301-0.2L98.7,20l-1.8-1.3C94.3,16.9,94,6.1,96.7,3.4L96.7,3.4L96.7,3.4z"/>
|
||||
<path id="path1532" class="st4" d="M535.4,22.4h392.4V31H143v-8.6H535.4L535.4,22.4z"/>
|
||||
<ellipse id="path3879" class="st9" cx="279.4" cy="128.2" rx="40.3" ry="40.3"/>
|
||||
<ellipse id="path3881" class="st10" cx="279.1" cy="128.2" rx="34.5" ry="34.1"/>
|
||||
<path id="path96" d="M306.1,128.3l-26.4-26.8v7.7h-22.5v38.5h22.5v7.2L306.1,128.3L306.1,128.3z M265.2,136.1v-15.2h14.5v15.2
|
||||
H265.2z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 17 KiB |
84
src/Ryujinx.Ava/Assets/Icons/Controller_ProCon.svg
Normal file
84
src/Ryujinx.Ava/Assets/Icons/Controller_ProCon.svg
Normal file
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 996.25 690.92">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
stroke: #fff;
|
||||
stroke-miterlimit: 10;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
fill: #444542;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #3b3b3b;
|
||||
}
|
||||
|
||||
.cls-3, .cls-4, .cls-2, .cls-5, .cls-6, .cls-7 {
|
||||
stroke-width: 0px;
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
fill: #3b3c3a;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #454644;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #20221f;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #121212;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Front">
|
||||
<path id="Right_Grip" data-name="Right Grip" class="cls-6" d="m739.17,492.09c34,28.2,27.6,35.9,68.5,108.5,36.7,74.7,64.4,104.4,125.1,84.1h0c95.3-57.9,59.3-145.3,43.6-275.2-10-60.6-35.6-190.3-35.6-190.3l-201.6,272.9Z"/>
|
||||
<path id="Left_Grip" data-name="Left Grip" class="cls-6" d="m55.47,219.19s-25.6,129.7-35.6,190.3c-15.7,129.9-51.7,217.2,43.6,275.1h0c60.8,20.3,88.4-9.4,125.1-84.1,40.9-72.7,34.5-80.3,68.5-108.5L55.47,219.19Z"/>
|
||||
<path id="Right_Bumper" data-name="Right Bumper" class="cls-3" d="m649.47,19.99c10.1-4.3,39.7-22.5,58.7-19.7,59.5.9,166.7,17.7,172.6,81.2"/>
|
||||
<path id="Left_Bumper" data-name="Left Bumper" class="cls-3" d="m115.57,81.49C121.47,18.09,228.57,1.29,288.17.29c19-2.8,48.6,15.4,58.7,19.7"/>
|
||||
<path id="Background" class="cls-7" d="m739.17,492.09c35.5-30.8,68.5-74.7,96-113.5,26.9-36.3,94.7-136.7,105.6-159.3,0-2.4-6.3-30.1-12.8-56.2C892.27,3.49,675.37,19.69,498.17,19.69S104.07,3.49,68.27,162.99c-6.5,26-12.8,53.8-12.8,56.2,10.9,22.6,78.8,123,105.6,159.3,27.5,38.8,60.5,82.8,96,113.5"/>
|
||||
<g id="Directional_Pad" data-name="Directional Pad">
|
||||
<path id="Background-2" data-name="Background" class="cls-2" d="m439.37,325.09h-40c-2.8,0-5-2.2-5-5v-40c0-2.8-2.2-5-5-5h-30c-2.8,0-5,2.2-5,5v40c0,2.8-2.2,5-5,5h-40c-2.8,0-5,2.2-5,5v30c0,2.8,2.2,5,5,5h40c2.8,0,5,2.2,5,5v40c0,2.8,2.2,5,5,5h30c2.8,0,5-2.2,5-5v-40c0-2.8,2.2-5,5-5h40c2.8,0,5-2.2,5-5v-30c0-2.7-2.2-5-5-5Z"/>
|
||||
</g>
|
||||
<g id="R_Thumbstick" data-name="R Thumbstick">
|
||||
<circle id="Background-3" data-name="Background" class="cls-6" cx="623.77" cy="345.09" r="55"/>
|
||||
<circle id="Stick" class="cls-1" cx="623.77" cy="345.09" r="45"/>
|
||||
</g>
|
||||
<g id="L_Thumbstick" data-name="L Thumbstick">
|
||||
<circle id="Background-4" data-name="Background" class="cls-6" cx="213.37" cy="206.39" r="55"/>
|
||||
<circle id="Stick-2" data-name="Stick" class="cls-1" cx="213.37" cy="206.39" r="45" transform="translate(-24.53 383.95) rotate(-80.78)"/>
|
||||
</g>
|
||||
<g id="Minus_Button" data-name="Minus Button">
|
||||
<circle id="_Background" data-name=" Background" class="cls-5" cx="374.17" cy="130.89" r="22.5"/>
|
||||
</g>
|
||||
<g id="Plus_Button" data-name="Plus Button">
|
||||
<circle id="_Background-2" data-name=" Background" class="cls-5" cx="623.57" cy="131.19" r="22.5"/>
|
||||
</g>
|
||||
<g id="Home_Button" data-name="Home Button">
|
||||
<circle id="_Background-3" data-name=" Background" class="cls-5" cx="578.57" cy="206.39" r="22.5"/>
|
||||
</g>
|
||||
<g id="Capture_Button" data-name="Capture Button">
|
||||
<path class="cls-5" d="m441.77,228.09h-30c-2.8,0-5-2.2-5-5v-29.5c0-2.8,2.2-5,5-5h30c2.8,0,5,2.2,5,5v29.5c0,2.7-2.2,5-5,5Z"/>
|
||||
</g>
|
||||
<g id="Buttons">
|
||||
<g id="A_Button" data-name="A Button">
|
||||
<circle id="Background-5" data-name="Background" class="cls-4" cx="837.07" cy="206.39" r="35"/>
|
||||
</g>
|
||||
<g id="X_Button" data-name="X Button">
|
||||
<circle id="Background-6" data-name="Background" class="cls-4" cx="767.07" cy="136.39" r="35"/>
|
||||
</g>
|
||||
<g id="Y_Button" data-name="Y Button">
|
||||
<circle id="Background-7" data-name="Background" class="cls-4" cx="697.07" cy="206.39" r="35"/>
|
||||
</g>
|
||||
<g id="B_Button" data-name="B Button">
|
||||
<circle id="Background-8" data-name="Background" class="cls-4" cx="767.07" cy="276.39" r="35"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
@@ -54,8 +54,6 @@
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Opens the Title Update management window",
|
||||
"GameListContextMenuManageDlc": "Manage DLC",
|
||||
"GameListContextMenuManageDlcToolTip": "Opens the DLC management window",
|
||||
"GameListContextMenuOpenModsDirectory": "Open Mods Directory",
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods",
|
||||
"GameListContextMenuCacheManagement": "Cache Management",
|
||||
"GameListContextMenuCacheManagementPurgePptc": "Queue PPTC Rebuild",
|
||||
"GameListContextMenuCacheManagementPurgePptcToolTip": "Trigger PPTC to rebuild at boot time on the next game launch",
|
||||
@@ -74,6 +72,11 @@
|
||||
"GameListContextMenuExtractDataLogoToolTip": "Extract the Logo section from Application's current config (including updates)",
|
||||
"GameListContextMenuCreateShortcut": "Create Application Shortcut",
|
||||
"GameListContextMenuCreateShortcutToolTip": "Create a Desktop Shortcut that launches the selected Application",
|
||||
"GameListContextMenuCreateShortcutToolTipMacOS": "Create a shortcut in macOS's Applications folder that launches the selected Application",
|
||||
"GameListContextMenuOpenModsDirectory": "Open Mods Directory",
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods",
|
||||
"GameListContextMenuOpenSdModsDirectory": "Open Atmosphere Mods Directory",
|
||||
"GameListContextMenuOpenSdModsDirectoryToolTip": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.",
|
||||
"StatusBarGamesLoaded": "{0}/{1} Games Loaded",
|
||||
"StatusBarSystemVersion": "System Version: {0}",
|
||||
"LinuxVmMaxMapCountDialogTitle": "Low limit for memory mappings detected",
|
||||
@@ -152,7 +155,7 @@
|
||||
"SettingsTabGraphicsResolutionScaleNative": "Native (720p/1080p)",
|
||||
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
|
||||
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
|
||||
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
|
||||
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p) (Not recommended)",
|
||||
"SettingsTabGraphicsAspectRatio": "Aspect Ratio:",
|
||||
"SettingsTabGraphicsAspectRatio4x3": "4:3",
|
||||
"SettingsTabGraphicsAspectRatio16x9": "16:9",
|
||||
@@ -294,13 +297,9 @@
|
||||
"GameListContextMenuRunApplication": "Run Application",
|
||||
"GameListContextMenuToggleFavorite": "Toggle Favorite",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "Toggle Favorite status of Game",
|
||||
"SettingsTabGeneralTheme": "Theme",
|
||||
"SettingsTabGeneralThemeCustomTheme": "Custom Theme Path",
|
||||
"SettingsTabGeneralThemeBaseStyle": "Base Style",
|
||||
"SettingsTabGeneralThemeBaseStyleDark": "Dark",
|
||||
"SettingsTabGeneralThemeBaseStyleLight": "Light",
|
||||
"SettingsTabGeneralThemeEnableCustomTheme": "Enable Custom Theme",
|
||||
"ButtonBrowse": "Browse",
|
||||
"SettingsTabGeneralTheme": "Theme:",
|
||||
"SettingsTabGeneralThemeDark": "Dark",
|
||||
"SettingsTabGeneralThemeLight": "Light",
|
||||
"ControllerSettingsConfigureGeneral": "Configure",
|
||||
"ControllerSettingsRumble": "Rumble",
|
||||
"ControllerSettingsRumbleStrongMultiplier": "Strong Rumble Multiplier",
|
||||
@@ -334,8 +333,6 @@
|
||||
"DialogUpdaterAddingFilesMessage": "Adding New Update...",
|
||||
"DialogUpdaterCompleteMessage": "Update Complete!",
|
||||
"DialogUpdaterRestartMessage": "Do you want to restart Ryujinx now?",
|
||||
"DialogUpdaterArchNotSupportedMessage": "You are not running a supported system architecture!",
|
||||
"DialogUpdaterArchNotSupportedSubMessage": "(Only x64 systems are supported!)",
|
||||
"DialogUpdaterNoInternetMessage": "You are not connected to the Internet!",
|
||||
"DialogUpdaterNoInternetSubMessage": "Please verify that you have a working Internet connection!",
|
||||
"DialogUpdaterDirtyBuildMessage": "You Cannot update a Dirty build of Ryujinx!",
|
||||
@@ -387,7 +384,10 @@
|
||||
"DialogUserProfileUnsavedChangesSubMessage": "Do you want to discard your changes?",
|
||||
"DialogControllerSettingsModifiedConfirmMessage": "The current controller settings has been updated.",
|
||||
"DialogControllerSettingsModifiedConfirmSubMessage": "Do you want to save?",
|
||||
"DialogLoadNcaErrorMessage": "{0}. Errored File: {1}",
|
||||
"DialogLoadFileErrorMessage": "{0}. Errored File: {1}",
|
||||
"DialogModAlreadyExistsMessage": "Mod already exists",
|
||||
"DialogModInvalidMessage": "The specified directory does not contain a mod!",
|
||||
"DialogModDeleteNoParentMessage": "Failed to Delete: Could not find the parent directory for mod \"{0}\"!",
|
||||
"DialogDlcNoDlcErrorMessage": "The specified file does not contain a DLC for the selected title!",
|
||||
"DialogPerformanceCheckLoggingEnabledMessage": "You have trace logging enabled, which is designed to be used by developers only.",
|
||||
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "For optimal performance, it's recommended to disable trace logging. Would you like to disable trace logging now?",
|
||||
@@ -398,6 +398,8 @@
|
||||
"DialogUpdateAddUpdateErrorMessage": "The specified file does not contain an update for the selected title!",
|
||||
"DialogSettingsBackendThreadingWarningTitle": "Warning - Backend Threading",
|
||||
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx must be restarted after changing this option for it to apply fully. Depending on your platform, you may need to manually disable your driver's own multithreading when using Ryujinx's.",
|
||||
"DialogModManagerDeletionWarningMessage": "You are about to delete the mod: {0}\n\nAre you sure you want to proceed?",
|
||||
"DialogModManagerDeletionAllWarningMessage": "You are about to delete all mods for this title.\n\nAre you sure you want to proceed?",
|
||||
"SettingsTabGraphicsFeaturesOptions": "Features",
|
||||
"SettingsTabGraphicsBackendMultithreading": "Graphics Backend Multithreading:",
|
||||
"CommonAuto": "Auto",
|
||||
@@ -432,6 +434,7 @@
|
||||
"DlcManagerRemoveAllButton": "Remove All",
|
||||
"DlcManagerEnableAllButton": "Enable All",
|
||||
"DlcManagerDisableAllButton": "Disable All",
|
||||
"ModManagerDeleteAllButton": "Delete All",
|
||||
"MenuBarOptionsChangeLanguage": "Change Language",
|
||||
"MenuBarShowFileTypes": "Show File Types",
|
||||
"CommonSort": "Sort",
|
||||
@@ -449,13 +452,13 @@
|
||||
"CustomThemePathTooltip": "Path to custom GUI theme",
|
||||
"CustomThemeBrowseTooltip": "Browse for a custom GUI theme",
|
||||
"DockModeToggleTooltip": "Docked mode makes the emulated system behave as a docked Nintendo Switch. This improves graphical fidelity in most games. Conversely, disabling this will make the emulated system behave as a handheld Nintendo Switch, reducing graphics quality.\n\nConfigure player 1 controls if planning to use docked mode; configure handheld controls if planning to use handheld mode.\n\nLeave ON if unsure.",
|
||||
"DirectKeyboardTooltip": "Direct keyboard access (HID) support. Provides games access to your keyboard as a text entry device.",
|
||||
"DirectMouseTooltip": "Direct mouse access (HID) support. Provides games access to your mouse as a pointing device.",
|
||||
"DirectKeyboardTooltip": "Direct keyboard access (HID) support. Provides games access to your keyboard as a text entry device.\n\nOnly works with games that natively support keyboard usage on Switch hardware.\n\nLeave OFF if unsure.",
|
||||
"DirectMouseTooltip": "Direct mouse access (HID) support. Provides games access to your mouse as a pointing device.\n\nOnly works with games that natively support mouse controls on Switch hardware, which are few and far between.\n\nWhen enabled, touch screen functionality may not work.\n\nLeave OFF if unsure.",
|
||||
"RegionTooltip": "Change System Region",
|
||||
"LanguageTooltip": "Change System Language",
|
||||
"TimezoneTooltip": "Change System TimeZone",
|
||||
"TimeTooltip": "Change System Time",
|
||||
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference. We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
|
||||
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference (F1 by default). We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
|
||||
"PptcToggleTooltip": "Saves translated JIT functions so that they do not need to be translated every time the game loads.\n\nReduces stuttering and significantly speeds up boot times after the first boot of a game.\n\nLeave ON if unsure.",
|
||||
"FsIntegrityToggleTooltip": "Checks for corrupt files when booting a game, and if corrupt files are detected, displays a hash error in the log.\n\nHas no impact on performance and is meant to help troubleshooting.\n\nLeave ON if unsure.",
|
||||
"AudioBackendTooltip": "Changes the backend used to render audio.\n\nSDL2 is the preferred one, while OpenAL and SoundIO are used as fallbacks. Dummy will have no sound.\n\nSet to SDL2 if unsure.",
|
||||
@@ -469,10 +472,10 @@
|
||||
"GraphicsBackendThreadingTooltip": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.",
|
||||
"GalThreadingTooltip": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.",
|
||||
"ShaderCacheToggleTooltip": "Saves a disk shader cache which reduces stuttering in subsequent runs.\n\nLeave ON if unsure.",
|
||||
"ResolutionScaleTooltip": "Resolution Scale applied to applicable render targets",
|
||||
"ResolutionScaleTooltip": "Multiplies the game's rendering resolution.\n\nA few games may not work with this and look pixelated even when the resolution is increased; for those games, you may need to find mods that remove anti-aliasing or that increase their internal rendering resolution. For using the latter, you'll likely want to select Native.\n\nThis option can be changed while a game is running by clicking \"Apply\" below; you can simply move the settings window aside and experiment until you find your preferred look for a game.\n\nKeep in mind 4x is overkill for virtually any setup.",
|
||||
"ResolutionScaleEntryTooltip": "Floating point resolution scale, such as 1.5. Non-integral scales are more likely to cause issues or crash.",
|
||||
"AnisotropyTooltip": "Level of Anisotropic Filtering (set to Auto to use the value requested by the game)",
|
||||
"AspectRatioTooltip": "Aspect Ratio applied to the renderer window.",
|
||||
"AnisotropyTooltip": "Level of Anisotropic Filtering. Set to Auto to use the value requested by the game.",
|
||||
"AspectRatioTooltip": "Aspect Ratio applied to the renderer window.\n\nOnly change this if you're using an aspect ratio mod for your game, otherwise the graphics will be stretched.\n\nLeave on 16:9 if unsure.",
|
||||
"ShaderDumpPathTooltip": "Graphics Shaders Dump Path",
|
||||
"FileLogTooltip": "Saves console logging to a log file on disk. Does not affect performance.",
|
||||
"StubLogTooltip": "Prints stub log messages in the console. Does not affect performance.",
|
||||
@@ -506,6 +509,8 @@
|
||||
"EnableInternetAccessTooltip": "Allows the emulated application to connect to the Internet.\n\nGames with a LAN mode can connect to each other when this is enabled and the systems are connected to the same access point. This includes real consoles as well.\n\nDoes NOT allow connecting to Nintendo servers. May cause crashing in certain games that try to connect to the Internet.\n\nLeave OFF if unsure.",
|
||||
"GameListContextMenuManageCheatToolTip": "Manage Cheats",
|
||||
"GameListContextMenuManageCheat": "Manage Cheats",
|
||||
"GameListContextMenuManageModToolTip": "Manage Mods",
|
||||
"GameListContextMenuManageMod": "Manage Mods",
|
||||
"ControllerSettingsStickRange": "Range:",
|
||||
"DialogStopEmulationTitle": "Ryujinx - Stop Emulation",
|
||||
"DialogStopEmulationMessage": "Are you sure you want to stop emulation?",
|
||||
@@ -517,8 +522,6 @@
|
||||
"SettingsTabCpuMemory": "CPU Mode",
|
||||
"DialogUpdaterFlatpakNotSupportedMessage": "Please update Ryujinx via FlatHub.",
|
||||
"UpdaterDisabledWarningTitle": "Updater Disabled!",
|
||||
"GameListContextMenuOpenSdModsDirectory": "Open Atmosphere Mods Directory",
|
||||
"GameListContextMenuOpenSdModsDirectoryToolTip": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.",
|
||||
"ControllerSettingsRotate90": "Rotate 90° Clockwise",
|
||||
"IconSize": "Icon Size",
|
||||
"IconSizeTooltip": "Change the size of game icons",
|
||||
@@ -549,9 +552,10 @@
|
||||
"SoftwareKeyboardModeNumeric": "Must be 0-9 or '.' only",
|
||||
"SoftwareKeyboardModeAlphabet": "Must be non CJK-characters only",
|
||||
"SoftwareKeyboardModeASCII": "Must be ASCII text only",
|
||||
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
||||
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
||||
"DialogControllerAppletDockModeSet": "Docked mode set. Handheld is also invalid.\n\n",
|
||||
"ControllerAppletControllers": "Supported Controllers:",
|
||||
"ControllerAppletPlayers": "Players:",
|
||||
"ControllerAppletDescription": "Your current configuration is invalid. Open settings and reconfigure your inputs.",
|
||||
"ControllerAppletDocked": "Docked mode set. Handheld control should be disabled.",
|
||||
"UpdaterRenaming": "Renaming Old Files...",
|
||||
"UpdaterRenameFailed": "Updater was unable to rename file: {0}",
|
||||
"UpdaterAddingFiles": "Adding New Files...",
|
||||
@@ -589,6 +593,7 @@
|
||||
"Writable": "Writable",
|
||||
"SelectDlcDialogTitle": "Select DLC files",
|
||||
"SelectUpdateDialogTitle": "Select update files",
|
||||
"SelectModDialogTitle": "Select mod directory",
|
||||
"UserProfileWindowTitle": "User Profiles Manager",
|
||||
"CheatWindowTitle": "Cheats Manager",
|
||||
"DlcWindowTitle": "Manage Downloadable Content for {0} ({1})",
|
||||
@@ -596,6 +601,7 @@
|
||||
"CheatWindowHeading": "Cheats Available for {0} [{1}]",
|
||||
"BuildId": "BuildId:",
|
||||
"DlcWindowHeading": "{0} Downloadable Content(s)",
|
||||
"ModWindowHeading": "{0} Mod(s)",
|
||||
"UserProfilesEditProfile": "Edit Selected",
|
||||
"Cancel": "Cancel",
|
||||
"Save": "Save",
|
||||
@@ -610,9 +616,9 @@
|
||||
"UserProfilesName": "Name:",
|
||||
"UserProfilesUserId": "User ID:",
|
||||
"SettingsTabGraphicsBackend": "Graphics Backend",
|
||||
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
|
||||
"SettingsTabGraphicsBackendTooltip": "Select the graphics backend that will be used in the emulator.\n\nVulkan is overall better for all modern graphics cards, as long as their drivers are up to date. Vulkan also features faster shader compilation (less stuttering) on all GPU vendors.\n\nOpenGL may achieve better results on old Nvidia GPUs, on old AMD GPUs on Linux, or on GPUs with lower VRAM, though shader compilation stutters will be greater.\n\nSet to Vulkan if unsure. Set to OpenGL if your GPU does not support Vulkan even with the latest graphics drivers.",
|
||||
"SettingsEnableTextureRecompression": "Enable Texture Recompression",
|
||||
"SettingsEnableTextureRecompressionTooltip": "Compresses certain textures in order to reduce VRAM usage.\n\nRecommended for use with GPUs that have less than 4GiB VRAM.\n\nLeave OFF if unsure.",
|
||||
"SettingsEnableTextureRecompressionTooltip": "Compresses ASTC textures in order to reduce VRAM usage.\n\nGames using this texture format include Astral Chain, Bayonetta 3, Fire Emblem Engage, Metroid Prime Remastered, Super Mario Bros. Wonder and The Legend of Zelda: Tears of the Kingdom.\n\nGraphics cards with 4GiB VRAM or less will likely crash at some point while running these games.\n\nEnable only if you're running out of VRAM on the aforementioned games. Leave OFF if unsure.",
|
||||
"SettingsTabGraphicsPreferredGpu": "Preferred GPU",
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
|
||||
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
|
||||
@@ -638,12 +644,12 @@
|
||||
"Recover": "Recover",
|
||||
"UserProfilesRecoverHeading": "Saves were found for the following accounts",
|
||||
"UserProfilesRecoverEmptyList": "No profiles to recover",
|
||||
"GraphicsAATooltip": "Applies anti-aliasing to the game render",
|
||||
"GraphicsAATooltip": "Applies anti-aliasing to the game render.\n\nFXAA will blur most of the image, while SMAA will attempt to find jagged edges and smooth them out.\n\nNot recommended to use in conjunction with the FSR scaling filter.\n\nThis option can be changed while a game is running by clicking \"Apply\" below; you can simply move the settings window aside and experiment until you find your preferred look for a game.\n\nLeave on NONE if unsure.",
|
||||
"GraphicsAALabel": "Anti-Aliasing:",
|
||||
"GraphicsScalingFilterLabel": "Scaling Filter:",
|
||||
"GraphicsScalingFilterTooltip": "Enables Framebuffer Scaling",
|
||||
"GraphicsScalingFilterTooltip": "Choose the scaling filter that will be applied when using resolution scale.\n\nBilinear works well for 3D games and is a safe default option.\n\nNearest is recommended for pixel art games.\n\nFSR 1.0 is merely a sharpening filter, not recommended for use with FXAA or SMAA.\n\nThis option can be changed while a game is running by clicking \"Apply\" below; you can simply move the settings window aside and experiment until you find your preferred look for a game.\n\nLeave on BILINEAR if unsure.",
|
||||
"GraphicsScalingFilterLevelLabel": "Level",
|
||||
"GraphicsScalingFilterLevelTooltip": "Set Scaling Filter Level",
|
||||
"GraphicsScalingFilterLevelTooltip": "Set FSR 1.0 sharpening level. Higher is sharper.",
|
||||
"SmaaLow": "SMAA Low",
|
||||
"SmaaMedium": "SMAA Medium",
|
||||
"SmaaHigh": "SMAA High",
|
||||
@@ -651,12 +657,12 @@
|
||||
"UserEditorTitle": "Edit User",
|
||||
"UserEditorTitleCreate": "Create User",
|
||||
"SettingsTabNetworkInterface": "Network Interface:",
|
||||
"NetworkInterfaceTooltip": "The network interface used for LAN/LDN features",
|
||||
"NetworkInterfaceTooltip": "The network interface used for LAN/LDN features.\n\nIn conjunction with a VPN or XLink Kai and a game with LAN support, can be used to spoof a same-network connection over the Internet.\n\nLeave on DEFAULT if unsure.",
|
||||
"NetworkInterfaceDefault": "Default",
|
||||
"PackagingShaders": "Packaging Shaders",
|
||||
"AboutChangelogButton": "View Changelog on GitHub",
|
||||
"AboutChangelogButtonTooltipMessage": "Click to open the changelog for this version in your default browser.",
|
||||
"SettingsTabNetworkMultiplayer": "Multiplayer",
|
||||
"MultiplayerMode": "Mode:",
|
||||
"MultiplayerModeTooltip": "Change multiplayer mode"
|
||||
"MultiplayerModeTooltip": "Change LDN multiplayer mode.\n\nLdnMitm will modify local wireless/local play functionality in games to function as if it were LAN, allowing for local, same-network connections with other Ryujinx instances and hacked Nintendo Switch consoles that have the ldn_mitm module installed.\n\nMultiplayer requires all players to be on the same game version (i.e. Super Smash Bros. Ultimate v13.0.1 can't connect to v13.0.0).\n\nLeave DISABLED if unsure."
|
||||
}
|
||||
|
@@ -18,8 +18,8 @@ using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using Ryujinx.Ui.App.Common;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
|
@@ -5,7 +5,7 @@ namespace Ryujinx.Ava.Common
|
||||
None,
|
||||
ToggleVSync,
|
||||
Screenshot,
|
||||
ShowUi,
|
||||
ShowUI,
|
||||
Pause,
|
||||
ToggleMute,
|
||||
ResScaleUp,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -16,8 +16,10 @@ namespace Ryujinx.Ava.Common.Locale
|
||||
private readonly Dictionary<LocaleKeys, string> _localeStrings;
|
||||
private Dictionary<LocaleKeys, string> _localeDefaultStrings;
|
||||
private readonly ConcurrentDictionary<LocaleKeys, object[]> _dynamicValues;
|
||||
private string _localeLanguageCode;
|
||||
|
||||
public static LocaleManager Instance { get; } = new();
|
||||
public event Action LocaleChanged;
|
||||
|
||||
public LocaleManager()
|
||||
{
|
||||
@@ -36,9 +38,9 @@ namespace Ryujinx.Ava.Common.Locale
|
||||
// If the view is loaded with the UI Previewer detached, then override it with the saved one or default.
|
||||
if (Program.PreviewerDetached)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ConfigurationState.Instance.Ui.LanguageCode.Value))
|
||||
if (!string.IsNullOrEmpty(ConfigurationState.Instance.UI.LanguageCode.Value))
|
||||
{
|
||||
localeLanguageCode = ConfigurationState.Instance.Ui.LanguageCode.Value;
|
||||
localeLanguageCode = ConfigurationState.Instance.UI.LanguageCode.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -104,6 +106,15 @@ namespace Ryujinx.Ava.Common.Locale
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRTL()
|
||||
{
|
||||
return _localeLanguageCode switch
|
||||
{
|
||||
"he_IL" => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
public string UpdateAndGetDynamicValue(LocaleKeys key, params object[] values)
|
||||
{
|
||||
_dynamicValues[key] = values;
|
||||
@@ -124,6 +135,9 @@ namespace Ryujinx.Ava.Common.Locale
|
||||
{
|
||||
this[item.Key] = item.Value;
|
||||
}
|
||||
|
||||
_localeLanguageCode = languageCode;
|
||||
LocaleChanged?.Invoke();
|
||||
}
|
||||
|
||||
private static Dictionary<LocaleKeys, string> LoadJsonLanguage(string languageCode = DefaultLanguageCode)
|
||||
|
@@ -10,8 +10,8 @@ using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.Ui.Common.Models.Github;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using Ryujinx.UI.Common.Models.Github;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -68,7 +68,8 @@ namespace Ryujinx.Modules
|
||||
}
|
||||
else if (OperatingSystem.IsLinux())
|
||||
{
|
||||
_platformExt = "linux_x64.tar.gz";
|
||||
var arch = RuntimeInformation.OSArchitecture == Architecture.Arm64 ? "arm64" : "x64";
|
||||
_platformExt = $"linux_{arch}.tar.gz";
|
||||
}
|
||||
|
||||
Version newVersion;
|
||||
@@ -637,20 +638,6 @@ namespace Ryujinx.Modules
|
||||
public static bool CanUpdate(bool showWarnings)
|
||||
{
|
||||
#if !DISABLE_UPDATER
|
||||
if (RuntimeInformation.OSArchitecture != Architecture.X64 && !OperatingSystem.IsMacOS())
|
||||
{
|
||||
if (showWarnings)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(() =>
|
||||
ContentDialogHelper.CreateWarningDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedMessage],
|
||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedSubMessage])
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NetworkInterface.GetIsNetworkAvailable())
|
||||
{
|
||||
if (showWarnings)
|
||||
@@ -665,7 +652,7 @@ namespace Ryujinx.Modules
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Program.Version.Contains("dirty") || !ReleaseInformation.IsValid())
|
||||
if (Program.Version.Contains("dirty") || !ReleaseInformation.IsValid)
|
||||
{
|
||||
if (showWarnings)
|
||||
{
|
||||
@@ -683,7 +670,7 @@ namespace Ryujinx.Modules
|
||||
#else
|
||||
if (showWarnings)
|
||||
{
|
||||
if (ReleaseInformation.IsFlatHubBuild())
|
||||
if (ReleaseInformation.IsFlatHubBuild)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(() =>
|
||||
ContentDialogHelper.CreateWarningDialog(
|
||||
|
@@ -9,10 +9,10 @@ using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.SystemInterop;
|
||||
using Ryujinx.Modules;
|
||||
using Ryujinx.SDL2.Common;
|
||||
using Ryujinx.Ui.Common;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.Ui.Common.SystemInfo;
|
||||
using Ryujinx.UI.Common;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using Ryujinx.UI.Common.SystemInfo;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -35,7 +35,7 @@ namespace Ryujinx.Ava
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Version = ReleaseInformation.GetVersion();
|
||||
Version = ReleaseInformation.Version;
|
||||
|
||||
if (OperatingSystem.IsWindows() && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134))
|
||||
{
|
||||
@@ -59,6 +59,7 @@ namespace Ryujinx.Ava
|
||||
{
|
||||
EnableMultiTouch = true,
|
||||
EnableIme = true,
|
||||
EnableInputFocusProxy = true,
|
||||
RenderingMode = new[] { X11RenderingMode.Glx, X11RenderingMode.Software },
|
||||
})
|
||||
.With(new Win32PlatformOptions
|
||||
@@ -125,8 +126,8 @@ namespace Ryujinx.Ava
|
||||
|
||||
public static void ReloadConfig()
|
||||
{
|
||||
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json");
|
||||
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, "Config.json");
|
||||
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
||||
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
||||
|
||||
// Now load the configuration as the other subsystems are now registered
|
||||
if (File.Exists(localConfigurationPath))
|
||||
|
@@ -43,14 +43,13 @@
|
||||
<PackageReference Include="Avalonia.Markup.Xaml.Loader" />
|
||||
<PackageReference Include="Avalonia.Svg" />
|
||||
<PackageReference Include="Avalonia.Svg.Skia" />
|
||||
<PackageReference Include="jp2masa.Avalonia.Flexbox" />
|
||||
<PackageReference Include="DynamicData" />
|
||||
<PackageReference Include="FluentAvaloniaUI" />
|
||||
|
||||
<PackageReference Include="OpenTK.Core" />
|
||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
|
||||
<PackageReference Include="Silk.NET.Vulkan" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" />
|
||||
@@ -74,12 +73,12 @@
|
||||
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Ui.Common\Ryujinx.Ui.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Ui.LocaleGenerator\Ryujinx.Ui.LocaleGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||
<ProjectReference Include="..\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||
<Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64'">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>alsoft.ini</TargetPath>
|
||||
</Content>
|
||||
@@ -93,7 +92,7 @@
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64'">
|
||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64'">
|
||||
<Content Include="..\..\distribution\linux\Ryujinx.sh">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
@@ -104,7 +103,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AvaloniaResource Include="Ui\**\*.xaml">
|
||||
<AvaloniaResource Include="UI\**\*.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</AvaloniaResource>
|
||||
<AvaloniaResource Include="Assets\Fonts\SegoeFluentIcons.ttf" />
|
||||
@@ -119,6 +118,7 @@
|
||||
<None Remove="Assets\Locales\en_US.json" />
|
||||
<None Remove="Assets\Locales\es_ES.json" />
|
||||
<None Remove="Assets\Locales\fr_FR.json" />
|
||||
<None Remove="Assets\Locales\he_IL.json" />
|
||||
<None Remove="Assets\Locales\de_DE.json" />
|
||||
<None Remove="Assets\Locales\it_IT.json" />
|
||||
<None Remove="Assets\Locales\ja_JP.json" />
|
||||
@@ -132,6 +132,10 @@
|
||||
<None Remove="Assets\Locales\zh_TW.json" />
|
||||
<None Remove="Assets\Styles\Styles.xaml" />
|
||||
<None Remove="Assets\Styles\Themes.xaml" />
|
||||
<None Remove="Assets\Icons\Controller_JoyConLeft.svg" />
|
||||
<None Remove="Assets\Icons\Controller_JoyConPair.svg" />
|
||||
<None Remove="Assets\Icons\Controller_JoyConRight.svg" />
|
||||
<None Remove="Assets\Icons\Controller_ProCon.svg" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -139,6 +143,7 @@
|
||||
<EmbeddedResource Include="Assets\Locales\en_US.json" />
|
||||
<EmbeddedResource Include="Assets\Locales\es_ES.json" />
|
||||
<EmbeddedResource Include="Assets\Locales\fr_FR.json" />
|
||||
<EmbeddedResource Include="Assets\Locales\he_IL.json" />
|
||||
<EmbeddedResource Include="Assets\Locales\de_DE.json" />
|
||||
<EmbeddedResource Include="Assets\Locales\it_IT.json" />
|
||||
<EmbeddedResource Include="Assets\Locales\ja_JP.json" />
|
||||
@@ -151,6 +156,10 @@
|
||||
<EmbeddedResource Include="Assets\Locales\zh_CN.json" />
|
||||
<EmbeddedResource Include="Assets\Locales\zh_TW.json" />
|
||||
<EmbeddedResource Include="Assets\Styles\Styles.xaml" />
|
||||
<EmbeddedResource Include="Assets\Icons\Controller_JoyConLeft.svg" />
|
||||
<EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" />
|
||||
<EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" />
|
||||
<EmbeddedResource Include="Assets\Icons\Controller_ProCon.svg" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="Assets\Locales\en_US.json" />
|
||||
|
@@ -8,35 +8,45 @@ using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.HLE;
|
||||
using Ryujinx.HLE.HOS.Applets;
|
||||
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
||||
using Ryujinx.HLE.Ui;
|
||||
using Ryujinx.HLE.UI;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Applet
|
||||
{
|
||||
internal class AvaHostUiHandler : IHostUiHandler
|
||||
internal class AvaHostUIHandler : IHostUIHandler
|
||||
{
|
||||
private readonly MainWindow _parent;
|
||||
|
||||
public IHostUiTheme HostUiTheme { get; }
|
||||
public IHostUITheme HostUITheme { get; }
|
||||
|
||||
public AvaHostUiHandler(MainWindow parent)
|
||||
public AvaHostUIHandler(MainWindow parent)
|
||||
{
|
||||
_parent = parent;
|
||||
|
||||
HostUiTheme = new AvaloniaHostUiTheme(parent);
|
||||
HostUITheme = new AvaloniaHostUITheme(parent);
|
||||
}
|
||||
|
||||
public bool DisplayMessageDialog(ControllerAppletUiArgs args)
|
||||
public bool DisplayMessageDialog(ControllerAppletUIArgs args)
|
||||
{
|
||||
string message = LocaleManager.Instance.UpdateAndGetDynamicValue(
|
||||
args.PlayerCountMin == args.PlayerCountMax ? LocaleKeys.DialogControllerAppletMessage : LocaleKeys.DialogControllerAppletMessagePlayerRange,
|
||||
args.PlayerCountMin == args.PlayerCountMax ? args.PlayerCountMin.ToString() : $"{args.PlayerCountMin}-{args.PlayerCountMax}",
|
||||
args.SupportedStyles,
|
||||
string.Join(", ", args.SupportedPlayers),
|
||||
args.IsDocked ? LocaleManager.Instance[LocaleKeys.DialogControllerAppletDockModeSet] : "");
|
||||
ManualResetEvent dialogCloseEvent = new(false);
|
||||
|
||||
return DisplayMessageDialog(LocaleManager.Instance[LocaleKeys.DialogControllerAppletTitle], message);
|
||||
bool okPressed = false;
|
||||
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
var response = await ControllerAppletDialog.ShowControllerAppletDialog(_parent, args);
|
||||
if (response == UserResult.Ok)
|
||||
{
|
||||
okPressed = true;
|
||||
}
|
||||
|
||||
dialogCloseEvent.Set();
|
||||
});
|
||||
|
||||
dialogCloseEvent.WaitOne();
|
||||
|
||||
return okPressed;
|
||||
}
|
||||
|
||||
public bool DisplayMessageDialog(string title, string message)
|
||||
@@ -75,6 +85,8 @@ namespace Ryujinx.Ava.UI.Applet
|
||||
|
||||
await _parent.SettingsWindow.ShowDialog(window);
|
||||
|
||||
_parent.SettingsWindow = null;
|
||||
|
||||
opened = false;
|
||||
});
|
||||
|
||||
@@ -98,7 +110,7 @@ namespace Ryujinx.Ava.UI.Applet
|
||||
return okPressed;
|
||||
}
|
||||
|
||||
public bool DisplayInputDialog(SoftwareKeyboardUiArgs args, out string userText)
|
||||
public bool DisplayInputDialog(SoftwareKeyboardUIArgs args, out string userText)
|
||||
{
|
||||
ManualResetEvent dialogCloseEvent = new(false);
|
||||
|
@@ -5,7 +5,7 @@ using Avalonia.Threading;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.HLE.Ui;
|
||||
using Ryujinx.HLE.UI;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using HidKey = Ryujinx.Common.Configuration.Hid.Key;
|
||||
|
@@ -1,13 +1,13 @@
|
||||
using Avalonia.Media;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.HLE.Ui;
|
||||
using Ryujinx.HLE.UI;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Applet
|
||||
{
|
||||
class AvaloniaHostUiTheme : IHostUiTheme
|
||||
class AvaloniaHostUITheme : IHostUITheme
|
||||
{
|
||||
public AvaloniaHostUiTheme(MainWindow parent)
|
||||
public AvaloniaHostUITheme(MainWindow parent)
|
||||
{
|
||||
FontFamily = OperatingSystem.IsWindows() && OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000) ? "Segoe UI Variable" : parent.FontFamily.Name;
|
||||
DefaultBackgroundColor = BrushToThemeColor(parent.Background);
|
145
src/Ryujinx.Ava/UI/Applet/ControllerAppletDialog.axaml
Normal file
145
src/Ryujinx.Ava/UI/Applet/ControllerAppletDialog.axaml
Normal file
@@ -0,0 +1,145 @@
|
||||
<UserControl
|
||||
x:Class="Ryujinx.Ava.UI.Applet.ControllerAppletDialog"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:applet="using:Ryujinx.Ava.UI.Applet"
|
||||
mc:Ignorable="d"
|
||||
Width="400"
|
||||
Focusable="True"
|
||||
x:DataType="applet:ControllerAppletDialog">
|
||||
<Grid
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="0 0 0 10"
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5">
|
||||
<StackPanel
|
||||
Spacing="10"
|
||||
Margin="10">
|
||||
<TextBlock
|
||||
Text="{locale:Locale ControllerAppletDescription}" />
|
||||
<TextBlock
|
||||
IsVisible="{Binding IsDocked}"
|
||||
FontWeight="Bold"
|
||||
Text="{locale:Locale ControllerAppletDocked}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Grid.Row="1"
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5"
|
||||
Margin="0 0 10 0">
|
||||
<StackPanel
|
||||
Margin="10"
|
||||
Spacing="10"
|
||||
Orientation="Vertical">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
TextAlignment="Center"
|
||||
FontWeight="Bold"
|
||||
Text="{locale:Locale ControllerAppletControllers}" />
|
||||
<StackPanel
|
||||
Spacing="10"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<Image
|
||||
Height="50"
|
||||
Width="50"
|
||||
Stretch="Uniform"
|
||||
Source="{Binding ProControllerImage}"
|
||||
IsVisible="{Binding SupportsProController}" />
|
||||
<Image
|
||||
Height="50"
|
||||
Width="50"
|
||||
Stretch="Uniform"
|
||||
Source="{Binding JoyconPairImage}"
|
||||
IsVisible="{Binding SupportsJoyconPair}" />
|
||||
<Image
|
||||
Height="50"
|
||||
Width="50"
|
||||
Stretch="Uniform"
|
||||
Source="{Binding JoyconLeftImage}"
|
||||
IsVisible="{Binding SupportsLeftJoycon}" />
|
||||
<Image
|
||||
Height="50"
|
||||
Width="50"
|
||||
Stretch="Uniform"
|
||||
Source="{Binding JoyconRightImage}"
|
||||
IsVisible="{Binding SupportsRightJoycon}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border
|
||||
Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
BorderBrush="{DynamicResource ThemeControlBorderColor}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5">
|
||||
<StackPanel
|
||||
Margin="10"
|
||||
Spacing="10"
|
||||
Orientation="Vertical">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
TextAlignment="Center"
|
||||
FontWeight="Bold"
|
||||
Text="{locale:Locale ControllerAppletPlayers}" />
|
||||
<Border Height="50">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
TextAlignment="Center"
|
||||
FontSize="40"
|
||||
FontWeight="Thin"
|
||||
Text="{Binding PlayerCount}" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Panel
|
||||
Margin="0 24 0 0"
|
||||
Grid.Column="0"
|
||||
Grid.Row="2"
|
||||
Grid.ColumnSpan="2">
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Spacing="10"
|
||||
HorizontalAlignment="Right">
|
||||
<Button
|
||||
Name="SaveButton"
|
||||
MinWidth="90"
|
||||
Command="{Binding OpenSettingsWindow}">
|
||||
<TextBlock Text="{locale:Locale DialogOpenSettingsWindowLabel}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="CancelButton"
|
||||
MinWidth="90"
|
||||
Command="{Binding Close}">
|
||||
<TextBlock Text="{locale:Locale SettingsButtonClose}" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Panel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
140
src/Ryujinx.Ava/UI/Applet/ControllerAppletDialog.axaml.cs
Normal file
140
src/Ryujinx.Ava/UI/Applet/ControllerAppletDialog.axaml.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.Svg.Skia;
|
||||
using Avalonia.Threading;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.HLE.HOS.Applets;
|
||||
using Ryujinx.HLE.HOS.Services.Hid;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Applet
|
||||
{
|
||||
internal partial class ControllerAppletDialog : UserControl
|
||||
{
|
||||
private const string ProControllerResource = "Ryujinx.Ava/Assets/Icons/Controller_ProCon.svg";
|
||||
private const string JoyConPairResource = "Ryujinx.Ava/Assets/Icons/Controller_JoyConPair.svg";
|
||||
private const string JoyConLeftResource = "Ryujinx.Ava/Assets/Icons/Controller_JoyConLeft.svg";
|
||||
private const string JoyConRightResource = "Ryujinx.Ava/Assets/Icons/Controller_JoyConRight.svg";
|
||||
|
||||
public static SvgImage ProControllerImage => GetResource(ProControllerResource);
|
||||
public static SvgImage JoyconPairImage => GetResource(JoyConPairResource);
|
||||
public static SvgImage JoyconLeftImage => GetResource(JoyConLeftResource);
|
||||
public static SvgImage JoyconRightImage => GetResource(JoyConRightResource);
|
||||
|
||||
public string PlayerCount { get; set; } = "";
|
||||
public bool SupportsProController { get; set; }
|
||||
public bool SupportsLeftJoycon { get; set; }
|
||||
public bool SupportsRightJoycon { get; set; }
|
||||
public bool SupportsJoyconPair { get; set; }
|
||||
public bool IsDocked { get; set; }
|
||||
|
||||
private readonly MainWindow _mainWindow;
|
||||
|
||||
public ControllerAppletDialog(MainWindow mainWindow, ControllerAppletUIArgs args)
|
||||
{
|
||||
if (args.PlayerCountMin == args.PlayerCountMax)
|
||||
{
|
||||
PlayerCount = args.PlayerCountMin.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerCount = $"{args.PlayerCountMin} - {args.PlayerCountMax}";
|
||||
}
|
||||
|
||||
SupportsProController = (args.SupportedStyles & ControllerType.ProController) != 0;
|
||||
SupportsLeftJoycon = (args.SupportedStyles & ControllerType.JoyconLeft) != 0;
|
||||
SupportsRightJoycon = (args.SupportedStyles & ControllerType.JoyconRight) != 0;
|
||||
SupportsJoyconPair = (args.SupportedStyles & ControllerType.JoyconPair) != 0;
|
||||
|
||||
IsDocked = args.IsDocked;
|
||||
|
||||
_mainWindow = mainWindow;
|
||||
|
||||
DataContext = this;
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public ControllerAppletDialog(MainWindow mainWindow)
|
||||
{
|
||||
_mainWindow = mainWindow;
|
||||
DataContext = this;
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public static async Task<UserResult> ShowControllerAppletDialog(MainWindow window, ControllerAppletUIArgs args)
|
||||
{
|
||||
ContentDialog contentDialog = new();
|
||||
UserResult result = UserResult.Cancel;
|
||||
ControllerAppletDialog content = new(window, args);
|
||||
|
||||
contentDialog.Title = LocaleManager.Instance[LocaleKeys.DialogControllerAppletTitle];
|
||||
contentDialog.Content = content;
|
||||
|
||||
void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Result == ContentDialogResult.Primary)
|
||||
{
|
||||
result = UserResult.Ok;
|
||||
}
|
||||
}
|
||||
|
||||
contentDialog.Closed += Handler;
|
||||
|
||||
Style bottomBorder = new(x => x.OfType<Grid>().Name("DialogSpace").Child().OfType<Border>());
|
||||
bottomBorder.Setters.Add(new Setter(IsVisibleProperty, false));
|
||||
|
||||
contentDialog.Styles.Add(bottomBorder);
|
||||
|
||||
await ContentDialogHelper.ShowAsync(contentDialog);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SvgImage GetResource(string path)
|
||||
{
|
||||
SvgImage image = new();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
SvgSource source = new(default(Uri));
|
||||
|
||||
source.Load(EmbeddedResources.GetStream(path));
|
||||
|
||||
image.Source = source;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
public void OpenSettingsWindow()
|
||||
{
|
||||
if (_mainWindow.SettingsWindow == null)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
_mainWindow.SettingsWindow = new SettingsWindow(_mainWindow.VirtualFileSystem, _mainWindow.ContentManager);
|
||||
_mainWindow.SettingsWindow.NavPanel.Content = _mainWindow.SettingsWindow.InputPage;
|
||||
_mainWindow.SettingsWindow.NavPanel.SelectedItem = _mainWindow.SettingsWindow.NavPanel.MenuItems.ElementAt(1);
|
||||
|
||||
await ContentDialogHelper.ShowWindowAsync(_mainWindow.SettingsWindow, _mainWindow);
|
||||
_mainWindow.SettingsWindow = null;
|
||||
this.Close();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
((ContentDialog)Parent)?.Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@
|
||||
Height="80"
|
||||
MinWidth="50"
|
||||
Margin="5,10,20,10"
|
||||
Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common" />
|
||||
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
|
@@ -31,7 +31,7 @@
|
||||
MinWidth="50"
|
||||
Margin="5,10,20,10"
|
||||
VerticalAlignment="Center"
|
||||
Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common" />
|
||||
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
|
@@ -54,7 +54,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
public string MainText { get; set; } = "";
|
||||
public string SecondaryText { get; set; } = "";
|
||||
|
||||
public static async Task<(UserResult Result, string Input)> ShowInputDialog(string title, SoftwareKeyboardUiArgs args)
|
||||
public static async Task<(UserResult Result, string Input)> ShowInputDialog(string title, SoftwareKeyboardUIArgs args)
|
||||
{
|
||||
ContentDialog contentDialog = new();
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
Click="CreateApplicationShortcut_Click"
|
||||
Header="{locale:Locale GameListContextMenuCreateShortcut}"
|
||||
IsEnabled="{Binding CreateShortcutEnabled}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuCreateShortcutToolTip}" />
|
||||
ToolTip.Tip="{OnPlatform Default={locale:Locale GameListContextMenuCreateShortcutToolTip}, macOS={locale:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
|
||||
<Separator />
|
||||
<MenuItem
|
||||
Click="OpenUserSaveDirectory_Click"
|
||||
@@ -46,6 +46,11 @@
|
||||
Click="OpenCheatManager_Click"
|
||||
Header="{locale:Locale GameListContextMenuManageCheat}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuManageCheatToolTip}" />
|
||||
<MenuItem
|
||||
Click="OpenModManager_Click"
|
||||
Header="{locale:Locale GameListContextMenuManageMod}"
|
||||
ToolTip.Tip="{locale:Locale GameListContextMenuManageModToolTip}" />
|
||||
<Separator />
|
||||
<MenuItem
|
||||
Click="OpenModsDirectory_Click"
|
||||
Header="{locale:Locale GameListContextMenuOpenModsDirectory}"
|
||||
|
@@ -11,8 +11,8 @@ using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.HLE.HOS;
|
||||
using Ryujinx.Ui.App.Common;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
@@ -133,7 +133,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
if (viewModel?.SelectedApplication != null)
|
||||
{
|
||||
string modsBasePath = ModLoader.GetModsBasePath();
|
||||
string titleModsPath = ModLoader.GetTitleDir(modsBasePath, viewModel.SelectedApplication.TitleId);
|
||||
string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, viewModel.SelectedApplication.TitleId);
|
||||
|
||||
OpenHelper.OpenFolder(titleModsPath);
|
||||
}
|
||||
@@ -146,12 +146,22 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
if (viewModel?.SelectedApplication != null)
|
||||
{
|
||||
string sdModsBasePath = ModLoader.GetSdModsBasePath();
|
||||
string titleModsPath = ModLoader.GetTitleDir(sdModsBasePath, viewModel.SelectedApplication.TitleId);
|
||||
string titleModsPath = ModLoader.GetApplicationDir(sdModsBasePath, viewModel.SelectedApplication.TitleId);
|
||||
|
||||
OpenHelper.OpenFolder(titleModsPath);
|
||||
}
|
||||
}
|
||||
|
||||
public async void OpenModManager_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
|
||||
|
||||
if (viewModel?.SelectedApplication != null)
|
||||
{
|
||||
await ModManagerWindow.Show(ulong.Parse(viewModel.SelectedApplication.TitleId, NumberStyles.HexNumber), viewModel.SelectedApplication.TitleName);
|
||||
}
|
||||
}
|
||||
|
||||
public async void PurgePtcCache_Click(object sender, RoutedEventArgs args)
|
||||
{
|
||||
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
|
||||
|
@@ -4,7 +4,6 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox"
|
||||
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
@@ -33,11 +32,10 @@
|
||||
SelectionChanged="GameList_SelectionChanged">
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<flex:FlexPanel
|
||||
<WrapPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
AlignContent="FlexStart"
|
||||
JustifyContent="FlexStart" />
|
||||
VerticalAlignment="Top"
|
||||
Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBox.Styles>
|
||||
|
@@ -3,7 +3,7 @@ using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ui.App.Common;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Controls
|
||||
|
@@ -86,17 +86,17 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding TitleName}"
|
||||
TextAlignment="Left"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding Developer}"
|
||||
TextAlignment="Left"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding Version}"
|
||||
TextAlignment="Left"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
@@ -110,12 +110,12 @@
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding TitleId}"
|
||||
TextAlignment="Left"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding FileExtension}"
|
||||
TextAlignment="Left"
|
||||
TextAlignment="Start"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
@@ -127,17 +127,17 @@
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding TimePlayedString}"
|
||||
TextAlignment="Right"
|
||||
TextAlignment="End"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding LastPlayedString, Converter={helpers:LocalizedNeverConverter}}"
|
||||
TextAlignment="Right"
|
||||
TextAlignment="End"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
Text="{Binding FileSizeString}"
|
||||
TextAlignment="Right"
|
||||
TextAlignment="End"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
<ui:SymbolIcon
|
||||
|
@@ -3,7 +3,7 @@ using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ui.App.Common;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Controls
|
||||
|
@@ -26,7 +26,7 @@
|
||||
Height="70"
|
||||
MinWidth="50"
|
||||
Margin="5,10,20,10"
|
||||
Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common" />
|
||||
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" />
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
@@ -39,4 +39,4 @@
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
</Window>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ui.App.Common;
|
||||
using Ryujinx.UI.App.Common;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Helpers
|
||||
{
|
||||
|
@@ -18,6 +18,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
public static class ContentDialogHelper
|
||||
{
|
||||
private static bool _isChoiceDialogOpen;
|
||||
private static ContentDialogOverlayWindow _contentDialogOverlayWindow;
|
||||
|
||||
private async static Task<UserResult> ShowContentDialog(
|
||||
string title,
|
||||
@@ -310,16 +311,20 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
public static async Task<ContentDialogResult> ShowAsync(ContentDialog contentDialog)
|
||||
{
|
||||
ContentDialogResult result;
|
||||
|
||||
ContentDialogOverlayWindow contentDialogOverlayWindow = null;
|
||||
bool isTopDialog = true;
|
||||
|
||||
Window parent = GetMainWindow();
|
||||
|
||||
if (_contentDialogOverlayWindow != null)
|
||||
{
|
||||
isTopDialog = false;
|
||||
}
|
||||
|
||||
if (parent is MainWindow window)
|
||||
{
|
||||
parent.Activate();
|
||||
|
||||
contentDialogOverlayWindow = new()
|
||||
_contentDialogOverlayWindow = new ContentDialogOverlayWindow
|
||||
{
|
||||
Height = parent.Bounds.Height,
|
||||
Width = parent.Bounds.Width,
|
||||
@@ -331,14 +336,19 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
|
||||
void OverlayOnPositionChanged(object sender, PixelPointEventArgs e)
|
||||
{
|
||||
contentDialogOverlayWindow.Position = parent.PointToScreen(new Point());
|
||||
if (_contentDialogOverlayWindow is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_contentDialogOverlayWindow.Position = parent.PointToScreen(new Point());
|
||||
}
|
||||
|
||||
contentDialogOverlayWindow.ContentDialog = contentDialog;
|
||||
_contentDialogOverlayWindow.ContentDialog = contentDialog;
|
||||
|
||||
bool opened = false;
|
||||
|
||||
contentDialogOverlayWindow.Opened += OverlayOnActivated;
|
||||
_contentDialogOverlayWindow.Opened += OverlayOnActivated;
|
||||
|
||||
async void OverlayOnActivated(object sender, EventArgs e)
|
||||
{
|
||||
@@ -349,12 +359,12 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
|
||||
opened = true;
|
||||
|
||||
contentDialogOverlayWindow.Position = parent.PointToScreen(new Point());
|
||||
_contentDialogOverlayWindow.Position = parent.PointToScreen(new Point());
|
||||
|
||||
result = await ShowDialog();
|
||||
}
|
||||
|
||||
result = await contentDialogOverlayWindow.ShowDialog<ContentDialogResult>(parent);
|
||||
result = await _contentDialogOverlayWindow.ShowDialog<ContentDialogResult>(parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -363,31 +373,39 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
|
||||
async Task<ContentDialogResult> ShowDialog()
|
||||
{
|
||||
if (contentDialogOverlayWindow is not null)
|
||||
if (_contentDialogOverlayWindow is not null)
|
||||
{
|
||||
result = await contentDialog.ShowAsync(contentDialogOverlayWindow);
|
||||
result = await contentDialog.ShowAsync(_contentDialogOverlayWindow);
|
||||
|
||||
contentDialogOverlayWindow!.Close();
|
||||
_contentDialogOverlayWindow!.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ContentDialogResult.None;
|
||||
|
||||
Logger.Warning?.Print(LogClass.Ui, "Content dialog overlay failed to populate. Default value has been returned.");
|
||||
Logger.Warning?.Print(LogClass.UI, "Content dialog overlay failed to populate. Default value has been returned.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (contentDialogOverlayWindow is not null)
|
||||
if (isTopDialog && _contentDialogOverlayWindow is not null)
|
||||
{
|
||||
contentDialogOverlayWindow.Content = null;
|
||||
contentDialogOverlayWindow.Close();
|
||||
_contentDialogOverlayWindow.Content = null;
|
||||
_contentDialogOverlayWindow.Close();
|
||||
_contentDialogOverlayWindow = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Task ShowWindowAsync(Window dialogWindow, Window mainWindow = null)
|
||||
{
|
||||
mainWindow ??= GetMainWindow();
|
||||
|
||||
return dialogWindow.ShowDialog(_contentDialogOverlayWindow ?? mainWindow);
|
||||
}
|
||||
|
||||
private static Window GetMainWindow()
|
||||
{
|
||||
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
|
@@ -39,12 +39,12 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
|
||||
public void Log(AvaLogLevel level, string area, object source, string messageTemplate)
|
||||
{
|
||||
GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, null));
|
||||
GetLog(level)?.PrintMsg(RyuLogClass.UI, Format(level, area, messageTemplate, source, null));
|
||||
}
|
||||
|
||||
public void Log(AvaLogLevel level, string area, object source, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, propertyValues));
|
||||
GetLog(level)?.PrintMsg(RyuLogClass.UI, Format(level, area, messageTemplate, source, propertyValues));
|
||||
}
|
||||
|
||||
private static string Format(AvaLogLevel level, string area, string template, object source, object[] v)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ui.Common;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.UI.Common;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Helpers
|
||||
|
@@ -1,40 +0,0 @@
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
public class CheatModel : BaseModel
|
||||
{
|
||||
private bool _isEnabled;
|
||||
|
||||
public event EventHandler<bool> EnableToggled;
|
||||
|
||||
public CheatModel(string name, string buildId, bool isEnabled)
|
||||
{
|
||||
Name = name;
|
||||
BuildId = buildId;
|
||||
IsEnabled = isEnabled;
|
||||
}
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
set
|
||||
{
|
||||
_isEnabled = value;
|
||||
|
||||
EnableToggled?.Invoke(this, _isEnabled);
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public string BuildId { get; }
|
||||
|
||||
public string BuildIdKey => $"{BuildId}-{Name}";
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public string CleanName => Name[1..^7];
|
||||
}
|
||||
}
|
57
src/Ryujinx.Ava/UI/Models/CheatNode.cs
Normal file
57
src/Ryujinx.Ava/UI/Models/CheatNode.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
public class CheatNode : BaseModel
|
||||
{
|
||||
private bool _isEnabled = false;
|
||||
public ObservableCollection<CheatNode> SubNodes { get; } = new();
|
||||
public string CleanName => Name[1..^7];
|
||||
public string BuildIdKey => $"{BuildId}-{Name}";
|
||||
public bool IsRootNode { get; }
|
||||
public string Name { get; }
|
||||
public string BuildId { get; }
|
||||
public string Path { get; }
|
||||
public bool IsEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SubNodes.Count > 0)
|
||||
{
|
||||
return SubNodes.ToList().TrueForAll(x => x.IsEnabled);
|
||||
}
|
||||
|
||||
return _isEnabled;
|
||||
}
|
||||
set
|
||||
{
|
||||
foreach (var cheat in SubNodes)
|
||||
{
|
||||
cheat.IsEnabled = value;
|
||||
cheat.OnPropertyChanged();
|
||||
}
|
||||
|
||||
_isEnabled = value;
|
||||
}
|
||||
}
|
||||
|
||||
public CheatNode(string name, string buildId, string path, bool isRootNode, bool isEnabled = false)
|
||||
{
|
||||
Name = name;
|
||||
BuildId = buildId;
|
||||
Path = path;
|
||||
IsEnabled = isEnabled;
|
||||
IsRootNode = isRootNode;
|
||||
|
||||
SubNodes.CollectionChanged += CheatsList_CollectionChanged;
|
||||
}
|
||||
|
||||
private void CheatsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
public class CheatsList : ObservableCollection<CheatModel>
|
||||
{
|
||||
public CheatsList(string buildId, string path)
|
||||
{
|
||||
BuildId = buildId;
|
||||
Path = path;
|
||||
|
||||
CollectionChanged += CheatsList_CollectionChanged;
|
||||
}
|
||||
|
||||
public string BuildId { get; }
|
||||
public string Path { get; }
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ToList().TrueForAll(x => x.IsEnabled);
|
||||
}
|
||||
set
|
||||
{
|
||||
foreach (var cheat in this)
|
||||
{
|
||||
cheat.IsEnabled = value;
|
||||
}
|
||||
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsEnabled)));
|
||||
}
|
||||
}
|
||||
|
||||
private void CheatsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
(e.NewItems[0] as CheatModel).EnableToggled += Item_EnableToggled;
|
||||
}
|
||||
}
|
||||
|
||||
private void Item_EnableToggled(object sender, bool e)
|
||||
{
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsEnabled)));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
using Ryujinx.Ui.App.Common;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
using Ryujinx.Ui.App.Common;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
32
src/Ryujinx.Ava/UI/Models/ModModel.cs
Normal file
32
src/Ryujinx.Ava/UI/Models/ModModel.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Models
|
||||
{
|
||||
public class ModModel : BaseModel
|
||||
{
|
||||
private bool _enabled;
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get => _enabled;
|
||||
set
|
||||
{
|
||||
_enabled = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool InSd { get; }
|
||||
public string Path { get; }
|
||||
public string Name { get; }
|
||||
|
||||
public ModModel(string path, string name, bool enabled, bool inSd)
|
||||
{
|
||||
Path = path;
|
||||
Name = name;
|
||||
Enabled = enabled;
|
||||
InSd = inSd;
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,8 +3,8 @@ using LibHac.Ncm;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using Ryujinx.Ui.App.Common;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.UI.App.Common;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
@@ -3,8 +3,8 @@ using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Platform;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using Ryujinx.UI.Common.Helper;
|
||||
using SPB.Graphics;
|
||||
using SPB.Platform;
|
||||
using SPB.Platform.GLX;
|
||||
|
@@ -3,7 +3,7 @@ using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.OpenGL;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using SPB.Graphics;
|
||||
using SPB.Graphics.Exceptions;
|
||||
using SPB.Graphics.OpenGL;
|
||||
@@ -75,7 +75,7 @@ namespace Ryujinx.Ava.UI.Renderer
|
||||
throw;
|
||||
}
|
||||
|
||||
Logger.Warning?.Print(LogClass.Ui, $"Failed to {(!unbind ? "bind" : "unbind")} OpenGL context: {e}");
|
||||
Logger.Warning?.Print(LogClass.UI, $"Failed to {(!unbind ? "bind" : "unbind")} OpenGL context: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,11 +1,12 @@
|
||||
<UserControl
|
||||
<UserControl
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
x:Class="Ryujinx.Ava.UI.Renderer.RendererHost"
|
||||
FlowDirection="LeftToRight"
|
||||
Focusable="True">
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Renderer
|
||||
|
@@ -29,6 +29,8 @@ namespace Ryujinx.Ava.UI.Renderer
|
||||
_context.MakeCurrent(_window);
|
||||
}
|
||||
|
||||
public bool HasContext() => _context.IsCurrent;
|
||||
|
||||
public static SPBOpenGLContext CreateBackgroundContext(OpenGLContextBase sharedContext)
|
||||
{
|
||||
OpenGLContextBase context = PlatformHelper.CreateOpenGLContext(FramebufferFormat.Default, 3, 3, OpenGLContextFlags.Compat, true, sharedContext);
|
||||
|
@@ -3,7 +3,7 @@ using Avalonia.Platform;
|
||||
using Avalonia.Threading;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.NetworkInformation;
|
||||
@@ -87,19 +87,19 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
Version = Program.Version;
|
||||
|
||||
if (ConfigurationState.Instance.Ui.BaseStyle.Value == "Light")
|
||||
if (ConfigurationState.Instance.UI.BaseStyle.Value == "Light")
|
||||
{
|
||||
GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_GitHub_Light.png?assembly=Ryujinx.Ui.Common")));
|
||||
DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Discord_Light.png?assembly=Ryujinx.Ui.Common")));
|
||||
PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Patreon_Light.png?assembly=Ryujinx.Ui.Common")));
|
||||
TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Twitter_Light.png?assembly=Ryujinx.Ui.Common")));
|
||||
GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_GitHub_Light.png?assembly=Ryujinx.UI.Common")));
|
||||
DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Discord_Light.png?assembly=Ryujinx.UI.Common")));
|
||||
PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Patreon_Light.png?assembly=Ryujinx.UI.Common")));
|
||||
TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Twitter_Light.png?assembly=Ryujinx.UI.Common")));
|
||||
}
|
||||
else
|
||||
{
|
||||
GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_GitHub_Dark.png?assembly=Ryujinx.Ui.Common")));
|
||||
DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Discord_Dark.png?assembly=Ryujinx.Ui.Common")));
|
||||
PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Patreon_Dark.png?assembly=Ryujinx.Ui.Common")));
|
||||
TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Twitter_Dark.png?assembly=Ryujinx.Ui.Common")));
|
||||
GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_GitHub_Dark.png?assembly=Ryujinx.UI.Common")));
|
||||
DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Discord_Dark.png?assembly=Ryujinx.UI.Common")));
|
||||
PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Patreon_Dark.png?assembly=Ryujinx.UI.Common")));
|
||||
TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Twitter_Dark.png?assembly=Ryujinx.UI.Common")));
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.InvokeAsync(DownloadPatronsJson);
|
||||
|
@@ -9,7 +9,7 @@ using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Ui.Common.Models.Amiibo;
|
||||
using Ryujinx.UI.Common.Models.Amiibo;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -17,6 +17,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
@@ -64,7 +65,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
_amiiboSeries = new ObservableCollection<string>();
|
||||
_amiibos = new AvaloniaList<AmiiboApi>();
|
||||
|
||||
_amiiboLogoBytes = EmbeddedResources.Read("Ryujinx.Ui.Common/Resources/Logo_Amiibo.png");
|
||||
_amiiboLogoBytes = EmbeddedResources.Read("Ryujinx.UI.Common/Resources/Logo_Amiibo.png");
|
||||
|
||||
_ = LoadContentAsync();
|
||||
}
|
||||
@@ -188,35 +189,83 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
_httpClient.Dispose();
|
||||
}
|
||||
|
||||
private async Task LoadContentAsync()
|
||||
private static bool TryGetAmiiboJson(string json, out AmiiboJson amiiboJson)
|
||||
{
|
||||
string amiiboJsonString = DefaultJson;
|
||||
|
||||
if (File.Exists(_amiiboJsonPath))
|
||||
if (string.IsNullOrEmpty(json))
|
||||
{
|
||||
amiiboJsonString = await File.ReadAllTextAsync(_amiiboJsonPath);
|
||||
amiiboJson = JsonHelper.Deserialize(DefaultJson, _serializerContext.AmiiboJson);
|
||||
|
||||
if (await NeedsUpdate(JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).LastUpdated))
|
||||
{
|
||||
amiiboJsonString = await DownloadAmiiboJson();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
try
|
||||
{
|
||||
amiiboJson = JsonHelper.Deserialize(json, _serializerContext.AmiiboJson);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (JsonException exception)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Unable to deserialize amiibo data: {exception}");
|
||||
amiiboJson = JsonHelper.Deserialize(DefaultJson, _serializerContext.AmiiboJson);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<AmiiboJson> GetMostRecentAmiiboListOrDefaultJson()
|
||||
{
|
||||
bool localIsValid = false;
|
||||
bool remoteIsValid = false;
|
||||
AmiiboJson amiiboJson = new();
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
amiiboJsonString = await DownloadAmiiboJson();
|
||||
if (File.Exists(_amiiboJsonPath))
|
||||
{
|
||||
localIsValid = TryGetAmiiboJson(await File.ReadAllTextAsync(_amiiboJsonPath), out amiiboJson);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception exception)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data: {ex}");
|
||||
Logger.Warning?.Print(LogClass.Application, $"Unable to read data from '{_amiiboJsonPath}': {exception}");
|
||||
}
|
||||
|
||||
if (!localIsValid || await NeedsUpdate(amiiboJson.LastUpdated))
|
||||
{
|
||||
remoteIsValid = TryGetAmiiboJson(await DownloadAmiiboJson(), out amiiboJson);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
if (!(localIsValid || remoteIsValid))
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Couldn't get valid amiibo data: {exception}");
|
||||
|
||||
// Neither local or remote files are valid JSON, close window.
|
||||
ShowInfoDialog();
|
||||
Close();
|
||||
}
|
||||
else if (!remoteIsValid)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Couldn't update amiibo data: {exception}");
|
||||
|
||||
// Only the local file is valid, the local one should be used
|
||||
// but the user should be warned.
|
||||
ShowInfoDialog();
|
||||
}
|
||||
}
|
||||
|
||||
_amiiboList = JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).Amiibo;
|
||||
_amiiboList = _amiiboList.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
|
||||
return amiiboJson;
|
||||
}
|
||||
|
||||
private async Task LoadContentAsync()
|
||||
{
|
||||
AmiiboJson amiiboJson = await GetMostRecentAmiiboListOrDefaultJson();
|
||||
|
||||
_amiiboList = amiiboJson.Amiibo.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
|
||||
|
||||
ParseAmiiboData();
|
||||
}
|
||||
@@ -364,43 +413,50 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpResponseMessage response =
|
||||
await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
|
||||
HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return response.Content.Headers.LastModified != new DateTimeOffset(oldLastModified.Ticks - (oldLastModified.Ticks % TimeSpan.TicksPerSecond), TimeSpan.Zero);
|
||||
return response.Content.Headers.LastModified != oldLastModified;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (HttpRequestException exception)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to check for amiibo updates: {ex}");
|
||||
|
||||
ShowInfoDialog();
|
||||
|
||||
return false;
|
||||
Logger.Error?.Print(LogClass.Application, $"Unable to check for amiibo data updates: {exception}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<string> DownloadAmiiboJson()
|
||||
{
|
||||
HttpResponseMessage response = await _httpClient.GetAsync("https://amiibo.ryujinx.org/");
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
try
|
||||
{
|
||||
string amiiboJsonString = await response.Content.ReadAsStringAsync();
|
||||
HttpResponseMessage response = await _httpClient.GetAsync("https://amiibo.ryujinx.org/");
|
||||
|
||||
using (FileStream amiiboJsonStream = File.Create(_amiiboJsonPath, 4096, FileOptions.WriteThrough))
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
amiiboJsonStream.Write(Encoding.UTF8.GetBytes(amiiboJsonString));
|
||||
string amiiboJsonString = await response.Content.ReadAsStringAsync();
|
||||
|
||||
try
|
||||
{
|
||||
using FileStream dlcJsonStream = File.Create(_amiiboJsonPath, 4096, FileOptions.WriteThrough);
|
||||
dlcJsonStream.Write(Encoding.UTF8.GetBytes(amiiboJsonString));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Couldn't write amiibo data to file '{_amiiboJsonPath}: {exception}'");
|
||||
}
|
||||
|
||||
return amiiboJsonString;
|
||||
}
|
||||
|
||||
return amiiboJsonString;
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data. Response status code: {response.StatusCode}");
|
||||
}
|
||||
catch (HttpRequestException exception)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to request amiibo data: {exception}");
|
||||
}
|
||||
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data. Response status code: {response.StatusCode}");
|
||||
|
||||
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle],
|
||||
LocaleManager.Instance[LocaleKeys.DialogAmiiboApiFailFetchMessage],
|
||||
@@ -408,9 +464,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
"",
|
||||
LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
|
||||
|
||||
Close();
|
||||
|
||||
return DefaultJson;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void Close()
|
||||
|
@@ -19,7 +19,7 @@ using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -35,10 +35,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public class ControllerInputViewModel : BaseModel, IDisposable
|
||||
{
|
||||
private const string Disabled = "disabled";
|
||||
private const string ProControllerResource = "Ryujinx.Ui.Common/Resources/Controller_ProCon.svg";
|
||||
private const string JoyConPairResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConPair.svg";
|
||||
private const string JoyConLeftResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConLeft.svg";
|
||||
private const string JoyConRightResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConRight.svg";
|
||||
private const string ProControllerResource = "Ryujinx.UI.Common/Resources/Controller_ProCon.svg";
|
||||
private const string JoyConPairResource = "Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg";
|
||||
private const string JoyConLeftResource = "Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg";
|
||||
private const string JoyConRightResource = "Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg";
|
||||
private const string KeyboardString = "keyboard";
|
||||
private const string ControllerString = "controller";
|
||||
private readonly MainWindow _mainWindow;
|
||||
@@ -180,7 +180,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_controllerImage))
|
||||
{
|
||||
SvgSource source = new();
|
||||
SvgSource source = new(default(Uri));
|
||||
|
||||
source.Load(EmbeddedResources.GetStream(_controllerImage));
|
||||
|
||||
|
@@ -39,6 +39,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private string _search;
|
||||
private readonly ulong _titleId;
|
||||
private readonly IStorageProvider _storageProvider;
|
||||
|
||||
private static readonly DownloadableContentJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
@@ -90,8 +91,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count);
|
||||
}
|
||||
|
||||
public IStorageProvider StorageProvider;
|
||||
|
||||
public DownloadableContentManagerViewModel(VirtualFileSystem virtualFileSystem, ulong titleId)
|
||||
{
|
||||
_virtualFileSystem = virtualFileSystem;
|
||||
@@ -100,7 +99,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
StorageProvider = desktop.MainWindow.StorageProvider;
|
||||
_storageProvider = desktop.MainWindow.StorageProvider;
|
||||
}
|
||||
|
||||
_downloadableContentJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "dlc.json");
|
||||
@@ -194,7 +193,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogLoadNcaErrorMessage], ex.Message, containerPath));
|
||||
await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogLoadFileErrorMessage], ex.Message, containerPath));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -203,7 +202,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public async void Add()
|
||||
{
|
||||
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
var result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
{
|
||||
Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle],
|
||||
AllowMultiple = true,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user