mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2026-04-20 22:22:03 +00:00
Compare commits
84 commits
Canary-1.3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9905ee17c2 | ||
|
|
7f0e82fe48 | ||
|
|
69c22a744e | ||
|
|
35b1531102 | ||
|
|
ea1185e96a | ||
|
|
31e0430b06 | ||
|
|
efb8658194 | ||
|
|
e909ea3210 | ||
|
|
2a688abeec | ||
|
|
9f88d68268 | ||
|
|
fe685c3f8f | ||
|
|
2edc165e26 | ||
|
|
fa7cb22240 | ||
|
|
c5b4add186 | ||
|
|
0079e0bfa5 | ||
|
|
25b70e05d7 | ||
|
|
78eb95733a | ||
|
|
17a768a5df | ||
|
|
339cddd0e2 | ||
|
|
66d9bc5a35 | ||
|
|
3e393449aa | ||
|
|
744c41937b | ||
|
|
ecd1c1240c | ||
|
|
3ad4d4a692 | ||
|
|
6fe7fb8dcb | ||
|
|
fc357d3ba4 | ||
|
|
32ee806070 | ||
|
|
4e81a4c2f4 | ||
|
|
9cae62096a | ||
|
|
648b609ebb | ||
|
|
5ae86fc493 | ||
|
|
6f90e47a73 | ||
|
|
ac5f9857e2 | ||
|
|
4b42087bd4 | ||
|
|
80cbf5d1fc | ||
|
|
cc6d2dc162 | ||
|
|
4ebc318da5 | ||
|
|
00dad0a5e2 | ||
|
|
b70e2e44cb | ||
|
|
012d1d6886 | ||
|
|
d1205dc95d | ||
|
|
6f95172bb6 | ||
|
|
8208d43d9e | ||
|
|
1260f93aaf | ||
|
|
1b3bf1473d | ||
|
|
081cdcab0c | ||
|
|
922775664c | ||
|
|
478b66fd49 | ||
|
|
a16a072155 | ||
|
|
a4a0fcd4da | ||
|
|
cc5b60bbca | ||
|
|
5ed94c365b | ||
|
|
fef93a453a | ||
|
|
82074eb191 | ||
|
|
bd388cf4f9 | ||
|
|
d271abe19a | ||
|
|
c154f66f26 | ||
|
|
f556e8b8fb | ||
|
|
99feaafbe6 | ||
|
|
fa55608587 | ||
|
|
4c64300576 | ||
|
|
0a3db19b28 | ||
|
|
453b246faa | ||
|
|
45193dcc8d | ||
|
|
9ebf444644 | ||
|
|
f585b36263 | ||
|
|
a96f20dca5 | ||
|
|
1e1bcb4a5b | ||
|
|
ca76bacd22 | ||
|
|
66f339d265 | ||
|
|
6cdbdfd329 | ||
|
|
9f817d60d5 | ||
|
|
5cffc95be6 | ||
|
|
2c0977f6b3 | ||
|
|
3a593b6084 | ||
|
|
c3155fcadb | ||
|
|
fd7554425a | ||
|
|
52700f71dc | ||
|
|
b018a44ff0 | ||
|
|
d522bfef62 | ||
|
|
39f55b2af3 | ||
|
|
6126e3dc1e | ||
|
|
e1c829f91d | ||
|
|
6c7dc7646b |
217 changed files with 5576 additions and 2382 deletions
|
|
@ -10,6 +10,10 @@ gpu:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: ['src/Ryujinx.Graphics.*/**', 'src/Spv.Generator/**', 'src/Ryujinx.ShaderTools/**']
|
- any-glob-to-any-file: ['src/Ryujinx.Graphics.*/**', 'src/Spv.Generator/**', 'src/Ryujinx.ShaderTools/**']
|
||||||
|
|
||||||
|
input:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file: ['src/Ryujinx.Input*/**', 'src/Ryujinx/UI/Views/Input/**']
|
||||||
|
|
||||||
'graphics-backend:opengl':
|
'graphics-backend:opengl':
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: 'src/Ryujinx.Graphics.OpenGL/**'
|
- any-glob-to-any-file: 'src/Ryujinx.Graphics.OpenGL/**'
|
||||||
|
|
@ -18,17 +22,17 @@ gpu:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Vulkan/**', 'src/Spv.Generator/**']
|
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Vulkan/**', 'src/Spv.Generator/**']
|
||||||
|
|
||||||
'graphics-backend:metal':
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Metal/**', 'src/Ryujinx.Graphics.Metal.SharpMetalExtensions/**']
|
|
||||||
|
|
||||||
gui:
|
gui:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.UI.Common/**', 'src/Ryujinx.UI.LocaleGenerator/**']
|
- any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.UI.LocaleGenerator/**']
|
||||||
|
|
||||||
horizon:
|
'horizon/hle':
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: ['src/Ryujinx.HLE/**', 'src/Ryujinx.Horizon/**']
|
- any-glob-to-any-file: ['src/Ryujinx.HLE/**', 'src/Ryujinx.HLE.Generators/**', 'src/Ryujinx.Horizon/**']
|
||||||
|
|
||||||
|
i18n:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file: ['assets/**/*.json', 'src/Ryujinx.UI.LocaleGenerator/**']
|
||||||
|
|
||||||
kernel:
|
kernel:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
|
|
@ -36,7 +40,7 @@ kernel:
|
||||||
|
|
||||||
infra:
|
infra:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: ['.github/**', 'distribution/**', 'Directory.Packages.props', 'src/Ryujinx.BuildValidationTasks/**']
|
- any-glob-to-any-file: ['.forgejo/**', 'distribution/**', 'Directory.Packages.props', 'src/Ryujinx.BuildValidationTasks/**']
|
||||||
|
|
||||||
documentation:
|
documentation:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
|
|
@ -44,4 +48,4 @@ documentation:
|
||||||
|
|
||||||
ldn:
|
ldn:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: 'src/Ryujinx.HLE/HOS/Services/Ldn/**'
|
- any-glob-to-any-file: ['src/Ryujinx.HLE/HOS/Services/Ldn/**', 'src/Ryujinx/UI/Windows/LdnGamesListWindow.*', 'src/Ryujinx/UI/ViewModels/LdnGamesListViewModel.cs']
|
||||||
197
.forgejo/workflows/build.yml
Normal file
197
.forgejo/workflows/build.yml
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
name: Build PR
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
paths:
|
||||||
|
- '**'
|
||||||
|
- '!.forgejo/**'
|
||||||
|
- '!*.yml'
|
||||||
|
- '!*.config'
|
||||||
|
- '!*.md'
|
||||||
|
- '.forgejo/workflows/*.yml'
|
||||||
|
|
||||||
|
env:
|
||||||
|
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
|
RELEASE: 0
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: ${{ matrix.platform.name }} (${{ matrix.configuration }})
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: ghcr.io/catthehacker/ubuntu:act-latest
|
||||||
|
timeout-minutes: 45
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
configuration: [Release]
|
||||||
|
platform:
|
||||||
|
- { name: win-x64, zip_os_name: win_x64 }
|
||||||
|
#- { name: win-arm64, zip_os_name: win_arm64 }
|
||||||
|
- { name: linux-x64, zip_os_name: linux_x64 }
|
||||||
|
- { name: linux-arm64, zip_os_name: linux_arm64 }
|
||||||
|
#- { name: osx-x64, zip_os_name: osx_x64 }
|
||||||
|
|
||||||
|
fail-fast: false
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v4
|
||||||
|
with:
|
||||||
|
global-json-file: global.json
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
|
- name: Overwrite csc problem matcher
|
||||||
|
run: echo "::add-matcher::.forgejo/csc.json"
|
||||||
|
|
||||||
|
- name: Get version info
|
||||||
|
id: version_info
|
||||||
|
run: |
|
||||||
|
echo "result=$(gli get-next-version -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
echo "git_short_hash=$(git rev-parse --short "${{ forgejo.sha }}")" >> $FORGEJO_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: forgejo.event_name == 'pull_request'
|
||||||
|
|
||||||
|
- name: 'Cache: ~/.nuget/packages'
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.nuget/packages
|
||||||
|
key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }}
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: dotnet build -c "${{ matrix.configuration }}" -p:Version="${{ steps.version_info.outputs.result }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:ExtraDefineConstants=DISABLE_UPDATER
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
uses: actions/unstable-commands@v1
|
||||||
|
with:
|
||||||
|
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.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.result }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained
|
||||||
|
if: forgejo.event_name == 'pull_request'
|
||||||
|
|
||||||
|
- name: Set executable bit
|
||||||
|
run: |
|
||||||
|
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
||||||
|
if: forgejo.event_name == 'pull_request' && contains(matrix.platform.name, 'linux')
|
||||||
|
|
||||||
|
- name: Build AppImage
|
||||||
|
if: forgejo.event_name == 'pull_request' && contains(matrix.platform.name, 'linux')
|
||||||
|
run: |
|
||||||
|
PLATFORM_NAME="${{ matrix.platform.name }}"
|
||||||
|
|
||||||
|
sudo apt update && sudo apt install -y zsync desktop-file-utils appstream libfuse2t64
|
||||||
|
|
||||||
|
mkdir -p tools
|
||||||
|
export PATH="$PATH:$(readlink -f tools)"
|
||||||
|
|
||||||
|
# Setup appimagetool
|
||||||
|
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||||
|
chmod +x tools/appimagetool
|
||||||
|
chmod +x distribution/linux/appimage/build-appimage.sh
|
||||||
|
|
||||||
|
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
||||||
|
if [ "$PLATFORM_NAME" = "linux-x64" ]; then
|
||||||
|
ARCH_NAME=x64
|
||||||
|
export ARCH=x86_64
|
||||||
|
elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
|
||||||
|
ARCH_NAME=arm64
|
||||||
|
export ARCH=aarch64
|
||||||
|
else
|
||||||
|
echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Upload Ryujinx artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ryujinx-${{ matrix.configuration }}-${{ steps.version_info.outputs.result }}+${{ steps.version_info.outputs.git_short_hash }}-${{ matrix.platform.zip_os_name }}
|
||||||
|
path: publish
|
||||||
|
if: forgejo.event_name == 'pull_request'
|
||||||
|
|
||||||
|
- name: Upload Ryujinx (AppImage) artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: forgejo.event_name == 'pull_request' && contains(matrix.platform.name, 'linux')
|
||||||
|
with:
|
||||||
|
name: ryujinx-${{ matrix.configuration }}-${{ steps.version_info.outputs.result }}+${{ steps.version_info.outputs.git_short_hash }}-${{ matrix.platform.zip_os_name }}-AppImage
|
||||||
|
path: publish_appimage
|
||||||
|
|
||||||
|
build_macos:
|
||||||
|
name: macOS Universal (${{ matrix.configuration }})
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 45
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
configuration: [ Release ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v4
|
||||||
|
with:
|
||||||
|
global-json-file: global.json
|
||||||
|
|
||||||
|
- name: Setup LLVM 17
|
||||||
|
run: |
|
||||||
|
wget https://apt.llvm.org/llvm.sh
|
||||||
|
chmod +x llvm.sh
|
||||||
|
sudo ./llvm.sh 17
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install rcodesign
|
||||||
|
run: |
|
||||||
|
gli ghr -R indygreg/apple-platform-rs -p apple-codesign-*-x86_64-unknown-linux-musl.tar.gz -O apple-codesign.tar.gz
|
||||||
|
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
|
||||||
|
rm apple-codesign.tar.gz
|
||||||
|
sudo mv rcodesign /usr/bin/rcodesign
|
||||||
|
|
||||||
|
- name: Get version info
|
||||||
|
id: version_info
|
||||||
|
run: |
|
||||||
|
echo "result=$(gli get-next-version -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
echo "git_short_hash=$(git rev-parse --short "${{ forgejo.sha }}")" >> $FORGEJO_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: forgejo.event_name == 'pull_request'
|
||||||
|
|
||||||
|
- name: 'Cache: ~/.nuget/packages'
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.nuget/packages
|
||||||
|
key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }}
|
||||||
|
|
||||||
|
- name: Publish macOS Ryujinx
|
||||||
|
run: |
|
||||||
|
bash distribution/macos/create_macos_pr_build_ava.sh . publish_tmp publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.result }}" "${{ steps.version_info.outputs.git_short_hash }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Upload Ryujinx artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ryujinx-${{ matrix.configuration }}-${{ steps.version_info.outputs.result }}+${{ steps.version_info.outputs.git_short_hash }}-macos_universal
|
||||||
|
path: "publish/*.tar.gz"
|
||||||
|
if: forgejo.event_name == 'pull_request'
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
name: Canary release job
|
name: Canary CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
@ -6,7 +6,7 @@ on:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '.github/**'
|
- '.forgejo/**'
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
- 'assets/**'
|
- 'assets/**'
|
||||||
- '*.yml'
|
- '*.yml'
|
||||||
|
|
@ -19,37 +19,47 @@ concurrency: release
|
||||||
env:
|
env:
|
||||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
RYUJINX_BASE_VERSION: "1.3"
|
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary"
|
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary"
|
||||||
RELEASE: 1
|
RELEASE: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Release for ${{ matrix.platform.name }}
|
name: Release for ${{ matrix.platform.name }}
|
||||||
runs-on: ${{ matrix.platform.os }}
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: ${{ matrix.platform.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
platform:
|
platform:
|
||||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
- { name: win-x64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: win_x64 }
|
||||||
#- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
#- { name: win-arm64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: win_arm64 }
|
||||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
- { name: linux-x64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: linux_x64 }
|
||||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
- { name: linux-arm64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: linux_arm64 }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
- uses: actions/setup-dotnet@v5
|
||||||
with:
|
with:
|
||||||
global-json-file: global.json
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Overwrite csc problem matcher
|
- name: Overwrite csc problem matcher
|
||||||
run: echo "::add-matcher::.github/csc.json"
|
run: echo "::add-matcher::.forgejo/csc.json"
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install 7zip
|
||||||
|
run: |
|
||||||
|
sudo apt update && sudo apt install -y 7zip
|
||||||
|
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
run: |
|
run: |
|
||||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
echo "build_version=$(gli get-next-version -c Canary -R)" >> $FORGEJO_OUTPUT
|
||||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
echo "prev_build_version=$(gli get-current-version -c Canary -R)" >> $FORGEJO_OUTPUT
|
||||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
echo "git_short_hash=$(git rev-parse --short "${{ forgejo.sha }}")" >> $FORGEJO_OUTPUT
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Configure for release
|
- name: Configure for release
|
||||||
|
|
@ -69,50 +79,31 @@ jobs:
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./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
|
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./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
|
||||||
|
|
||||||
- name: Packing Windows builds
|
- name: Packing Windows builds
|
||||||
if: matrix.platform.os == 'windows-latest'
|
if: contains(matrix.platform.name, 'win')
|
||||||
run: |
|
run: |
|
||||||
pushd publish
|
pushd publish
|
||||||
rm libarmeilleure-jitsupport.dylib
|
rm libarmeilleure-jitsupport.dylib
|
||||||
7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
||||||
popd
|
popd
|
||||||
|
|
||||||
gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe'
|
|
||||||
|
|
||||||
./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip"
|
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Install GitLabCli
|
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
|
||||||
chmod +x gli
|
|
||||||
mv gli $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Packing Linux builds
|
- name: Packing Linux builds
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
if: contains(matrix.platform.name, 'linux')
|
||||||
run: |
|
run: |
|
||||||
pushd publish
|
pushd publish
|
||||||
rm libarmeilleure-jitsupport.dylib
|
rm libarmeilleure-jitsupport.dylib
|
||||||
chmod +x Ryujinx.sh Ryujinx
|
chmod +x Ryujinx.sh Ryujinx
|
||||||
tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||||
popd
|
popd
|
||||||
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz"
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Build AppImage (Linux)
|
- name: Build AppImage (Linux)
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
if: contains(matrix.platform.name, 'linux')
|
||||||
run: |
|
run: |
|
||||||
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
||||||
PLATFORM_NAME="${{ matrix.platform.name }}"
|
PLATFORM_NAME="${{ matrix.platform.name }}"
|
||||||
|
|
||||||
sudo apt install -y zsync desktop-file-utils appstream
|
sudo apt update && sudo apt install -y zsync desktop-file-utils appstream libfuse2t64
|
||||||
|
|
||||||
mkdir -p tools
|
mkdir -p tools
|
||||||
export PATH="$PATH:$(readlink -f tools)"
|
export PATH="$PATH:$(readlink -f tools)"
|
||||||
|
|
@ -139,17 +130,28 @@ jobs:
|
||||||
pushd publish_appimage
|
pushd publish_appimage
|
||||||
mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
|
mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||||
popd
|
popd
|
||||||
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage"
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
with:
|
||||||
|
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
||||||
|
body: "**Full Changelog:** [`${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}`](https://git.ryujinx.app/projects/Ryubing/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})"
|
||||||
|
repository: "Ryubing/Canary"
|
||||||
|
token: ${{ secrets.RELEASER_TOKEN }}
|
||||||
|
tag_name: ${{ steps.version_info.outputs.build_version }}
|
||||||
|
files: |-
|
||||||
|
release_output/**
|
||||||
|
|
||||||
macos_release:
|
macos_release:
|
||||||
name: Release MacOS universal
|
name: Release MacOS universal
|
||||||
runs-on: ubuntu-24.04
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: ghcr.io/catthehacker/ubuntu:act-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
- uses: actions/setup-dotnet@v5
|
||||||
with:
|
with:
|
||||||
global-json-file: global.json
|
global-json-file: global.json
|
||||||
|
|
||||||
|
|
@ -159,33 +161,25 @@ jobs:
|
||||||
chmod +x llvm.sh
|
chmod +x llvm.sh
|
||||||
sudo ./llvm.sh 17
|
sudo ./llvm.sh 17
|
||||||
|
|
||||||
- name: Install GitLabCli
|
- name: Install GLI
|
||||||
run: |
|
uses: actions/setup-gli@v1
|
||||||
mkdir -p $HOME/.bin
|
with:
|
||||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
chmod +x gli
|
|
||||||
mv gli $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Install rcodesign
|
- name: Install rcodesign
|
||||||
run: |
|
run: |
|
||||||
mkdir -p $HOME/.bin
|
gli ghr -R indygreg/apple-platform-rs -p apple-codesign-*-x86_64-unknown-linux-musl.tar.gz -O apple-codesign.tar.gz
|
||||||
gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz'
|
|
||||||
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
|
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
|
||||||
rm apple-codesign.tar.gz
|
rm apple-codesign.tar.gz
|
||||||
mv rcodesign $HOME/.bin/
|
mv rcodesign /usr/bin/rcodesign
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
run: |
|
run: |
|
||||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
echo "build_version=$(gli get-next-version -c Canary -R)" >> $FORGEJO_OUTPUT
|
||||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
echo "prev_build_version=$(gli get-current-version -c Canary -R)" >> $FORGEJO_OUTPUT
|
||||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
echo "git_short_hash=$(git rev-parse --short "${{ forgejo.sha }}")" >> $FORGEJO_OUTPUT
|
||||||
|
shell: bash
|
||||||
|
|
||||||
- name: Configure for release
|
- name: Configure for release
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -200,47 +194,58 @@ jobs:
|
||||||
- name: Publish macOS Ryujinx
|
- name: Publish macOS Ryujinx
|
||||||
run: |
|
run: |
|
||||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
|
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|publish_ava/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz"
|
|
||||||
|
|
||||||
create_gitlab_release:
|
- name: Create release
|
||||||
name: Create GitLab Release
|
uses: actions/create-release@v1
|
||||||
runs-on: ubuntu-24.04
|
with:
|
||||||
|
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
||||||
|
body: "**Full Changelog:** [`${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}`](https://git.ryujinx.app/projects/Ryubing/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})"
|
||||||
|
repository: "Ryubing/Canary"
|
||||||
|
token: ${{ secrets.RELEASER_TOKEN }}
|
||||||
|
tag_name: ${{ steps.version_info.outputs.build_version }}
|
||||||
|
files: |-
|
||||||
|
publish_ava/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz
|
||||||
|
|
||||||
|
post_ci:
|
||||||
|
name: Post CI Steps
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: ghcr.io/catthehacker/ubuntu:act-latest
|
||||||
needs:
|
needs:
|
||||||
- macos_release
|
- macos_release
|
||||||
- release
|
- release
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
run: |
|
run: |
|
||||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
echo "build_version=$(gli get-next-version -c Canary -R)" >> $FORGEJO_OUTPUT
|
||||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
echo "prev_build_version=$(gli get-current-version -c Canary -R)" >> $FORGEJO_OUTPUT
|
||||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
echo "git_short_hash=$(git rev-parse --short "${{ forgejo.sha }}")" >> $FORGEJO_OUTPUT
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Install GitLabCli
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
|
||||||
chmod +x gli
|
|
||||||
mv gli $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Create tag
|
- name: Create tag
|
||||||
run: |
|
run: |
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateTag "Canary-${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}"
|
gli create-tag -T ${{ secrets.RELEASER_TOKEN }} -P projects/Ryubing -n Canary-${{ steps.version_info.outputs.build_version }} -r ${{ steps.version_info.outputs.git_short_hash }}
|
||||||
|
|
||||||
- name: Create release
|
|
||||||
run: |
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=CreateReleaseFromGenericPackageFiles "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|main|Canary ${{ steps.version_info.outputs.build_version }}|**Full Changelog:** [${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})"
|
|
||||||
|
|
||||||
|
- name: Link to actual source archives for Canary
|
||||||
|
run: |
|
||||||
|
gli canary-release -T ${{ secrets.RELEASER_TOKEN }} -P Ryubing/Canary -r ${{ steps.version_info.outputs.build_version }}
|
||||||
|
|
||||||
- name: Send notification webhook
|
- name: Send notification webhook
|
||||||
run: |
|
run: |
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|FF4500|${{ secrets.CANARY_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4|false"
|
gli send-update-message -T ${{ secrets.RELEASER_TOKEN }} -P Ryubing/Canary -t ${{ steps.version_info.outputs.build_version }} -c FF4500 -w ${{ secrets.CANARY_DISCORD_WEBHOOK }} -i https://avatars.githubusercontent.com/u/192939710?s=200&v=4
|
||||||
|
|
||||||
- name: Notify update server of new builds
|
- name: Notify update server of new builds
|
||||||
run: |
|
run: |
|
||||||
curl 'https://update.ryujinx.app/api/v1/admin/refresh_cache?rc=canary' -X PATCH -H 'accept: */*' -H 'Authorization: ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}'
|
gli refresh-version-cache -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Canary
|
||||||
|
|
||||||
|
- name: Advance to the next version
|
||||||
|
run: |
|
||||||
|
gli increment-version -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Canary
|
||||||
|
|
@ -5,10 +5,6 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
triage:
|
triage:
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -18,11 +14,13 @@ jobs:
|
||||||
with:
|
with:
|
||||||
# Ensure we pin the source origin as pull_request_target run under forks.
|
# Ensure we pin the source origin as pull_request_target run under forks.
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
repository: GreemDev/Ryujinx
|
repository: projects/Ryubing
|
||||||
ref: master
|
ref: master
|
||||||
|
|
||||||
- name: Update labels based on changes
|
- name: Update labels based on changes
|
||||||
uses: actions/labeler@v5
|
uses: actions/labeler@v6
|
||||||
with:
|
with:
|
||||||
|
repo-token: ${{ secrets.LABELER_TOKEN }}
|
||||||
|
configuration-path: .forgejo/labeler.yml
|
||||||
sync-labels: true
|
sync-labels: true
|
||||||
dot: true
|
dot: true
|
||||||
246
.forgejo/workflows/release.yml
Normal file
246
.forgejo/workflows/release.yml
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
name: Stable CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
is_bugfix_release:
|
||||||
|
description: "Bug fix release: If checked, this will increment the third number for only Stable, and leave the Major version alone for both Stable and Canary."
|
||||||
|
required: true
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
concurrency: release
|
||||||
|
|
||||||
|
env:
|
||||||
|
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
|
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
|
||||||
|
RELEASE: 1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Release for ${{ matrix.platform.name }}
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: ${{ matrix.platform.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
platform:
|
||||||
|
- { name: win-x64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: win_x64 }
|
||||||
|
#- { name: win-arm64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: win_arm64 }
|
||||||
|
- { name: linux-x64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: linux_x64 }
|
||||||
|
- { name: linux-arm64, os: ghcr.io/catthehacker/ubuntu:act-latest, zip_os_name: linux_arm64 }
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v5
|
||||||
|
with:
|
||||||
|
global-json-file: global.json
|
||||||
|
|
||||||
|
- name: Overwrite csc problem matcher
|
||||||
|
run: echo "::add-matcher::.github/csc.json"
|
||||||
|
|
||||||
|
- name: Install 7zip
|
||||||
|
run: |
|
||||||
|
sudo apt install -y 7zip
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
|
- name: Get version info
|
||||||
|
id: version_info
|
||||||
|
run: |
|
||||||
|
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
|
||||||
|
echo "build_version=$(gli get-next-version -m -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
else
|
||||||
|
echo "build_version=$(gli get-next-version -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
fi
|
||||||
|
echo "prev_build_version=$(gli get-current-version -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
echo "git_short_hash=$(git rev-parse --short "${{ forgejo.sha }}")" >> $FORGEJO_OUTPUT
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Configure for release
|
||||||
|
run: |
|
||||||
|
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
|
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
|
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_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Create output dir
|
||||||
|
run: "mkdir release_output"
|
||||||
|
|
||||||
|
- name: Publish
|
||||||
|
run: |
|
||||||
|
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./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
|
||||||
|
|
||||||
|
- name: Packing Windows builds
|
||||||
|
if: contains(matrix.platform.name, 'win')
|
||||||
|
run: |
|
||||||
|
pushd publish
|
||||||
|
rm libarmeilleure-jitsupport.dylib
|
||||||
|
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
||||||
|
popd
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Packing Linux builds
|
||||||
|
if: contains(matrix.platform.name, 'linux')
|
||||||
|
run: |
|
||||||
|
pushd publish
|
||||||
|
rm libarmeilleure-jitsupport.dylib
|
||||||
|
chmod +x Ryujinx.sh Ryujinx
|
||||||
|
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||||
|
popd
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Build AppImage (Linux)
|
||||||
|
if: contains(matrix.platform.name, 'linux')
|
||||||
|
run: |
|
||||||
|
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
||||||
|
PLATFORM_NAME="${{ matrix.platform.name }}"
|
||||||
|
|
||||||
|
sudo apt install -y zsync desktop-file-utils appstream
|
||||||
|
|
||||||
|
mkdir -p tools
|
||||||
|
export PATH="$PATH:$(readlink -f tools)"
|
||||||
|
|
||||||
|
# Setup appimagetool
|
||||||
|
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||||
|
chmod +x tools/appimagetool
|
||||||
|
chmod +x distribution/linux/appimage/build-appimage.sh
|
||||||
|
|
||||||
|
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
||||||
|
if [ "$PLATFORM_NAME" = "linux-x64" ]; then
|
||||||
|
ARCH_NAME=x64
|
||||||
|
export ARCH=x86_64
|
||||||
|
elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
|
||||||
|
ARCH_NAME=arm64
|
||||||
|
export ARCH=aarch64
|
||||||
|
else
|
||||||
|
echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
|
||||||
|
|
||||||
|
pushd publish_appimage
|
||||||
|
mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||||
|
popd
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
with:
|
||||||
|
name: "${{ steps.version_info.outputs.build_version }}"
|
||||||
|
repository: "projects/Ryubing"
|
||||||
|
token: ${{ secrets.RELEASER_TOKEN }}
|
||||||
|
tag_name: ${{ steps.version_info.outputs.build_version }}
|
||||||
|
files: |-
|
||||||
|
release_output/**
|
||||||
|
|
||||||
|
macos_release:
|
||||||
|
name: Release MacOS universal
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: ghcr.io/catthehacker/ubuntu:act-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v5
|
||||||
|
with:
|
||||||
|
global-json-file: global.json
|
||||||
|
|
||||||
|
- name: Setup LLVM 17
|
||||||
|
run: |
|
||||||
|
wget https://apt.llvm.org/llvm.sh
|
||||||
|
chmod +x llvm.sh
|
||||||
|
sudo ./llvm.sh 17
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install rcodesign
|
||||||
|
run: |
|
||||||
|
gli ghr -R indygreg/apple-platform-rs -p apple-codesign-*-x86_64-unknown-linux-musl.tar.gz -O apple-codesign.tar.gz
|
||||||
|
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
|
||||||
|
rm apple-codesign.tar.gz
|
||||||
|
mv rcodesign /usr/bin/rcodesign
|
||||||
|
|
||||||
|
- name: Get version info
|
||||||
|
id: version_info
|
||||||
|
run: |
|
||||||
|
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
|
||||||
|
echo "build_version=$(gli get-next-version -m -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
else
|
||||||
|
echo "build_version=$(gli get-next-version -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
fi
|
||||||
|
echo "prev_build_version=$(gli get-current-version -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
echo "git_short_hash=$(git rev-parse --short "${{ forgejo.sha }}")" >> $FORGEJO_OUTPUT
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Configure for release
|
||||||
|
run: |
|
||||||
|
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
|
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
|
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_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Publish macOS Ryujinx
|
||||||
|
run: |
|
||||||
|
bash distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
with:
|
||||||
|
name: "${{ steps.version_info.outputs.build_version }}"
|
||||||
|
repository: "projects/Ryubing"
|
||||||
|
token: ${{ secrets.RELEASER_TOKEN }}
|
||||||
|
tag_name: ${{ steps.version_info.outputs.build_version }}
|
||||||
|
files: |-
|
||||||
|
publish_ava/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz
|
||||||
|
|
||||||
|
post_ci:
|
||||||
|
name: Post-CI Steps
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
needs:
|
||||||
|
- macos_release
|
||||||
|
- release
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install GLI
|
||||||
|
uses: actions/setup-gli@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.SETUP_GLI_TOKEN }}
|
||||||
|
|
||||||
|
- name: Get version info
|
||||||
|
id: version_info
|
||||||
|
run: |
|
||||||
|
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
|
||||||
|
echo "build_version=$(gli get-next-version -m -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
else
|
||||||
|
echo "build_version=$(gli get-next-version -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
fi
|
||||||
|
echo "prev_build_version=$(gli get-current-version -c Stable -R)" >> $FORGEJO_OUTPUT
|
||||||
|
echo "git_short_hash=$(git rev-parse --short "${{ forgejo.sha }}")" >> $FORGEJO_OUTPUT
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Send notification webhook
|
||||||
|
run: |
|
||||||
|
gli send-update-message -T ${{ secrets.RELEASER_TOKEN }} -P projects/Ryubing -t ${{ steps.version_info.outputs.build_version }} -c 32cd32 -w ${{ secrets.STABLE_DISCORD_WEBHOOK }} -i https://avatars.githubusercontent.com/u/192939710?s=200&v=4
|
||||||
|
|
||||||
|
- name: Notify update server of new builds
|
||||||
|
run: |
|
||||||
|
gli refresh-version-cache -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Stable
|
||||||
|
|
||||||
|
- name: Advance to the next version
|
||||||
|
run: |
|
||||||
|
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
|
||||||
|
gli advance-version -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}
|
||||||
|
else
|
||||||
|
gli increment-version -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Stable
|
||||||
|
fi
|
||||||
86
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
86
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -1,86 +0,0 @@
|
||||||
name: Bug Report
|
|
||||||
description: File a bug report
|
|
||||||
title: "[Bug]"
|
|
||||||
labels: bug
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: issue
|
|
||||||
attributes:
|
|
||||||
label: Description of the issue
|
|
||||||
description: What's the issue you encountered?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: repro
|
|
||||||
attributes:
|
|
||||||
label: Reproduction steps
|
|
||||||
description: How can the issue be reproduced?
|
|
||||||
placeholder: Describe each step as precisely as possible
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: log
|
|
||||||
attributes:
|
|
||||||
label: Log file
|
|
||||||
description: "A log file will help our developers to better diagnose and fix the issue. UPLOAD THE FILE. DO NOT COPY AND PASTE THE FILE'S CONTENT."
|
|
||||||
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. They can also be accessed by opening Ryujinx, then going to File > Open Logs Folder. You can drag and drop the log on to the text area (do not copy paste).
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: os
|
|
||||||
attributes:
|
|
||||||
label: OS
|
|
||||||
placeholder: "e.g. Windows 10"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: ryujinx-version
|
|
||||||
attributes:
|
|
||||||
label: Ryujinx version
|
|
||||||
placeholder: "e.g. 1.0.470"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: game-version
|
|
||||||
attributes:
|
|
||||||
label: Game version
|
|
||||||
placeholder: "e.g. 1.1.1"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: input
|
|
||||||
id: cpu
|
|
||||||
attributes:
|
|
||||||
label: CPU
|
|
||||||
placeholder: "e.g. i7-6700"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: input
|
|
||||||
id: gpu
|
|
||||||
attributes:
|
|
||||||
label: GPU
|
|
||||||
placeholder: "e.g. NVIDIA RTX 2070"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: input
|
|
||||||
id: ram
|
|
||||||
attributes:
|
|
||||||
label: RAM
|
|
||||||
placeholder: "e.g. 16GB"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: mods
|
|
||||||
attributes:
|
|
||||||
label: List of applied mods
|
|
||||||
placeholder: You can list applied mods here.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: additional-context
|
|
||||||
attributes:
|
|
||||||
label: Additional context?
|
|
||||||
description: |
|
|
||||||
- Additional info about your environment:
|
|
||||||
- Any other information relevant to your issue.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
|
|
@ -1,5 +0,0 @@
|
||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
|
||||||
- name: Ryujinx Discord
|
|
||||||
url: https://discord.gg/N2FmfVc
|
|
||||||
about: This is for development related issues. For support and technical issues, please come to our Discord server.
|
|
||||||
31
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
31
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
|
|
@ -1,31 +0,0 @@
|
||||||
name: Feature Request
|
|
||||||
description: Suggest a new feature for Ryujinx.
|
|
||||||
title: "[Feature Request]"
|
|
||||||
labels: enhancement
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: overview
|
|
||||||
attributes:
|
|
||||||
label: Overview
|
|
||||||
description: Include the basic, high-level concepts for this feature here.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: details
|
|
||||||
attributes:
|
|
||||||
label: Smaller details
|
|
||||||
description: These may include specific methods of implementation etc.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: request
|
|
||||||
attributes:
|
|
||||||
label: Nature of request
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: feature
|
|
||||||
attributes:
|
|
||||||
label: Why would this feature be useful?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
name: Missing CPU Instruction
|
|
||||||
description: CPU Instruction is missing in Ryujinx.
|
|
||||||
title: "[CPU]"
|
|
||||||
labels: [cpu, not-implemented]
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: instruction
|
|
||||||
attributes:
|
|
||||||
label: CPU instruction
|
|
||||||
description: What CPU instruction is missing?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: name
|
|
||||||
attributes:
|
|
||||||
label: Instruction name
|
|
||||||
description: Include the name from [armconverter.com](https://armconverter.com/?disasm) or [shell-storm.org](http://shell-storm.org/online/Online-Assembler-and-Disassembler/?arch=arm64&endianness=big&dis_with_raw=True&dis_with_ins=True) in the above code block
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: required
|
|
||||||
attributes:
|
|
||||||
label: Required by
|
|
||||||
description: Add links to the [compatibility list page(s)](https://github.com/Ryujinx/Ryujinx-Games-List/issues) of the game(s) that require this instruction.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
25
.github/ISSUE_TEMPLATE/missing_service_call.yml
vendored
25
.github/ISSUE_TEMPLATE/missing_service_call.yml
vendored
|
|
@ -1,25 +0,0 @@
|
||||||
name: Missing Service Call
|
|
||||||
description: Service call is missing in Ryujinx.
|
|
||||||
labels: not-implemented
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: instruction
|
|
||||||
attributes:
|
|
||||||
label: Service call
|
|
||||||
description: What service call is missing?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: name
|
|
||||||
attributes:
|
|
||||||
label: Service description
|
|
||||||
description: Include the description/explanation from [Switchbrew](https://switchbrew.org/w/index.php?title=Services_API) and/or [SwIPC](https://reswitched.github.io/SwIPC/) in the above code block
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: required
|
|
||||||
attributes:
|
|
||||||
label: Required by
|
|
||||||
description: Add links to the [compatibility list page(s)](https://github.com/Ryujinx/Ryujinx-Games-List/issues) of the game(s) that require this service.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
name: Missing Shader Instruction
|
|
||||||
description: Shader Instruction is missing in Ryujinx.
|
|
||||||
title: "[GPU]"
|
|
||||||
labels: [gpu, not-implemented]
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: instruction
|
|
||||||
attributes:
|
|
||||||
label: Shader instruction
|
|
||||||
description: What shader instruction is missing?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: required
|
|
||||||
attributes:
|
|
||||||
label: Required by
|
|
||||||
description: Add links to the [compatibility list page(s)](https://github.com/Ryujinx/Ryujinx-Games-List/issues) of the game(s) that require this instruction.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
168
.github/workflows/build.yml
vendored
168
.github/workflows/build.yml
vendored
|
|
@ -1,168 +0,0 @@
|
||||||
name: Build job
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
|
|
||||||
env:
|
|
||||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
|
||||||
RYUJINX_BASE_VERSION: "1.2.0"
|
|
||||||
RELEASE: 0
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: ${{ matrix.platform.name }} (${{ matrix.configuration }})
|
|
||||||
runs-on: ${{ matrix.platform.os }}
|
|
||||||
timeout-minutes: 45
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
configuration: [Debug, Release]
|
|
||||||
platform:
|
|
||||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
|
||||||
- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
|
||||||
- { 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-13, zip_os_name: osx_x64 }
|
|
||||||
|
|
||||||
fail-fast: false
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
global-json-file: global.json
|
|
||||||
|
|
||||||
- name: Overwrite csc problem matcher
|
|
||||||
run: echo "::add-matcher::.github/csc.json"
|
|
||||||
|
|
||||||
- name: Get git short hash
|
|
||||||
id: git_short_hash
|
|
||||||
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-13'
|
|
||||||
|
|
||||||
- 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-13'
|
|
||||||
|
|
||||||
- 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
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
uses: TSRBerry/unstable-commands@v1
|
|
||||||
with:
|
|
||||||
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.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
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
|
||||||
|
|
||||||
- name: Set executable bit
|
|
||||||
run: |
|
|
||||||
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
|
|
||||||
|
|
||||||
- name: Build AppImage
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
PLATFORM_NAME="${{ matrix.platform.name }}"
|
|
||||||
|
|
||||||
sudo apt install -y zsync desktop-file-utils appstream
|
|
||||||
|
|
||||||
mkdir -p tools
|
|
||||||
export PATH="$PATH:$(readlink -f tools)"
|
|
||||||
|
|
||||||
# Setup appimagetool
|
|
||||||
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
|
||||||
chmod +x tools/appimagetool
|
|
||||||
chmod +x distribution/linux/appimage/build-appimage.sh
|
|
||||||
|
|
||||||
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
|
||||||
if [ "$PLATFORM_NAME" = "linux-x64" ]; then
|
|
||||||
ARCH_NAME=x64
|
|
||||||
export ARCH=x86_64
|
|
||||||
elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
|
|
||||||
ARCH_NAME=arm64
|
|
||||||
export ARCH=aarch64
|
|
||||||
else
|
|
||||||
echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync"
|
|
||||||
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Upload Ryujinx artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
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.platform.os != 'macos-13'
|
|
||||||
|
|
||||||
- name: Upload Ryujinx (AppImage) artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
|
|
||||||
with:
|
|
||||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}-AppImage
|
|
||||||
path: publish_appimage
|
|
||||||
|
|
||||||
build_macos:
|
|
||||||
name: macOS Universal (${{ matrix.configuration }})
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 45
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
configuration: [ Debug, Release ]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
global-json-file: global.json
|
|
||||||
|
|
||||||
- name: Setup LLVM 17
|
|
||||||
run: |
|
|
||||||
wget https://apt.llvm.org/llvm.sh
|
|
||||||
chmod +x llvm.sh
|
|
||||||
sudo ./llvm.sh 17
|
|
||||||
|
|
||||||
- name: Install rcodesign
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz'
|
|
||||||
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
|
|
||||||
rm apple-codesign.tar.gz
|
|
||||||
mv rcodesign $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Get git short hash
|
|
||||||
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
|
|
||||||
run: |
|
|
||||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp publish ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
|
||||||
|
|
||||||
- name: Upload Ryujinx artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
|
||||||
path: "publish/*.tar.gz"
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
25
.github/workflows/checks.yml
vendored
25
.github/workflows/checks.yml
vendored
|
|
@ -1,25 +0,0 @@
|
||||||
name: Build PR
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
paths:
|
|
||||||
- '**'
|
|
||||||
- '!.github/**'
|
|
||||||
- '!*.yml'
|
|
||||||
- '!*.config'
|
|
||||||
- '!*.md'
|
|
||||||
- '.github/workflows/*.yml'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
checks: write
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: pr-checks-${{ github.event.number }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
pr_build:
|
|
||||||
uses: ./.github/workflows/build.yml
|
|
||||||
secrets: inherit
|
|
||||||
224
.github/workflows/debug_release.yml
vendored
224
.github/workflows/debug_release.yml
vendored
|
|
@ -1,224 +0,0 @@
|
||||||
name: Release job (Debug)
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs: {}
|
|
||||||
|
|
||||||
concurrency: release
|
|
||||||
|
|
||||||
env:
|
|
||||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
|
||||||
RYUJINX_BASE_VERSION: "1.3"
|
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
|
|
||||||
RELEASE: 1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: Release for ${{ matrix.platform.name }}
|
|
||||||
runs-on: ${{ matrix.platform.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
platform:
|
|
||||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
|
||||||
#- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
|
||||||
- { 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
|
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
global-json-file: global.json
|
|
||||||
|
|
||||||
- name: Overwrite csc problem matcher
|
|
||||||
run: echo "::add-matcher::.github/csc.json"
|
|
||||||
|
|
||||||
- name: Get version info
|
|
||||||
id: version_info
|
|
||||||
run: |
|
|
||||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT
|
|
||||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
|
||||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Configure for release
|
|
||||||
run: |
|
|
||||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
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_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Create output dir
|
|
||||||
run: "mkdir release_output"
|
|
||||||
|
|
||||||
- name: Publish
|
|
||||||
run: |
|
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./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
|
|
||||||
|
|
||||||
- name: Packing Windows builds
|
|
||||||
if: matrix.platform.os == 'windows-latest'
|
|
||||||
run: |
|
|
||||||
pushd publish
|
|
||||||
rm libarmeilleure-jitsupport.dylib
|
|
||||||
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
|
||||||
popd
|
|
||||||
|
|
||||||
gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe'
|
|
||||||
|
|
||||||
./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip"
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Install GitLabCli
|
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
|
||||||
chmod +x gli
|
|
||||||
mv gli $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Packing Linux builds
|
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
pushd publish
|
|
||||||
rm libarmeilleure-jitsupport.dylib
|
|
||||||
chmod +x Ryujinx.sh Ryujinx
|
|
||||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
|
||||||
popd
|
|
||||||
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz"
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Build AppImage (Linux)
|
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
|
||||||
PLATFORM_NAME="${{ matrix.platform.name }}"
|
|
||||||
|
|
||||||
sudo apt install -y zsync desktop-file-utils appstream
|
|
||||||
|
|
||||||
mkdir -p tools
|
|
||||||
export PATH="$PATH:$(readlink -f tools)"
|
|
||||||
|
|
||||||
# Setup appimagetool
|
|
||||||
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
|
||||||
chmod +x tools/appimagetool
|
|
||||||
chmod +x distribution/linux/appimage/build-appimage.sh
|
|
||||||
|
|
||||||
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
|
||||||
if [ "$PLATFORM_NAME" = "linux-x64" ]; then
|
|
||||||
ARCH_NAME=x64
|
|
||||||
export ARCH=x86_64
|
|
||||||
elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
|
|
||||||
ARCH_NAME=arm64
|
|
||||||
export ARCH=aarch64
|
|
||||||
else
|
|
||||||
echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync"
|
|
||||||
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
|
|
||||||
|
|
||||||
pushd publish_appimage
|
|
||||||
mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
|
|
||||||
mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
|
|
||||||
popd
|
|
||||||
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage"
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
macos_release:
|
|
||||||
name: Release MacOS universal
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
global-json-file: global.json
|
|
||||||
|
|
||||||
- name: Setup LLVM 17
|
|
||||||
run: |
|
|
||||||
wget https://apt.llvm.org/llvm.sh
|
|
||||||
chmod +x llvm.sh
|
|
||||||
sudo ./llvm.sh 17
|
|
||||||
|
|
||||||
- name: Install GitLabCli
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
|
||||||
chmod +x gli
|
|
||||||
mv gli $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Install rcodesign
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz'
|
|
||||||
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
|
|
||||||
rm apple-codesign.tar.gz
|
|
||||||
mv rcodesign $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Get version info
|
|
||||||
id: version_info
|
|
||||||
run: |
|
|
||||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT
|
|
||||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
|
||||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Configure for release
|
|
||||||
run: |
|
|
||||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
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_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Publish macOS Ryujinx
|
|
||||||
run: |
|
|
||||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz"
|
|
||||||
|
|
||||||
create_gitlab_release:
|
|
||||||
name: Create GitLab Release
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs:
|
|
||||||
- macos_release
|
|
||||||
- release
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get version info
|
|
||||||
id: version_info
|
|
||||||
run: |
|
|
||||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT
|
|
||||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
|
||||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Install GitLabCli
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
|
||||||
chmod +x gli
|
|
||||||
mv gli $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Create release
|
|
||||||
run: |
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|test|THIS IS NOT INTENDED FOR END USER USAGE"
|
|
||||||
231
.github/workflows/release.yml
vendored
231
.github/workflows/release.yml
vendored
|
|
@ -1,231 +0,0 @@
|
||||||
name: Release job
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs: {}
|
|
||||||
|
|
||||||
concurrency: release
|
|
||||||
|
|
||||||
env:
|
|
||||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
|
||||||
RYUJINX_BASE_VERSION: "1.3"
|
|
||||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
|
|
||||||
RELEASE: 1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: Release for ${{ matrix.platform.name }}
|
|
||||||
runs-on: ${{ matrix.platform.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
platform:
|
|
||||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
|
||||||
#- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
|
||||||
- { 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
|
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
global-json-file: global.json
|
|
||||||
|
|
||||||
- name: Overwrite csc problem matcher
|
|
||||||
run: echo "::add-matcher::.github/csc.json"
|
|
||||||
|
|
||||||
- name: Get version info
|
|
||||||
id: version_info
|
|
||||||
run: |
|
|
||||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
|
||||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
|
||||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Configure for release
|
|
||||||
run: |
|
|
||||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
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_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Create output dir
|
|
||||||
run: "mkdir release_output"
|
|
||||||
|
|
||||||
- name: Publish
|
|
||||||
run: |
|
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./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
|
|
||||||
|
|
||||||
- name: Packing Windows builds
|
|
||||||
if: matrix.platform.os == 'windows-latest'
|
|
||||||
run: |
|
|
||||||
pushd publish
|
|
||||||
rm libarmeilleure-jitsupport.dylib
|
|
||||||
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
|
||||||
popd
|
|
||||||
|
|
||||||
gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe'
|
|
||||||
|
|
||||||
./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip"
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Install GitLabCli
|
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
|
||||||
chmod +x gli
|
|
||||||
mv gli $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Packing Linux builds
|
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
pushd publish
|
|
||||||
rm libarmeilleure-jitsupport.dylib
|
|
||||||
chmod +x Ryujinx.sh Ryujinx
|
|
||||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
|
||||||
popd
|
|
||||||
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz"
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build AppImage (Linux)
|
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
|
||||||
run: |
|
|
||||||
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
|
||||||
PLATFORM_NAME="${{ matrix.platform.name }}"
|
|
||||||
|
|
||||||
sudo apt install -y zsync desktop-file-utils appstream
|
|
||||||
|
|
||||||
mkdir -p tools
|
|
||||||
export PATH="$PATH:$(readlink -f tools)"
|
|
||||||
|
|
||||||
# Setup appimagetool
|
|
||||||
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
|
||||||
chmod +x tools/appimagetool
|
|
||||||
chmod +x distribution/linux/appimage/build-appimage.sh
|
|
||||||
|
|
||||||
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
|
||||||
if [ "$PLATFORM_NAME" = "linux-x64" ]; then
|
|
||||||
ARCH_NAME=x64
|
|
||||||
export ARCH=x86_64
|
|
||||||
elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
|
|
||||||
ARCH_NAME=arm64
|
|
||||||
export ARCH=aarch64
|
|
||||||
else
|
|
||||||
echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
|
|
||||||
|
|
||||||
pushd publish_appimage
|
|
||||||
mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
|
|
||||||
popd
|
|
||||||
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage"
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
macos_release:
|
|
||||||
name: Release MacOS universal
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
global-json-file: global.json
|
|
||||||
|
|
||||||
- name: Setup LLVM 17
|
|
||||||
run: |
|
|
||||||
wget https://apt.llvm.org/llvm.sh
|
|
||||||
chmod +x llvm.sh
|
|
||||||
sudo ./llvm.sh 17
|
|
||||||
|
|
||||||
- name: Install GitLabCli
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
|
||||||
chmod +x gli
|
|
||||||
mv gli $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Install rcodesign
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz'
|
|
||||||
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
|
|
||||||
rm apple-codesign.tar.gz
|
|
||||||
mv rcodesign $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Get version info
|
|
||||||
id: version_info
|
|
||||||
run: |
|
|
||||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
|
||||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
|
||||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Configure for release
|
|
||||||
run: |
|
|
||||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
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_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Publish macOS Ryujinx
|
|
||||||
run: |
|
|
||||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz"
|
|
||||||
|
|
||||||
create_gitlab_release:
|
|
||||||
name: Create GitLab Release
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs:
|
|
||||||
- macos_release
|
|
||||||
- release
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get version info
|
|
||||||
id: version_info
|
|
||||||
run: |
|
|
||||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
|
||||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
|
||||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Install GitLabCli
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.bin
|
|
||||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
|
||||||
chmod +x gli
|
|
||||||
mv gli $HOME/.bin/
|
|
||||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Create release
|
|
||||||
run: |
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|${{ steps.version_info.outputs.build_version }}|msd:${{ steps.version_info.outputs.build_version }}"
|
|
||||||
|
|
||||||
- name: Send notification webhook
|
|
||||||
run: |
|
|
||||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|32cd32|${{ secrets.STABLE_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4|false"
|
|
||||||
|
|
||||||
- name: Notify update server of new builds
|
|
||||||
run: |
|
|
||||||
curl 'https://update.ryujinx.app/api/v1/admin/refresh_cache?rc=stable' -X PATCH -H 'accept: */*' -H 'Authorization: ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}'
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -100,6 +100,7 @@ DocProject/Help/html
|
||||||
|
|
||||||
# Click-Once directory
|
# Click-Once directory
|
||||||
publish/
|
publish/
|
||||||
|
RyubingMaintainerTools/
|
||||||
|
|
||||||
# Publish Web Output
|
# Publish Web Output
|
||||||
*.Publish.xml
|
*.Publish.xml
|
||||||
|
|
|
||||||
|
|
@ -3,26 +3,26 @@
|
||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia" Version="11.3.6" />
|
<PackageVersion Include="Avalonia" Version="11.3.12" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.6" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.12" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.6" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.3.12" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.6" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.12" />
|
||||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.6" />
|
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.12" />
|
||||||
<PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.6.2" />
|
<PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.9.4" />
|
||||||
<PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.6.2" />
|
<PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.9.4" />
|
||||||
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
|
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
|
||||||
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
|
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
|
||||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.6.2" />
|
<PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.6.2" />
|
||||||
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.6.2" />
|
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.6.2" />
|
||||||
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.6.2" />
|
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.6.2" />
|
||||||
<PackageVersion Include="ppy.SDL3-CS" Version="2025.920.0" />
|
<PackageVersion Include="ppy.SDL3-CS" Version="2026.320.0" />
|
||||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||||
<PackageVersion Include="Concentus" Version="2.2.2" />
|
<PackageVersion Include="Concentus" Version="2.2.2" />
|
||||||
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
|
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
|
||||||
<PackageVersion Include="DynamicData" Version="9.4.1" />
|
<PackageVersion Include="DynamicData" Version="9.4.1" />
|
||||||
<PackageVersion Include="FluentAvaloniaUI.NoAnim" Version="2.4.0-build3" />
|
<PackageVersion Include="FluentAvaloniaUI" Version="2.5.0" />
|
||||||
<PackageVersion Include="Humanizer" Version="2.14.1" />
|
<PackageVersion Include="Humanizer" Version="2.14.1" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.126" />
|
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.129" />
|
||||||
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.44" />
|
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.44" />
|
||||||
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.44" />
|
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.44" />
|
||||||
<PackageVersion Include="Gommon" Version="2.8.0.1" />
|
<PackageVersion Include="Gommon" Version="2.8.0.1" />
|
||||||
|
|
@ -56,7 +56,6 @@
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.2" />
|
<PackageVersion Include="System.IO.Hashing" Version="9.0.2" />
|
||||||
<PackageVersion Include="System.Management" Version="9.0.2" />
|
|
||||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
24
README.md
24
README.md
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
# Ryujinx
|
# Ryujinx
|
||||||
|
|
||||||
[](https://update.ryujinx.app/latest/stable)
|
[](https://update.ryujinx.app/latest/stable)
|
||||||
[](https://update.ryujinx.app/latest/canary)
|
[](https://update.ryujinx.app/latest/canary)
|
||||||
<br>
|
<br>
|
||||||
<a href="https://discord.gg/PEuzjrFXUA">
|
<a href="https://discord.gg/PEuzjrFXUA">
|
||||||
<img src="https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Ryubing&logo=discord&logoColor=white" alt="Discord">
|
<img src="https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Ryubing&logo=discord&logoColor=white" alt="Discord">
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
Ryujinx is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
|
Ryujinx is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
|
||||||
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
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.
|
It was written from scratch and development on the project began in September 2017.
|
||||||
Ryujinx is available on a self-managed GitLab instance under the <a href="https://git.ryujinx.app/ryubing/ryujinx/-/blob/master/LICENSE.txt?ref_type=heads" target="_blank">MIT license</a>.
|
Ryujinx is available on a self-managed <a href="https://github.com/Ryubing/forgejo" target="_blank">modified</a> <a href="https://forgejo.org/" target="_blank">Forgejo</a> instance under the <a href="https://git.ryujinx.app/projects/Ryubing/src/branch/master/LICENSE.txt" target="_blank">MIT license</a>.
|
||||||
<br />
|
<br />
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
|
|
@ -31,11 +31,11 @@
|
||||||
<br>
|
<br>
|
||||||
This is not a Ryujinx revival project. This is not a Phoenix project.
|
This is not a Ryujinx revival project. This is not a Phoenix project.
|
||||||
<br>
|
<br>
|
||||||
Guides and documentation can be found on the <a href="https://git.ryujinx.app/groups/ryubing/-/wikis/home">Wiki tab</a>.
|
Guides and documentation can be found on the <a href="https://git.ryujinx.app/projects/Ryubing/wiki/Home">Wiki tab</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://git.ryujinx.app/ryubing/ryujinx/-/raw/master/docs/shell.png?ref_type=heads&inline=false" alt="Ryujinx example">
|
<img src="https://git.ryujinx.app/projects/Ryubing/raw/branch/master/docs/shell.png" alt="Ryujinx example">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
@ -49,17 +49,17 @@ Stable builds are made every so often, based on the `master` branch, that then g
|
||||||
These stable builds exist so that the end user can get a more **enjoyable and stable experience**.
|
These stable builds exist so that the end user can get a more **enjoyable and stable experience**.
|
||||||
They are released every month or so, to ensure consistent updates, while not being an annoying amount of individual updates to download over the course of that month.
|
They are released every month or so, to ensure consistent updates, while not being an annoying amount of individual updates to download over the course of that month.
|
||||||
|
|
||||||
You can find the stable releases [here](https://git.ryujinx.app/ryubing/ryujinx/-/releases).
|
You can find the stable releases [here](https://git.ryujinx.app/projects/Ryubing/releases).
|
||||||
|
|
||||||
Canary builds are compiled automatically for each commit on the `master` branch.
|
Canary 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, these builds **may be unstable or completely broken**.
|
While we strive to ensure optimal stability and performance prior to pushing an update, these builds **may be unstable or completely broken**.
|
||||||
These canary builds are only recommended for experienced users.
|
These canary builds are only recommended for experienced users.
|
||||||
|
|
||||||
You can find the canary releases [here](https://git.ryujinx.app/ryubing/canary/-/releases).
|
You can find the canary releases [here](https://git.ryujinx.app/Ryubing/Canary/releases).
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
If you are planning to contribute or just want to learn more about this project please read through our [documentation](docs/README.md).
|
If you are planning to contribute or just want to learn more about this project please read through our [documentation](https://git.ryujinx.app/projects/Ryubing/src/branch/master/docs/README.md).
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|
@ -105,13 +105,13 @@ If you are planning to contribute or just want to learn more about this project
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This software is licensed under the terms of the [MIT license](LICENSE.txt).
|
This software is licensed under the terms of the [MIT license](https://git.ryujinx.app/projects/Ryubing/src/branch/master/LICENSE.txt).
|
||||||
This project makes use of code authored by the libvpx project, licensed under BSD and the ffmpeg project, licensed under LGPLv3.
|
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.
|
See [LICENSE.txt](https://git.ryujinx.app/projects/Ryubing/src/branch/master/LICENSE.txt) and [THIRDPARTY.md](https://git.ryujinx.app/projects/Ryubing/src/branch/master/distribution/legal/THIRDPARTY.md) for more details.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
- [LibHac](https://git.ryujinx.app/ryubing/libhac) is used for our file-system.
|
- [LibHac](https://git.ryujinx.app/projects/LibHac) is used for our file-system.
|
||||||
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
|
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
|
||||||
- [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) is used for one of our available multiplayer modes.
|
- [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) is used for one of our available multiplayer modes.
|
||||||
- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
|
- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
|
||||||
|
|
|
||||||
34
Ryujinx.sln
34
Ryujinx.sln
|
|
@ -21,6 +21,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.GAL", "src
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.OpenGL", "src\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj", "{9558FB96-075D-4219-8FFF-401979DC0B69}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.OpenGL", "src\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj", "{9558FB96-075D-4219-8FFF-401979DC0B69}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.RenderDoc", "src\Ryujinx.Graphics.RenderDocApi\Ryujinx.Graphics.RenderDocApi.csproj", "{D58FA894-27D5-4EAA-9042-AD422AD82931}"
|
||||||
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Texture", "src\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj", "{E1B1AD28-289D-47B7-A106-326972240207}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Texture", "src\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj", "{E1B1AD28-289D-47B7-A106-326972240207}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Shader", "src\Ryujinx.Graphics.Shader\Ryujinx.Graphics.Shader.csproj", "{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Shader", "src\Ryujinx.Graphics.Shader\Ryujinx.Graphics.Shader.csproj", "{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}"
|
||||||
|
|
@ -45,6 +47,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vic", "src
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "src\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "src\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.Apple", "src\Ryujinx.Audio.Backends.Apple\Ryujinx.Audio.Backends.Apple.csproj", "{AC26EFF0-8593-4184-9A09-98E37EFFB32E}"
|
||||||
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL3", "src\Ryujinx.Audio.Backends.SDL3\Ryujinx.Audio.Backends.SDL3.csproj", "{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL3", "src\Ryujinx.Audio.Backends.SDL3\Ryujinx.Audio.Backends.SDL3.csproj", "{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.OpenAL", "src\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj", "{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.OpenAL", "src\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj", "{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}"
|
||||||
|
|
@ -82,11 +86,11 @@ EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
.github\workflows\build.yml = .github\workflows\build.yml
|
.forgejo\workflows\build.yml = .forgejo\workflows\build.yml
|
||||||
.github\workflows\canary.yml = .github\workflows\canary.yml
|
.forgejo\workflows\canary.yml = .forgejo\workflows\canary.yml
|
||||||
Directory.Packages.props = Directory.Packages.props
|
Directory.Packages.props = Directory.Packages.props
|
||||||
Directory.Build.props = Directory.Build.props
|
Directory.Build.props = Directory.Build.props
|
||||||
.github\workflows\release.yml = .github\workflows\release.yml
|
.forgejo\workflows\release.yml = .forgejo\workflows\release.yml
|
||||||
nuget.config = nuget.config
|
nuget.config = nuget.config
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -555,6 +559,30 @@ Global
|
||||||
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x64.Build.0 = Release|Any CPU
|
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x86.ActiveCfg = Release|Any CPU
|
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x86.Build.0 = Release|Any CPU
|
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{D58FA894-27D5-4EAA-9042-AD422AD82931}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{AC26EFF0-8593-4184-9A09-98E37EFFB32E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
||||||
24
assets/Languages.json
Normal file
24
assets/Languages.json
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"Languages": {
|
||||||
|
"ar_SA": "اَلْعَرَبِيَّةُ",
|
||||||
|
"de_DE": "Deutsch",
|
||||||
|
"el_GR": "Ελληνικά",
|
||||||
|
"en_US": "English (US)",
|
||||||
|
"es_ES": "Español (ES)",
|
||||||
|
"fr_FR": "Français (FR)",
|
||||||
|
"he_IL": "עִברִית",
|
||||||
|
"it_IT": "Italiano",
|
||||||
|
"ja_JP": "日本語",
|
||||||
|
"ko_KR": "한국어",
|
||||||
|
"no_NO": "Norsk",
|
||||||
|
"pl_PL": "Polski",
|
||||||
|
"pt_BR": "Português (BR)",
|
||||||
|
"ru_RU": "Русский",
|
||||||
|
"sv_SE": "Svenska",
|
||||||
|
"th_TH": "ภาษาไทย",
|
||||||
|
"tr_TR": "Türkçe",
|
||||||
|
"uk_UA": "Українська",
|
||||||
|
"zh_CN": "简体中文",
|
||||||
|
"zh_TW": "繁體中文 (台灣)"
|
||||||
|
}
|
||||||
|
}
|
||||||
60
assets/Locales.md
Normal file
60
assets/Locales.md
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
|
||||||
|
# Ryubing Locales
|
||||||
|
|
||||||
|
Ryubing Locales uses a custom format, which uses a file for defining the supported languages and a folder of json files for the locales themselves.
|
||||||
|
Each json file holds the locales for a specific part of the emulator, e.g. the Setup Wizard locales are in `SetupWizard.json`, and each locale entry in the file includes all the supported languages in the same place.
|
||||||
|
|
||||||
|
## Languages
|
||||||
|
in the `/assets/` folder you will find the `Languages.json` file, which defines all the languages supported by the emulator.
|
||||||
|
The file includes a table of the langauge codes and their langauge names.
|
||||||
|
|
||||||
|
#Example of the format for Languages.json
|
||||||
|
{
|
||||||
|
"Languages": {
|
||||||
|
"ar_SA": "اَلْعَرَبِيَّةُ",
|
||||||
|
"en_US": "English (US)",
|
||||||
|
...
|
||||||
|
"zh_TW": "繁體中文 (台灣)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## Locales
|
||||||
|
in the `/assets/Locales/` folder you will find the json files, which define all the locales supported by the emulator.
|
||||||
|
Each json file holds locales for a specific part of the emulator in a large array of locale objects.
|
||||||
|
Each locale is made up an ID used for lookup and a list of the languages and their matching translations.
|
||||||
|
Any empty string or null value will automatically use the English translation instead in the emulator.
|
||||||
|
|
||||||
|
### Format
|
||||||
|
When adding a new locale, you just need to add the ID and the en_US language translation, then the validation system will add default values for the rest of languages automatically, when rebuilding the project.
|
||||||
|
If you want to signal that a translation is supposed to match the English translation, you just have to replace the empty string with `null`.
|
||||||
|
When you want to check what translations are missing for a language just search for `"<lang_code>": ""`, e.g: `"en_US": ""` (but with any other language, as English will never be missing translations).
|
||||||
|
|
||||||
|
### Legacy file (Root.json)
|
||||||
|
Currently all older locales are stored in `Root.json`, but they are slowly being moved into newer, more descriptive json files, to make the locale system more accessible.
|
||||||
|
Do **not** add new locales to `Root.json`.
|
||||||
|
If no json file exists for the specific part of the emulator you're working on, you should instead add a new json file for that part.
|
||||||
|
|
||||||
|
#Example of the format for Root.json
|
||||||
|
{
|
||||||
|
"Locales": [
|
||||||
|
{
|
||||||
|
"ID": "MenuBarActionsOpenMiiEditor",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"en_US": "Mii Editor",
|
||||||
|
...
|
||||||
|
"zh_TW": "Mii 編輯器"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "KeyNumber9",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "٩",
|
||||||
|
"en_US": "9",
|
||||||
|
...
|
||||||
|
"zh_TW": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
104
assets/Locales/RenderDoc.json
Normal file
104
assets/Locales/RenderDoc.json
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
{
|
||||||
|
"Locales": [
|
||||||
|
{
|
||||||
|
"ID": "MenuBarActions_StartCapture",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Start RenderDoc Frame Capture",
|
||||||
|
"es_ES": "Iniciar una captura de fotograma de RenderDoc",
|
||||||
|
"fr_FR": "Démarrer une capture de trame RenderDoc",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "RenderDoc 프레임 캡처 시작",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "启动 RenderDoc 帧捕获",
|
||||||
|
"zh_TW": "啟動 RenderDoc 畫格擷取"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "MenuBarActions_EndCapture",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "End RenderDoc Frame Capture",
|
||||||
|
"es_ES": "Detener la captura de fotograma de RenderDoc",
|
||||||
|
"fr_FR": "Arrêter la capture de trame RenderDoc",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "RenderDoc 프레임 캡처 종료",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "结束 RenderDoc 帧捕获",
|
||||||
|
"zh_TW": "停止 RenderDoc 畫格擷取"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "MenuBarActions_DiscardCapture",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Discard RenderDoc Frame Capture",
|
||||||
|
"es_ES": "Descartar la captura de fotograma de RenderDoc",
|
||||||
|
"fr_FR": "Supprimer la capture de trame RenderDoc",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "RenderDoc 프레임 캡처 폐기",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "丢弃 RenderDoc 帧捕获",
|
||||||
|
"zh_TW": "捨棄 RenderDoc 畫格擷取"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "MenuBarActions_DiscardCapture_ToolTip",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Ends the currently active RenderDoc Frame Capture, immediately discarding its result.",
|
||||||
|
"es_ES": "Finaliza la captura de fotograma de RenderDoc actualmente activa y descarta inmediatamente su resultado.",
|
||||||
|
"fr_FR": "Met fin à la capture de trame RenderDoc en cours, en supprimant immédiatement son résultat.",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "현재 활성화된 RenderDoc 프레임 캡처를 종료하고 결과를 즉시 폐기합니다.",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "结束当前正在进行的 RenderDoc 帧捕获,并立即丢弃其结果。",
|
||||||
|
"zh_TW": "停止正在執行的 RenderDoc 畫格擷取,且立即捨棄其結果。"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -1,72 +1,5 @@
|
||||||
{
|
{
|
||||||
"Info": {
|
|
||||||
"Format1": "The Locale file uses a custom Unified format.",
|
|
||||||
"Format2": "The file starts with a list of all the supported languages.",
|
|
||||||
"Format3": "Each locale is made up an ID used for lookup and a list",
|
|
||||||
"Format4": "of the languages and their matching translations.",
|
|
||||||
"Format5": "When adding a new locale you just need to add the ID and",
|
|
||||||
"Format6": "the en_US language translation, then the validation system",
|
|
||||||
"Format7": "will add the rest of the languages automatically on rebuild.",
|
|
||||||
"Format8": "By default the languages will be added with an empty string.",
|
|
||||||
"Format9": "Any empty string or null value will automatically match the",
|
|
||||||
"Format10": "English translation.",
|
|
||||||
"Format11": "If you want to signal that a translation is supposed to",
|
|
||||||
"Format12": "match the English translation, you just have to replace the",
|
|
||||||
"Format13": "empty string with null.",
|
|
||||||
"Format14": "Translators who want to check what translations are missing",
|
|
||||||
"Format15": "for their language just need to search for:",
|
|
||||||
"Format16": "{'lang_code': ''} with double quotes instead of single",
|
|
||||||
"Format17": "e.g: {'en_US': ''} (but with any other language as English",
|
|
||||||
"Format18": "will never be missing translations)."
|
|
||||||
},
|
|
||||||
"Languages": [
|
|
||||||
"ar_SA",
|
|
||||||
"de_DE",
|
|
||||||
"el_GR",
|
|
||||||
"en_US",
|
|
||||||
"es_ES",
|
|
||||||
"fr_FR",
|
|
||||||
"he_IL",
|
|
||||||
"it_IT",
|
|
||||||
"ja_JP",
|
|
||||||
"ko_KR",
|
|
||||||
"no_NO",
|
|
||||||
"pl_PL",
|
|
||||||
"pt_BR",
|
|
||||||
"ru_RU",
|
|
||||||
"sv_SE",
|
|
||||||
"th_TH",
|
|
||||||
"tr_TR",
|
|
||||||
"uk_UA",
|
|
||||||
"zh_CN",
|
|
||||||
"zh_TW"
|
|
||||||
],
|
|
||||||
"Locales": [
|
"Locales": [
|
||||||
{
|
|
||||||
"ID": "Language",
|
|
||||||
"Translations": {
|
|
||||||
"ar_SA": "اَلْعَرَبِيَّةُ",
|
|
||||||
"de_DE": "Deutsch",
|
|
||||||
"el_GR": "Ελληνικά",
|
|
||||||
"en_US": "English (US)",
|
|
||||||
"es_ES": "Español (ES)",
|
|
||||||
"fr_FR": "Français (FR)",
|
|
||||||
"he_IL": "עִברִית",
|
|
||||||
"it_IT": "Italiano",
|
|
||||||
"ja_JP": "日本語",
|
|
||||||
"ko_KR": "한국어",
|
|
||||||
"no_NO": "Norsk",
|
|
||||||
"pl_PL": "Polski",
|
|
||||||
"pt_BR": "Português (BR)",
|
|
||||||
"ru_RU": "Русский",
|
|
||||||
"sv_SE": "Svenska",
|
|
||||||
"th_TH": "ภาษาไทย",
|
|
||||||
"tr_TR": "Türkçe",
|
|
||||||
"uk_UA": "Українська",
|
|
||||||
"zh_CN": "简体中文",
|
|
||||||
"zh_TW": "繁體中文 (台灣)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ID": "MenuBarActionsOpenMiiEditor",
|
"ID": "MenuBarActionsOpenMiiEditor",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
|
@ -225,7 +158,7 @@
|
||||||
"el_GR": "Χωρίς Ελέγχους (γρηγορότερο, μη ασφαλές)",
|
"el_GR": "Χωρίς Ελέγχους (γρηγορότερο, μη ασφαλές)",
|
||||||
"en_US": "Host Unchecked (Fastest, Unsafe)",
|
"en_US": "Host Unchecked (Fastest, Unsafe)",
|
||||||
"es_ES": "Host Sin Verificación (Más rápido, Inseguro)",
|
"es_ES": "Host Sin Verificación (Más rápido, Inseguro)",
|
||||||
"fr_FR": "Hôte Non Vérifié (plus rapide, non sécurisé)",
|
"fr_FR": "Hôte Non Vérifié (Plus Rapide, Non Sécurisé)",
|
||||||
"he_IL": "מארח לא מבוקר (המהיר ביותר, לא בטוח)",
|
"he_IL": "מארח לא מבוקר (המהיר ביותר, לא בטוח)",
|
||||||
"it_IT": "Host senza verifica (più veloce, non sicura)",
|
"it_IT": "Host senza verifica (più veloce, non sicura)",
|
||||||
"ja_JP": "ホスト, チェックなし (最高速, 安全でない)",
|
"ja_JP": "ホスト, チェックなし (最高速, 安全でない)",
|
||||||
|
|
@ -642,6 +575,31 @@
|
||||||
"zh_TW": "停止模擬"
|
"zh_TW": "停止模擬"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "MenuBarOptionsRestartEmulation",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Restart Emulation",
|
||||||
|
"es_ES": "Reiniciar Emulación",
|
||||||
|
"fr_FR": "Redémarrer l'Émulation",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "Starta om emulering",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": "重新啟動模擬"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "MenuBarOptionsSettings",
|
"ID": "MenuBarOptionsSettings",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
|
@ -767,6 +725,56 @@
|
||||||
"zh_TW": "掃描 Amiibo"
|
"zh_TW": "掃描 Amiibo"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "MenuBarActionsScanSkylander",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "فحص Skylander",
|
||||||
|
"de_DE": "Skylander scannen",
|
||||||
|
"el_GR": "Σάρωση Skylander",
|
||||||
|
"en_US": "Scan A Skylander",
|
||||||
|
"es_ES": "Escanear Skylander",
|
||||||
|
"fr_FR": "Scanner un Skylander",
|
||||||
|
"he_IL": "סרוק אמיבו",
|
||||||
|
"it_IT": "Scansiona un Skylander",
|
||||||
|
"ja_JP": "Skylander をスキャン",
|
||||||
|
"ko_KR": "Skylander 스캔",
|
||||||
|
"no_NO": "Skann en Skylander",
|
||||||
|
"pl_PL": "Skanuj Skylander",
|
||||||
|
"pt_BR": "Escanear um Skylander",
|
||||||
|
"ru_RU": "Сканировать Skylander",
|
||||||
|
"sv_SE": "Skanna en Skylander",
|
||||||
|
"th_TH": "สแกนหา Skylander",
|
||||||
|
"tr_TR": "Bir Skylander Tara",
|
||||||
|
"uk_UA": "Сканувати Skylander",
|
||||||
|
"zh_CN": "扫描 Skylander",
|
||||||
|
"zh_TW": "掃描 Skylander"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "MenuBarActionsRemoveSkylander",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "إزالة Skylander",
|
||||||
|
"de_DE": "Skylander entfernen",
|
||||||
|
"el_GR": "Αφαίρεση Skylander",
|
||||||
|
"en_US": "Remove Skylander",
|
||||||
|
"es_ES": "Eliminar Skylander",
|
||||||
|
"fr_FR": "Supprimer un Skylander",
|
||||||
|
"he_IL": "הסר Skylander",
|
||||||
|
"it_IT": "Rimuovi Skylander",
|
||||||
|
"ja_JP": "Skylander を削除",
|
||||||
|
"ko_KR": "Skylander 제거",
|
||||||
|
"no_NO": "Fjern Skylander",
|
||||||
|
"pl_PL": "Usuń Skylander",
|
||||||
|
"pt_BR": "Remover um Skylander",
|
||||||
|
"ru_RU": "Удалить Skylander",
|
||||||
|
"sv_SE": "Ta bort Skylander",
|
||||||
|
"th_TH": "ลบ Skylander",
|
||||||
|
"tr_TR": "Skylander'ı Kaldır",
|
||||||
|
"uk_UA": "Видалити Skylander",
|
||||||
|
"zh_CN": "移除 Skylander",
|
||||||
|
"zh_TW": "移除 Skylander"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "MenuBarActionsScanAmiiboBin",
|
"ID": "MenuBarActionsScanAmiiboBin",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
|
@ -3350,7 +3358,7 @@
|
||||||
"el_GR": "Ερώτημα",
|
"el_GR": "Ερώτημα",
|
||||||
"en_US": "Prompt",
|
"en_US": "Prompt",
|
||||||
"es_ES": "Al Inicio",
|
"es_ES": "Al Inicio",
|
||||||
"fr_FR": "Demande",
|
"fr_FR": "Demander",
|
||||||
"he_IL": "הודעה",
|
"he_IL": "הודעה",
|
||||||
"it_IT": "Domanda",
|
"it_IT": "Domanda",
|
||||||
"ja_JP": "プロンプト",
|
"ja_JP": "プロンプト",
|
||||||
|
|
@ -3800,7 +3808,7 @@
|
||||||
"el_GR": "DLC/Ενημερώσεις για αρχεία/παιχνίδια που λείπουν θα αποφορτωθούν αυτόματα",
|
"el_GR": "DLC/Ενημερώσεις για αρχεία/παιχνίδια που λείπουν θα αποφορτωθούν αυτόματα",
|
||||||
"en_US": "DLC/Updates Referring To Missing Files/Games Will Unload Automatically",
|
"en_US": "DLC/Updates Referring To Missing Files/Games Will Unload Automatically",
|
||||||
"es_ES": "DLC/Actualizaciones que hacen referencia a archivos/juegos ausentes se descargarán automáticamente",
|
"es_ES": "DLC/Actualizaciones que hacen referencia a archivos/juegos ausentes se descargarán automáticamente",
|
||||||
"fr_FR": "DLC/Mises à jour concernant des fichiers/jeux manquants seront déchargées automatiquement",
|
"fr_FR": "DLC/Mises à Jour Concernant des Fichiers/Jeux Manquants Seront Déchargées Automatiquement",
|
||||||
"he_IL": "DLC/עדכונים המתייחסים לקבצים/משחקים חסרים יוסרו אוטומטית",
|
"he_IL": "DLC/עדכונים המתייחסים לקבצים/משחקים חסרים יוסרו אוטומטית",
|
||||||
"it_IT": "DLC/Aggiornamenti relativi a file/gioco mancanti verranno disabilitati automaticamente",
|
"it_IT": "DLC/Aggiornamenti relativi a file/gioco mancanti verranno disabilitati automaticamente",
|
||||||
"ja_JP": "DLC/欠損ファイル/ゲームを参照するアップデートは自動的にアンロードされます",
|
"ja_JP": "DLC/欠損ファイル/ゲームを参照するアップデートは自動的にアンロードされます",
|
||||||
|
|
@ -4800,7 +4808,7 @@
|
||||||
"el_GR": "Backend Ήχου:",
|
"el_GR": "Backend Ήχου:",
|
||||||
"en_US": "Audio Backend:",
|
"en_US": "Audio Backend:",
|
||||||
"es_ES": "Motor de Audio:",
|
"es_ES": "Motor de Audio:",
|
||||||
"fr_FR": "Bibliothèque Audio :",
|
"fr_FR": "Moteur Audio :",
|
||||||
"he_IL": "אחראי שמע:",
|
"he_IL": "אחראי שמע:",
|
||||||
"it_IT": "Backend audio:",
|
"it_IT": "Backend audio:",
|
||||||
"ja_JP": "音声バックエンド:",
|
"ja_JP": "音声バックエンド:",
|
||||||
|
|
@ -4917,6 +4925,31 @@
|
||||||
"zh_TW": null
|
"zh_TW": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "SettingsTabSystemAudioBackendAudioToolbox",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": null,
|
||||||
|
"de_DE": null,
|
||||||
|
"el_GR": null,
|
||||||
|
"en_US": "Apple Audio (macOS only)",
|
||||||
|
"es_ES": null,
|
||||||
|
"fr_FR": null,
|
||||||
|
"he_IL": null,
|
||||||
|
"it_IT": null,
|
||||||
|
"ja_JP": null,
|
||||||
|
"ko_KR": null,
|
||||||
|
"no_NO": null,
|
||||||
|
"pl_PL": null,
|
||||||
|
"pt_BR": null,
|
||||||
|
"ru_RU": null,
|
||||||
|
"sv_SE": null,
|
||||||
|
"th_TH": null,
|
||||||
|
"tr_TR": null,
|
||||||
|
"uk_UA": null,
|
||||||
|
"zh_CN": null,
|
||||||
|
"zh_TW": null
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "SettingsTabSystemHacks",
|
"ID": "SettingsTabSystemHacks",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
|
@ -5700,7 +5733,7 @@
|
||||||
"el_GR": "Έκταση σε όλο το παράθυρο",
|
"el_GR": "Έκταση σε όλο το παράθυρο",
|
||||||
"en_US": "Stretch to Fit Window",
|
"en_US": "Stretch to Fit Window",
|
||||||
"es_ES": "Estirar a la Ventana",
|
"es_ES": "Estirar a la Ventana",
|
||||||
"fr_FR": "Ajuster à la Taille de la Fenêtre",
|
"fr_FR": "Adapter à la Taille de la Fenêtre",
|
||||||
"he_IL": "מתח לגודל חלון",
|
"he_IL": "מתח לגודל חלון",
|
||||||
"it_IT": "Adatta alla finestra",
|
"it_IT": "Adatta alla finestra",
|
||||||
"ja_JP": "ウインドウサイズに合わせる",
|
"ja_JP": "ウインドウサイズに合わせる",
|
||||||
|
|
@ -5750,7 +5783,7 @@
|
||||||
"el_GR": "Τοποθεσία Shaders Γραφικών:",
|
"el_GR": "Τοποθεσία Shaders Γραφικών:",
|
||||||
"en_US": "Graphics Shader Dump Path:",
|
"en_US": "Graphics Shader Dump Path:",
|
||||||
"es_ES": "Directorio de Volcado de Sombreadores:",
|
"es_ES": "Directorio de Volcado de Sombreadores:",
|
||||||
"fr_FR": "Chemin du Dossier de Copie des Shaders :",
|
"fr_FR": "Chemin du dump des shaders graphiques :",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "Percorso di dump degli shader:",
|
"it_IT": "Percorso di dump degli shader:",
|
||||||
"ja_JP": "グラフィックス シェーダー ダンプパス:",
|
"ja_JP": "グラフィックス シェーダー ダンプパス:",
|
||||||
|
|
@ -11292,6 +11325,31 @@
|
||||||
"zh_TW": "刪除"
|
"zh_TW": "刪除"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "UserProfilesSave",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "Speichern",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Save",
|
||||||
|
"es_ES": "Guardar",
|
||||||
|
"fr_FR": "Sauvegarder",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "Spara",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": "儲存"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "UserProfilesClose",
|
"ID": "UserProfilesClose",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
|
@ -13975,7 +14033,7 @@
|
||||||
"el_GR": "\n\nΑυτό θα αντικαταστήσει την τρέχουσα έκδοση συστήματος {0}.",
|
"el_GR": "\n\nΑυτό θα αντικαταστήσει την τρέχουσα έκδοση συστήματος {0}.",
|
||||||
"en_US": "\n\nThis will replace the current system version {0}.",
|
"en_US": "\n\nThis will replace the current system version {0}.",
|
||||||
"es_ES": "\n\nEsto reemplazará la versión de sistema actual, {0}.",
|
"es_ES": "\n\nEsto reemplazará la versión de sistema actual, {0}.",
|
||||||
"fr_FR": "\n\nCela remplacera la version actuelle du système {0}.",
|
"fr_FR": "\n\nCeci remplacera la version actuelle du système {0}.",
|
||||||
"he_IL": "\n\nזה יחליף את גרסת המערכת הנוכחית {0}.",
|
"he_IL": "\n\nזה יחליף את גרסת המערכת הנוכחית {0}.",
|
||||||
"it_IT": "\n\nQuesta sostituirà l'attuale versione del sistema ({0}).",
|
"it_IT": "\n\nQuesta sostituirà l'attuale versione del sistema ({0}).",
|
||||||
"ja_JP": "\n\n現在のシステムバージョン {0} を置き換えます.",
|
"ja_JP": "\n\n現在のシステムバージョン {0} を置き換えます.",
|
||||||
|
|
@ -14150,7 +14208,7 @@
|
||||||
"el_GR": "",
|
"el_GR": "",
|
||||||
"en_US": "\n\nThis may replace some of the current installed Keys.",
|
"en_US": "\n\nThis may replace some of the current installed Keys.",
|
||||||
"es_ES": "\n\nEsto puede reemplazar algunas de las Keys actualmente instaladas.",
|
"es_ES": "\n\nEsto puede reemplazar algunas de las Keys actualmente instaladas.",
|
||||||
"fr_FR": "\n\nCela peut remplacer certaines des Clés actuellement installées.",
|
"fr_FR": "\n\nCeci peut remplacer certaines des Clés actuellement installées.",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "\n\nAlcune delle chiavi già installate potrebbero essere sovrascritte.",
|
"it_IT": "\n\nAlcune delle chiavi già installate potrebbero essere sovrascritte.",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
|
|
@ -15000,7 +15058,7 @@
|
||||||
"el_GR": "Πολυνηματική Επεξεργασία Γραφικών:",
|
"el_GR": "Πολυνηματική Επεξεργασία Γραφικών:",
|
||||||
"en_US": "Graphics Backend Multithreading:",
|
"en_US": "Graphics Backend Multithreading:",
|
||||||
"es_ES": "Multihilado del Motor Gráfico:",
|
"es_ES": "Multihilado del Motor Gráfico:",
|
||||||
"fr_FR": "Interface graphique multithread :",
|
"fr_FR": "Interface Graphique Multithread :",
|
||||||
"he_IL": "אחראי גרפיקה רב-תהליכי:",
|
"he_IL": "אחראי גרפיקה רב-תהליכי:",
|
||||||
"it_IT": "Multithreading del backend grafico:",
|
"it_IT": "Multithreading del backend grafico:",
|
||||||
"ja_JP": "グラフィックスバックエンドのマルチスレッド実行:",
|
"ja_JP": "グラフィックスバックエンドのマルチスレッド実行:",
|
||||||
|
|
@ -15293,28 +15351,28 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ID": "AboutGitLabUrlTooltipMessage",
|
"ID": "AboutForgejoUrlTooltipMessage",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
"ar_SA": "انقر لفتح صفحة ريوجينكس في غيت هاب في متصفحك الافتراضي.",
|
"ar_SA": "انقر لفتح صفحة ريوجينكس في غيت هاب في متصفحك الافتراضي.",
|
||||||
"de_DE": "Klicke hier, um die Ryujinx GitLab Seite im Standardbrowser zu öffnen.",
|
"de_DE": "Klicke hier, um die Ryujinx Forgejo Seite im Standardbrowser zu öffnen.",
|
||||||
"el_GR": "Κάντε κλικ για να ανοίξετε τη σελίδα Ryujinx GitLab στο προεπιλεγμένο πρόγραμμα περιήγησης.",
|
"el_GR": "Κάντε κλικ για να ανοίξετε τη σελίδα Ryujinx Forgejo στο προεπιλεγμένο πρόγραμμα περιήγησης.",
|
||||||
"en_US": "Click to open the Ryujinx GitLab page in your default browser.",
|
"en_US": "Click to open the Ryujinx Forgejo page in your default browser.",
|
||||||
"es_ES": "Haz clic para abrir el GitLab de Ryujinx en tu navegador predeterminado.",
|
"es_ES": "Haz clic para abrir el Forgejo de Ryujinx en tu navegador predeterminado.",
|
||||||
"fr_FR": "Cliquez pour ouvrir la page GitLab de Ryujinx dans votre navigateur par défaut.",
|
"fr_FR": "Cliquez pour ouvrir la page Forgejo de Ryujinx dans votre navigateur par défaut.",
|
||||||
"he_IL": "לחץ כדי לפתוח את דף הגיטהב של ריוג'ינקס בדפדפן ברירת המחדל שלך.",
|
"he_IL": "לחץ כדי לפתוח את דף הגיטהב של ריוג'ינקס בדפדפן ברירת המחדל שלך.",
|
||||||
"it_IT": "Clicca per aprire la pagina GitLab di Ryujinx nel tuo browser predefinito.",
|
"it_IT": "Clicca per aprire la pagina Forgejo di Ryujinx nel tuo browser predefinito.",
|
||||||
"ja_JP": "クリックするとデフォルトのブラウザで Ryujinx の GitLab ページを開きます.",
|
"ja_JP": "クリックするとデフォルトのブラウザで Ryujinx の Forgejo ページを開きます.",
|
||||||
"ko_KR": "클릭하면 기본 브라우저에서 Ryujinx GitLab 페이지가 열립니다.",
|
"ko_KR": "클릭하면 기본 브라우저에서 Ryujinx Forgejo 페이지가 열립니다.",
|
||||||
"no_NO": "Klikk for å åpne Ryujinx GitLab siden i din standardnettleser.",
|
"no_NO": "Klikk for å åpne Ryujinx Forgejo siden i din standardnettleser.",
|
||||||
"pl_PL": "Kliknij, aby otworzyć stronę GitLab Ryujinx w domyślnej przeglądarce.",
|
"pl_PL": "Kliknij, aby otworzyć stronę Forgejo Ryujinx w domyślnej przeglądarce.",
|
||||||
"pt_BR": "Clique para abrir a página do GitLab do Ryujinx no seu navegador padrão.",
|
"pt_BR": "Clique para abrir a página do Forgejo do Ryujinx no seu navegador padrão.",
|
||||||
"ru_RU": "Нажмите, чтобы открыть страницу Ryujinx на GitLab",
|
"ru_RU": "Нажмите, чтобы открыть страницу Ryujinx на Forgejo",
|
||||||
"sv_SE": "Klicka för att öppna Ryujinx GitLab-sida i din webbläsare.",
|
"sv_SE": "Klicka för att öppna Ryujinx Forgejo-sida i din webbläsare.",
|
||||||
"th_TH": "คลิกเพื่อเปิดหน้า GitLab ของ Ryujinx บนเบราว์เซอร์เริ่มต้นของคุณ",
|
"th_TH": "คลิกเพื่อเปิดหน้า Forgejo ของ Ryujinx บนเบราว์เซอร์เริ่มต้นของคุณ",
|
||||||
"tr_TR": "Ryujinx'in GitLab sayfasını varsayılan tarayıcınızda açmak için tıklayın.",
|
"tr_TR": "Ryujinx'in Forgejo sayfasını varsayılan tarayıcınızda açmak için tıklayın.",
|
||||||
"uk_UA": "Натисніть, щоб відкрити сторінку GitLab Ryujinx у браузері.",
|
"uk_UA": "Натисніть, щоб відкрити сторінку Forgejo Ryujinx у браузері.",
|
||||||
"zh_CN": "在浏览器中打开 Ryujinx 的 GitLab 代码库。",
|
"zh_CN": "在浏览器中打开 Ryujinx 的 Forgejo 代码库。",
|
||||||
"zh_TW": "在預設瀏覽器中開啟 Ryujinx 的 GitLab 網頁。"
|
"zh_TW": "在預設瀏覽器中開啟 Ryujinx 的 Forgejo 網頁。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -15373,23 +15431,23 @@
|
||||||
"ar_SA": "",
|
"ar_SA": "",
|
||||||
"de_DE": "",
|
"de_DE": "",
|
||||||
"el_GR": "",
|
"el_GR": "",
|
||||||
"en_US": "Ryujinx is an emulator for the Nintendo Switch™ 1.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our GitLab or Discord.",
|
"en_US": "Ryujinx is an emulator for the Nintendo Switch™ 1.\nGet all the latest news in our Discord.\nDevelopers interested in contributing can find out more on our Forgejo or Discord.",
|
||||||
"es_ES": "Ryujinx es un emulador para Nintendo Switch™ 1.\nObtén todas las novedades en nuestro Discord.\nLos desarrolladores interesados en contribuir pueden obtener más información en nuestro GitLab o Discord.",
|
"es_ES": "Ryujinx es un emulador para Nintendo Switch™ 1.\nObtén todas las novedades en nuestro Discord.\nLos desarrolladores interesados en contribuir pueden obtener más información en nuestro Forgejo o Discord.",
|
||||||
"fr_FR": "Ryujinx est un émulateur pour la Nintendo Switch™ 1.\nObtenez les dernières nouvelles sur notre Discord.\nLes développeurs souhaitant contribuer peuvent en savoir plus sur notre GitLab ou Discord.",
|
"fr_FR": "Ryujinx est un émulateur pour la Nintendo Switch™ 1.\nObtenez les dernières nouvelles sur notre Discord.\nLes développeurs souhaitant contribuer peuvent en savoir plus sur notre Forgejo ou Discord.",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "Ryujinx è un emulatore della console Nintendo Switch™ 1.\nRimani aggiornato sulle ultime novità nel nostro server Discord.\nGli sviluppatori interessati a contribuire possono trovare maggiori informazioni su Discord o sulla nostra pagina GitLab.",
|
"it_IT": "Ryujinx è un emulatore della console Nintendo Switch™ 1.\nRimani aggiornato sulle ultime novità nel nostro server Discord.\nGli sviluppatori interessati a contribuire possono trovare maggiori informazioni su Discord o sulla nostra pagina Forgejo.",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "Ryujinx는 Nintendo Switch™ 1용 에뮬레이터입니다.\n모든 최신 소식을 Discord에서 확인하세요.\n기여에 관심이 있는 개발자는 GitLab 또는 Discord에서 자세한 내용을 확인할 수 있습니다.",
|
"ko_KR": "Ryujinx는 Nintendo Switch™ 1용 에뮬레이터입니다.\n모든 최신 소식을 Discord에서 확인하세요.\n기여에 관심이 있는 개발자는 Forgejo 또는 Discord에서 자세한 내용을 확인할 수 있습니다.",
|
||||||
"no_NO": "Ryujinx er en emulator for Nintendo Switch™ 1\nVennligst støtt oss på Patreon.\nFå alle de siste nyhetene på vår Twitter eller Discord.\nUtviklere som er interessert i å bidra kan finne ut mer på GitLab eller Discord.",
|
"no_NO": "Ryujinx er en emulator for Nintendo Switch™ 1\nVennligst støtt oss på Patreon.\nFå alle de siste nyhetene på vår Twitter eller Discord.\nUtviklere som er interessert i å bidra kan finne ut mer på Forgejo eller Discord.",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Ryujinx é um emulador de Nintendo Switch™ 1.\nReceba todas as últimas notícias em nosso Discord.\nDesenvolvedores interessados em contribuir podem descobrir mais em nosso GitLab ou Discord.",
|
"pt_BR": "Ryujinx é um emulador de Nintendo Switch™ 1.\nReceba todas as últimas notícias em nosso Discord.\nDesenvolvedores interessados em contribuir podem descobrir mais em nosso Forgejo ou Discord.",
|
||||||
"ru_RU": "Ryujinx - это эмулятор для Nintendo Switch™ 1.\nПолучайте все последние новости разработки в нашем Discord.\nРазработчики, заинтересованные в участии, могут узнать больше на нашем GitLab или Discord.",
|
"ru_RU": "Ryujinx - это эмулятор для Nintendo Switch™ 1.\nПолучайте все последние новости разработки в нашем Discord.\nРазработчики, заинтересованные в участии, могут узнать больше на нашем Forgejo или Discord.",
|
||||||
"sv_SE": "Ryujinx är en emulator för Nintendo Switch™ 1.\nFå de senaste nyheterna via vår Discord.\nUtvecklare som är intresserade att bidra kan hitta mer info på vår GitLab eller Discord.",
|
"sv_SE": "Ryujinx är en emulator för Nintendo Switch™ 1.\nFå de senaste nyheterna via vår Discord.\nUtvecklare som är intresserade att bidra kan hitta mer info på vår Forgejo eller Discord.",
|
||||||
"th_TH": "Ryujinx เป็นโปรแกรมจำลองสำหรับเครื่อง Nintendo Switch™ 1\nติดตามข่าวสารล่าสุดได้ที่ Discord ของเรา\nนักพัฒนาที่สนใจร่วมพัฒนา สามารถดูข้อมูลเพิ่มเติมได้ทาง GitLab หรือ Discord",
|
"th_TH": "Ryujinx เป็นโปรแกรมจำลองสำหรับเครื่อง Nintendo Switch™ 1\nติดตามข่าวสารล่าสุดได้ที่ Discord ของเรา\nนักพัฒนาที่สนใจร่วมพัฒนา สามารถดูข้อมูลเพิ่มเติมได้ทาง Forgejo หรือ Discord",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Ryujinx — це емулятор для Nintendo Switch™ 1.\nОстанні новини можна отримати в нашому Discord.\nРозробники, що бажають долучитись до розробки та зробити свій внесок, можуть отримати більше інформації на нашому GitLab або в Discord.",
|
"uk_UA": "Ryujinx — це емулятор для Nintendo Switch™ 1.\nОстанні новини можна отримати в нашому Discord.\nРозробники, що бажають долучитись до розробки та зробити свій внесок, можуть отримати більше інформації на нашому Forgejo або в Discord.",
|
||||||
"zh_CN": "Ryujinx 是一个 Nintendo Switch™ 1 模拟器。\n有兴趣做出贡献的开发者可以在我们的 GitLab 或 Discord 上了解更多信息。\n",
|
"zh_CN": "Ryujinx 是一个 Nintendo Switch™ 1 模拟器。\n有兴趣做出贡献的开发者可以在我们的 Forgejo 或 Discord 上了解更多信息。\n",
|
||||||
"zh_TW": "Ryujinx 是一款 Nintendo Switch™ 1 模擬器。\n關注我們的 Discord 取得所有最新消息。\n對於有興趣貢獻的開發者,可以在我們的 GitLab 或 Discord 上了解更多資訊。"
|
"zh_TW": "Ryujinx 是一款 Nintendo Switch™ 1 模擬器。\n關注我們的 Discord 取得所有最新消息。\n對於有興趣貢獻的開發者,可以在我們的 Forgejo 或 Discord 上了解更多資訊。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -16598,9 +16656,9 @@
|
||||||
"ar_SA": "",
|
"ar_SA": "",
|
||||||
"de_DE": "Diese Option überspringt den Dialog 'Benutzerprofile verwalten' während des Spiels und verwendet ein voreingestelltes Profil.\n\nDie Profilumschaltung finden Sie unter 'Einstellungen' - 'Benutzerprofile verwalten'. Wählen Sie das gewünschte Profil aus, bevor Sie das Spiel laden.",
|
"de_DE": "Diese Option überspringt den Dialog 'Benutzerprofile verwalten' während des Spiels und verwendet ein voreingestelltes Profil.\n\nDie Profilumschaltung finden Sie unter 'Einstellungen' - 'Benutzerprofile verwalten'. Wählen Sie das gewünschte Profil aus, bevor Sie das Spiel laden.",
|
||||||
"el_GR": "Αυτή η επιλογή παρακάμπτει το παράθυρο διαλόγου 'Διαχειριστής Προφίλ Χρήστη' κατά τη διάρκεια του παιχνιδιού, χρησιμοποιώντας ένα προεπιλεγμένο προφίλ.\n\nΗ εναλλαγή προφίλ βρίσκεται στις 'Ρυθμίσεις' - 'Διαχειριστής Προφίλ Χρήστη'. Επιλέξτε το επιθυμητό προφίλ πριν φορτώσετε το παιχνίδι.",
|
"el_GR": "Αυτή η επιλογή παρακάμπτει το παράθυρο διαλόγου 'Διαχειριστής Προφίλ Χρήστη' κατά τη διάρκεια του παιχνιδιού, χρησιμοποιώντας ένα προεπιλεγμένο προφίλ.\n\nΗ εναλλαγή προφίλ βρίσκεται στις 'Ρυθμίσεις' - 'Διαχειριστής Προφίλ Χρήστη'. Επιλέξτε το επιθυμητό προφίλ πριν φορτώσετε το παιχνίδι.",
|
||||||
"en_US": "This option skips the 'Manage User Profiles' dialog during gameplay, using a pre-selected profile.\n\nProfile switching is found in 'Settings' - 'Manager User Profiles'. Select the desired profile before loading the game.",
|
"en_US": "This option skips the 'Manage User Profiles' dialog during gameplay, using a pre-selected profile.\n\nProfile switching is found in 'Options' - 'User Profiles'. Select the desired profile before loading the game.",
|
||||||
"es_ES": "Esta opción omite el diálogo de 'Gestionar perfiles de usuario' durante el juego, utilizando un perfil preseleccionado.\n\nEl cambio de perfil se encuentra en 'Configuración' - 'Gestionar perfiles de usuario'. Seleccione el perfil deseado antes de cargar el juego.",
|
"es_ES": "Esta opción omite el diálogo de 'Gestionar perfiles de usuario' durante el juego, utilizando un perfil preseleccionado.\n\nEl cambio de perfil se encuentra en 'Opciones' - 'Perfiles de Usuario'. Seleccione el perfil deseado antes de cargar el juego.",
|
||||||
"fr_FR": "Cette option permet d'éviter le dialogue du 'Gérer les profils d'utilisateurs' pendant le jeu, en utilisant un profil pré-sélectionné.\n\nLa sélection du profil se trouve dans 'Paramètres' - 'Gérer les profils d'utilisateurs'. Sélectionnez le profil souhaité avant de lancer le jeu.",
|
"fr_FR": "Cette option permet de passer le dialogue 'Gérer les profils d'utilisateurs' pendant le jeu, en utilisant un profil pré-sélectionné.\n\nLa sélection du profil se trouve dans 'Options' - 'Profils d'Utilisateurs'. Sélectionnez le profil souhaité avant de lancer le jeu.",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "Questa opzione salta la finestra di dialogo 'Gestisci i profili utente' durante il gioco, utilizzando un profilo pre-selezionato.\n\nIl cambio del profilo si trova in 'Impostazioni' - 'Gestisci i profili utente'. Seleziona il profilo desiderato prima di caricare il gioco.",
|
"it_IT": "Questa opzione salta la finestra di dialogo 'Gestisci i profili utente' durante il gioco, utilizzando un profilo pre-selezionato.\n\nIl cambio del profilo si trova in 'Impostazioni' - 'Gestisci i profili utente'. Seleziona il profilo desiderato prima di caricare il gioco.",
|
||||||
"ja_JP": "このオプションは、ゲームプレイ中に「ユーザプロファイルを管理」ダイアログをスキップし、事前に選択されたプロファイルを使用します。\n\nプロファイルの切り替えは、「設定」-「ユーザプロファイルを管理」で見つけることができます。ゲームのロード前に目的のプロファイルをを選択してください。",
|
"ja_JP": "このオプションは、ゲームプレイ中に「ユーザプロファイルを管理」ダイアログをスキップし、事前に選択されたプロファイルを使用します。\n\nプロファイルの切り替えは、「設定」-「ユーザプロファイルを管理」で見つけることができます。ゲームのロード前に目的のプロファイルをを選択してください。",
|
||||||
|
|
@ -16625,7 +16683,7 @@
|
||||||
"el_GR": "Ενεργοποίηση Πολυνηματικής Επεξεργασίας Γραφικών",
|
"el_GR": "Ενεργοποίηση Πολυνηματικής Επεξεργασίας Γραφικών",
|
||||||
"en_US": "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.",
|
"en_US": "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.",
|
||||||
"es_ES": "Ejecuta los comandos del motor gráfico en un segundo hilo. Acelera la compilación de sombreadores, reduce los tirones, y mejora el rendimiento en controladores gráficos que no realicen su propio procesamiento con múltiples hilos. Rendimiento ligeramente superior en controladores gráficos que soporten múltiples hilos.\n\nSelecciona \"Auto\" si no sabes qué hacer.",
|
"es_ES": "Ejecuta los comandos del motor gráfico en un segundo hilo. Acelera la compilación de sombreadores, reduce los tirones, y mejora el rendimiento en controladores gráficos que no realicen su propio procesamiento con múltiples hilos. Rendimiento ligeramente superior en controladores gráficos que soporten múltiples hilos.\n\nSelecciona \"Auto\" si no sabes qué hacer.",
|
||||||
"fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore la performance sur les pilotes GPU sans support natif du multithreading. Offre une légère amélioration des performances sur les pilotes multithreadés.\n\nRéglez sur AUTO si vous n’êtes pas sûr.",
|
"fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore la performance sur les pilotes GPU sans support natif du multithreading. Offre une légère amélioration des performances sur les pilotes multithreadés.\n\nSéléctionnez Auto si vous n’êtes pas sûr.",
|
||||||
"he_IL": "מריץ פקודות גראפיקה בתהליך שני נפרד.\n\nמאיץ עיבוד הצללות, מפחית תקיעות ומשפר ביצועים של דרייבר כרטיסי מסך אשר לא תומכים בהרצה רב-תהליכית.\n\nמוטב להשאיר על אוטומטי אם לא בטוחים.",
|
"he_IL": "מריץ פקודות גראפיקה בתהליך שני נפרד.\n\nמאיץ עיבוד הצללות, מפחית תקיעות ומשפר ביצועים של דרייבר כרטיסי מסך אשר לא תומכים בהרצה רב-תהליכית.\n\nמוטב להשאיר על אוטומטי אם לא בטוחים.",
|
||||||
"it_IT": "Esegue i comandi del backend grafico su un secondo thread.\n\nVelocizza la compilazione degli shader, riduce lo stuttering e migliora le prestazioni sui driver grafici senza il supporto integrato al multithreading. Migliora leggermente le prestazioni sui driver che supportano il multithreading.\n\nNel dubbio, imposta l'opzione su Automatico.",
|
"it_IT": "Esegue i comandi del backend grafico su un secondo thread.\n\nVelocizza la compilazione degli shader, riduce lo stuttering e migliora le prestazioni sui driver grafici senza il supporto integrato al multithreading. Migliora leggermente le prestazioni sui driver che supportano il multithreading.\n\nNel dubbio, imposta l'opzione su Automatico.",
|
||||||
"ja_JP": "グラフィックスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
|
"ja_JP": "グラフィックスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
|
||||||
|
|
@ -16650,7 +16708,7 @@
|
||||||
"el_GR": "Εκτελεί εντολές γραφικών σε ένα δεύτερο νήμα. Επιτρέπει την πολυνηματική μεταγλώττιση Shader σε χρόνο εκτέλεσης, μειώνει το τρεμόπαιγμα και βελτιώνει την απόδοση των προγραμμάτων οδήγησης χωρίς τη δική τους υποστήριξη πολλαπλών νημάτων. Ποικίλες κορυφαίες επιδόσεις σε προγράμματα οδήγησης με multithreading. Μπορεί να χρειαστεί επανεκκίνηση του Ryujinx για να απενεργοποιήσετε σωστά την ενσωματωμένη λειτουργία πολλαπλών νημάτων του προγράμματος οδήγησης ή ίσως χρειαστεί να το κάνετε χειροκίνητα για να έχετε την καλύτερη απόδοση.",
|
"el_GR": "Εκτελεί εντολές γραφικών σε ένα δεύτερο νήμα. Επιτρέπει την πολυνηματική μεταγλώττιση Shader σε χρόνο εκτέλεσης, μειώνει το τρεμόπαιγμα και βελτιώνει την απόδοση των προγραμμάτων οδήγησης χωρίς τη δική τους υποστήριξη πολλαπλών νημάτων. Ποικίλες κορυφαίες επιδόσεις σε προγράμματα οδήγησης με multithreading. Μπορεί να χρειαστεί επανεκκίνηση του Ryujinx για να απενεργοποιήσετε σωστά την ενσωματωμένη λειτουργία πολλαπλών νημάτων του προγράμματος οδήγησης ή ίσως χρειαστεί να το κάνετε χειροκίνητα για να έχετε την καλύτερη απόδοση.",
|
||||||
"en_US": "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.",
|
"en_US": "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.",
|
||||||
"es_ES": "Ejecuta los comandos del motor gráfico en un segundo hilo. Acelera la compilación de sombreadores, reduce los tirones, y mejora el rendimiento en controladores gráficos que no realicen su propio procesamiento con múltiples hilos. Rendimiento ligeramente superior en controladores gráficos que soporten múltiples hilos.\n\nSelecciona \"Auto\" si no sabes qué hacer.",
|
"es_ES": "Ejecuta los comandos del motor gráfico en un segundo hilo. Acelera la compilación de sombreadores, reduce los tirones, y mejora el rendimiento en controladores gráficos que no realicen su propio procesamiento con múltiples hilos. Rendimiento ligeramente superior en controladores gráficos que soporten múltiples hilos.\n\nSelecciona \"Auto\" si no sabes qué hacer.",
|
||||||
"fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore la performance sur les pilotes GPU sans support de multithreading. Légère augementation des performances sur les pilotes avec multithreading intégrer.\n\nRéglez sur Auto en cas d'incertitude.",
|
"fr_FR": "Exécute des commandes du backend graphiques sur un second thread.\n\nAccélère la compilation des shaders, réduit les crashs et les lags, améliore la performance sur les pilotes GPU sans support de multithreading. Légère augementation des performances sur les pilotes avec multithreading intégrer.\n\nSéléctionnez Auto en cas d'incertitude.",
|
||||||
"he_IL": "מריץ פקודות גראפיקה בתהליך שני נפרד.\n\nמאיץ עיבוד הצללות, מפחית תקיעות ומשפר ביצועים של דרייבר כרטיסי מסך אשר לא תומכים בהרצה רב-תהליכית.\n\nמוטב להשאיר על אוטומטי אם לא בטוחים.",
|
"he_IL": "מריץ פקודות גראפיקה בתהליך שני נפרד.\n\nמאיץ עיבוד הצללות, מפחית תקיעות ומשפר ביצועים של דרייבר כרטיסי מסך אשר לא תומכים בהרצה רב-תהליכית.\n\nמוטב להשאיר על אוטומטי אם לא בטוחים.",
|
||||||
"it_IT": "Esegue i comandi del backend grafico su un secondo thread.\n\nVelocizza la compilazione degli shader, riduce lo stuttering e migliora le prestazioni sui driver grafici senza il supporto integrato al multithreading. Migliora leggermente le prestazioni sui driver che supportano il multithreading.\n\nNel dubbio, imposta l'opzione su Automatico.",
|
"it_IT": "Esegue i comandi del backend grafico su un secondo thread.\n\nVelocizza la compilazione degli shader, riduce lo stuttering e migliora le prestazioni sui driver grafici senza il supporto integrato al multithreading. Migliora leggermente le prestazioni sui driver che supportano il multithreading.\n\nNel dubbio, imposta l'opzione su Automatico.",
|
||||||
"ja_JP": "グラフィックスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
|
"ja_JP": "グラフィックスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
|
||||||
|
|
@ -16750,7 +16808,7 @@
|
||||||
"el_GR": "",
|
"el_GR": "",
|
||||||
"en_US": "Level of Anisotropic Filtering. Set to Auto to use the value requested by the game.",
|
"en_US": "Level of Anisotropic Filtering. Set to Auto to use the value requested by the game.",
|
||||||
"es_ES": "Nivel de filtrado anisotrópico. Setear en Auto para utilizar el valor solicitado por el juego.",
|
"es_ES": "Nivel de filtrado anisotrópico. Setear en Auto para utilizar el valor solicitado por el juego.",
|
||||||
"fr_FR": "Niveau de filtrage anisotrope. Réglez sur Auto pour utiliser la valeur demandée par le jeu.",
|
"fr_FR": "Niveau de filtrage anisotrope. Séléctionnez Auto pour utiliser la valeur demandée par le jeu.",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "Livello del filtro anisotropico. Imposta su Automatico per usare il valore richiesto dal gioco.",
|
"it_IT": "Livello del filtro anisotropico. Imposta su Automatico per usare il valore richiesto dal gioco.",
|
||||||
"ja_JP": "異方性フィルタリングのレベルです. ゲームが要求する値を使用する場合は「自動」を設定してください.",
|
"ja_JP": "異方性フィルタリングのレベルです. ゲームが要求する値を使用する場合は「自動」を設定してください.",
|
||||||
|
|
@ -16775,7 +16833,7 @@
|
||||||
"el_GR": "",
|
"el_GR": "",
|
||||||
"en_US": "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.",
|
"en_US": "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.",
|
||||||
"es_ES": "Relación de aspecto aplicada a la ventana del renderizador.\n\nSolamente modificar esto si estás utilizando un mod de relación de aspecto para su juego, en cualquier otro caso los gráficos se estirarán.\n\nDejar en 16:9 si no sabe que hacer.",
|
"es_ES": "Relación de aspecto aplicada a la ventana del renderizador.\n\nSolamente modificar esto si estás utilizando un mod de relación de aspecto para su juego, en cualquier otro caso los gráficos se estirarán.\n\nDejar en 16:9 si no sabe que hacer.",
|
||||||
"fr_FR": "Format\u00A0d'affichage appliqué à la fenêtre du moteur de rendu.\n\nChangez cela uniquement si vous utilisez un mod changeant le format\u00A0d'affichage pour votre jeu, sinon les graphismes seront étirés.\n\nLaissez sur 16:9 si vous n'êtes pas sûr.",
|
"fr_FR": "Format\u00A0d'affichage appliqué à la fenêtre du moteur de rendu.\n\nChangez celui-ci uniquement si vous utilisez un mod changeant le format\u00A0d'affichage pour votre jeu, sinon les graphismes seront étirés.\n\nLaissez sur 16:9 si vous n'êtes pas sûr.",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "Proporzioni dello schermo applicate alla finestra di renderizzazione.\n\nCambialo solo se stai usando una mod di proporzioni per il tuo gioco, altrimenti la grafica verrà allungata.\n\nLasciare il 16:9 se incerto.",
|
"it_IT": "Proporzioni dello schermo applicate alla finestra di renderizzazione.\n\nCambialo solo se stai usando una mod di proporzioni per il tuo gioco, altrimenti la grafica verrà allungata.\n\nLasciare il 16:9 se incerto.",
|
||||||
"ja_JP": "レンダリングウインドウに適用するアスペクト比です.\n\nゲームにアスペクト比を変更する mod を使用している場合のみ変更してください.\n\nわからない場合は16:9のままにしておいてください.\n",
|
"ja_JP": "レンダリングウインドウに適用するアスペクト比です.\n\nゲームにアスペクト比を変更する mod を使用している場合のみ変更してください.\n\nわからない場合は16:9のままにしておいてください.\n",
|
||||||
|
|
@ -21997,23 +22055,23 @@
|
||||||
"Translations": {
|
"Translations": {
|
||||||
"ar_SA": "اختر فلتر التكبير الذي سيتم تطبيقه عند استخدام مقياس الدقة.\n\nيعمل Bilinear بشكل جيد مع الألعاب ثلاثية الأبعاد وهو خيار افتراضي آمن.\n\nيوصى باستخدام Nearest لألعاب البكسل الفنية.\n\nFSR 1.0 هو مجرد مرشح توضيحي، ولا ينصح باستخدامه مع FXAA أو SMAA.\n\nيمكن تغيير هذا الخيار أثناء تشغيل اللعبة بالنقر فوق \"تطبيق\" أدناه؛ يمكنك ببساطة تحريك نافذة الإعدادات جانبا والتجربة حتى تجد المظهر المفضل للعبة.\n\nاتركه على Bilinear إذا لم تكن متأكدا.",
|
"ar_SA": "اختر فلتر التكبير الذي سيتم تطبيقه عند استخدام مقياس الدقة.\n\nيعمل Bilinear بشكل جيد مع الألعاب ثلاثية الأبعاد وهو خيار افتراضي آمن.\n\nيوصى باستخدام Nearest لألعاب البكسل الفنية.\n\nFSR 1.0 هو مجرد مرشح توضيحي، ولا ينصح باستخدامه مع FXAA أو SMAA.\n\nيمكن تغيير هذا الخيار أثناء تشغيل اللعبة بالنقر فوق \"تطبيق\" أدناه؛ يمكنك ببساطة تحريك نافذة الإعدادات جانبا والتجربة حتى تجد المظهر المفضل للعبة.\n\nاتركه على Bilinear إذا لم تكن متأكدا.",
|
||||||
"de_DE": "Wählen Sie den Skalierungsfilter, der bei der Auflösungsskalierung angewendet werden soll.\n\nBilinear eignet sich gut für 3D-Spiele und ist eine sichere Standardoption.\n\nNearest wird für Pixel-Art-Spiele empfohlen.\n\nFSR 1.0 ist lediglich ein Schärfungsfilter und wird nicht für die Verwendung mit FXAA oder SMAA empfohlen.\n\nDiese Option kann geändert werden, während ein Spiel läuft, indem Sie unten auf \"Anwenden\" klicken; Sie können das Einstellungsfenster einfach zur Seite schieben und experimentieren, bis Sie Ihr bevorzugtes Aussehen für ein Spiel gefunden haben.\n\nBleiben Sie auf BILINEAR, wenn Sie unsicher sind.",
|
"de_DE": "Wählen Sie den Skalierungsfilter, der bei der Auflösungsskalierung angewendet werden soll.\n\nBilinear eignet sich gut für 3D-Spiele und ist eine sichere Standardoption.\n\nNearest wird für Pixel-Art-Spiele empfohlen.\n\nFSR 1.0 ist lediglich ein Schärfungsfilter und wird nicht für die Verwendung mit FXAA oder SMAA empfohlen.\n\nDiese Option kann geändert werden, während ein Spiel läuft, indem Sie unten auf \"Anwenden\" klicken; Sie können das Einstellungsfenster einfach zur Seite schieben und experimentieren, bis Sie Ihr bevorzugtes Aussehen für ein Spiel gefunden haben.\n\nBleiben Sie auf BILINEAR, wenn Sie unsicher sind.",
|
||||||
"el_GR": "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.",
|
"el_GR": "",
|
||||||
"en_US": "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\nArea scaling is recommended when downscaling resolutions that are larger than the output window. It can be used to achieve a supersampled anti-aliasing effect when downscaling by more than 2x.\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.",
|
"en_US": "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\nArea scaling is recommended when downscaling resolutions that are larger than the output window. It can be used to achieve a supersampled anti-aliasing effect when downscaling by more than 2x.\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.",
|
||||||
"es_ES": "Elija el filtro de escala que se aplicará al utilizar la escala de resolución.\n\nBilinear funciona bien para juegos 3D y es una opción predeterminada segura.\n\nSe recomienda el bilinear para juegos de pixel art.\n\nFSR 1.0 es simplemente un filtro de afilado, no se recomienda su uso con FXAA o SMAA.\n\nEsta opción se puede cambiar mientras se ejecuta un juego haciendo clic en \"Aplicar\" a continuación; simplemente puedes mover la ventana de configuración a un lado y experimentar hasta que encuentres tu estilo preferido para un juego.\n\nDéjelo en BILINEAR si no está seguro.",
|
"es_ES": "Elija el filtro de escala que se aplicará al utilizar la escala de resolución.\n\nBilinear funciona bien para juegos 3D y es una opción predeterminada segura.\n\nSe recomienda el bilinear para juegos de pixel art.\n\nFSR 1.0 es simplemente un filtro de afilado, no se recomienda su uso con FXAA o SMAA.\n\nEsta opción se puede cambiar mientras se ejecuta un juego haciendo clic en \"Aplicar\" a continuación; simplemente puedes mover la ventana de configuración a un lado y experimentar hasta que encuentres tu estilo preferido para un juego.\n\nDéjelo en BILINEAR si no está seguro.",
|
||||||
"fr_FR": "Choisis le filtre de mise à l'échelle qui sera appliqué lors de l'utilisation de la mise à l'échelle de la résolution.\n\nLe filtre bilinéaire fonctionne bien pour les jeux en 3D et constitue une option par défaut sûre.\n\nLe filtre le plus proche est recommandé pour les jeux de pixel art.\n\nFSR 1.0 est simplement un filtre de netteté, non recommandé pour une utilisation avec FXAA ou SMAA.\n\nCette option peut être modifiée pendant qu'un jeu est en cours d'exécution en cliquant sur \"Appliquer\" ci-dessous ; vous pouvez simplement déplacer la fenêtre des paramètres de côté et expérimenter jusqu'à ce que vous trouviez l'aspect souhaité pour un jeu.\n\nLaissez sur BILINÉAIRE si vous n'êtes pas sûr.",
|
"fr_FR": "Choisit le filtre de mise à l'échelle qui sera appliqué lors de l'utilisation de la mise à l'échelle de la résolution.\n\nLe filtre bilinéaire fonctionne le mieux pour les jeux en 3D et constitue une option par défaut fiable.\n\nLe filtre le plus proche est recommandé pour les jeux de pixel art.\n\nFSR 1.0 est simplement un filtre de netteté, non recommandé pour une utilisation avec FXAA ou SMAA.\n\nCette option peut être modifiée pendant qu'un jeu est en cours d'exécution en cliquant sur \"Appliquer\" ci-dessous ; vous pouvez simplement déplacer la fenêtre des paramètres de côté et expérimenter jusqu'à ce que vous trouviez l'aspect souhaité pour un jeu.\n\nLaissez sur BILINÉAIRE si vous n'êtes pas sûr.",
|
||||||
"he_IL": "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.",
|
"he_IL": "",
|
||||||
"it_IT": "Scegli il filtro di scaling che verrà applicato quando si utilizza lo scaling della risoluzione.\n\nBilineare funziona bene per i giochi 3D ed è un'opzione predefinita affidabile.\n\nNearest è consigliato per i giochi in pixel art.\n\nFSR 1.0 è solo un filtro di nitidezza, sconsigliato per l'uso con FXAA o SMAA.\n\nLo scaling ad area è consigliato quando si riducono delle risoluzioni che sono più grandi della finestra di output. Può essere usato per ottenere un effetto di anti-aliasing supercampionato quando si riduce di più di 2x.\n\nQuesta opzione può essere modificata mentre un gioco è in esecuzione facendo clic su \"Applica\" qui sotto; puoi semplicemente spostare la finestra delle impostazioni da parte e sperimentare fino a quando non trovi il tuo look preferito per un gioco.\n\nNel dubbio, lascia su Bilineare.",
|
"it_IT": "Scegli il filtro di scaling che verrà applicato quando si utilizza lo scaling della risoluzione.\n\nBilineare funziona bene per i giochi 3D ed è un'opzione predefinita affidabile.\n\nNearest è consigliato per i giochi in pixel art.\n\nFSR 1.0 è solo un filtro di nitidezza, sconsigliato per l'uso con FXAA o SMAA.\n\nLo scaling ad area è consigliato quando si riducono delle risoluzioni che sono più grandi della finestra di output. Può essere usato per ottenere un effetto di anti-aliasing supercampionato quando si riduce di più di 2x.\n\nQuesta opzione può essere modificata mentre un gioco è in esecuzione facendo clic su \"Applica\" qui sotto; puoi semplicemente spostare la finestra delle impostazioni da parte e sperimentare fino a quando non trovi il tuo look preferito per un gioco.\n\nNel dubbio, lascia su Bilineare.",
|
||||||
"ja_JP": "解像度変更時に適用されるスケーリングフィルタを選択します.\n\nBilinearは3Dゲームに適しており, 安全なデフォルトオプションです.\n\nピクセルアートゲームにはNearestを推奨します.\n\nFSR 1.0は単なるシャープニングフィルタであり, FXAAやSMAAとの併用は推奨されません.\n\nこのオプションは, ゲーム実行中に下の「適用」をクリックすることで変更できます. 設定ウィンドウを脇に移動し, ゲームが好みの表示になるように試してみてください.\n\n不明な場合はBilinearのままにしておいてください.",
|
"ja_JP": "解像度変更時に適用されるスケーリングフィルタを選択します.\n\nBilinearは3Dゲームに適しており, 安全なデフォルトオプションです.\n\nピクセルアートゲームにはNearestを推奨します.\n\nFSR 1.0は単なるシャープニングフィルタであり, FXAAやSMAAとの併用は推奨されません.\n\nこのオプションは, ゲーム実行中に下の「適用」をクリックすることで変更できます. 設定ウィンドウを脇に移動し, ゲームが好みの表示になるように試してみてください.\n\n不明な場合はBilinearのままにしておいてください.",
|
||||||
"ko_KR": "해상도 스케일을 사용할 때 적용될 스케일링 필터를 선택합니다.\n\n쌍선형은 3D 게임에 적합하며 안전한 기본 옵션입니다.\n\nNearest는 픽셀 아트 게임에 권장됩니다.\n\nFSR 1.0은 단순히 선명도 필터일 뿐이며 FXAA 또는 SMAA와 함께 사용하는 것은 권장되지 않습니다.\n\nArea 스케일링은 출력 창보다 큰 해상도를 다운스케일링할 때 권장됩니다. 2배 이상 다운스케일링할 때 슈퍼샘플링된 앤티앨리어싱 효과를 얻는 데 사용할 수 있습니다.\n\n이 옵션은 아래의 \"적용\"을 클릭하여 게임을 실행하는 동안 변경할 수 있습니다. 설정 창을 옆으로 옮겨 원하는 게임 모양을 찾을 때까지 실험하면 됩니다.\n\n모르면 쌍선형을 그대로 두세요.",
|
"ko_KR": "해상도 스케일을 사용할 때 적용될 스케일링 필터를 선택합니다.\n\n쌍선형은 3D 게임에 적합하며 안전한 기본 옵션입니다.\n\nNearest는 픽셀 아트 게임에 권장됩니다.\n\nFSR 1.0은 단순히 선명도 필터일 뿐이며 FXAA 또는 SMAA와 함께 사용하는 것은 권장되지 않습니다.\n\nArea 스케일링은 출력 창보다 큰 해상도를 다운스케일링할 때 권장됩니다. 2배 이상 다운스케일링할 때 슈퍼샘플링된 앤티앨리어싱 효과를 얻는 데 사용할 수 있습니다.\n\n이 옵션은 아래의 \"적용\"을 클릭하여 게임을 실행하는 동안 변경할 수 있습니다. 설정 창을 옆으로 옮겨 원하는 게임 모양을 찾을 때까지 실험하면 됩니다.\n\n모르면 쌍선형을 그대로 두세요.",
|
||||||
"no_NO": "Velg det skaleringsfilteret som skal brukes når du bruker oppløsningsskalaen.\n\nBilinear fungerer godt for 3D-spill og er et trygt standardalternativ.\n\nNærmeste anbefales for pixel kunst-spill.\n\nFSR 1.0 er bare et skarpere filter, ikke anbefalt for bruk med FXAA eller SMAA.\n\nOmrådeskalering anbefales når nedskalering er større enn utgangsvinduet. Den kan brukes til å oppnå en superprøvetaket anti-aliasingseffekt når en nedskalerer med mer enn 2x.\n\nDette valget kan endres mens et spill kjører ved å klikke \"Apply\" nedenfor; du kan bare flytte innstillingsvinduet til du finner det foretrukne utseendet til et spill.\n\nLa være på BILINEAR hvis usikker.",
|
"no_NO": "Velg det skaleringsfilteret som skal brukes når du bruker oppløsningsskalaen.\n\nBilinear fungerer godt for 3D-spill og er et trygt standardalternativ.\n\nNærmeste anbefales for pixel kunst-spill.\n\nFSR 1.0 er bare et skarpere filter, ikke anbefalt for bruk med FXAA eller SMAA.\n\nOmrådeskalering anbefales når nedskalering er større enn utgangsvinduet. Den kan brukes til å oppnå en superprøvetaket anti-aliasingseffekt når en nedskalerer med mer enn 2x.\n\nDette valget kan endres mens et spill kjører ved å klikke \"Apply\" nedenfor; du kan bare flytte innstillingsvinduet til du finner det foretrukne utseendet til et spill.\n\nLa være på BILINEAR hvis usikker.",
|
||||||
"pl_PL": "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.",
|
"pl_PL": "",
|
||||||
"pt_BR": "Escolha o filtro de escala que será aplicado ao usar a escala de resolução.\n\nBilinear funciona bem para jogos 3D e é uma opção padrão segura.\n\nNearest é recomendado para jogos em pixel art.\n\nFSR 1.0 é apenas um filtro de nitidez, não recomendado para uso com FXAA ou SMAA.\n\nEssa opção pode ser alterada enquanto o jogo está em execução, clicando em \"Aplicar\" abaixo; basta mover a janela de configurações para o lado e experimentar até encontrar o visual preferido para o jogo.\n\nMantenha em BILINEAR se estiver em dúvida.",
|
"pt_BR": "Escolha o filtro de escala que será aplicado ao usar a escala de resolução.\n\nBilinear funciona bem para jogos 3D e é uma opção padrão segura.\n\nNearest é recomendado para jogos em pixel art.\n\nFSR 1.0 é apenas um filtro de nitidez, não recomendado para uso com FXAA ou SMAA.\n\nEssa opção pode ser alterada enquanto o jogo está em execução, clicando em \"Aplicar\" abaixo; basta mover a janela de configurações para o lado e experimentar até encontrar o visual preferido para o jogo.\n\nMantenha em BILINEAR se estiver em dúvida.",
|
||||||
"ru_RU": "Фильтрация текстур, которая будет применяться при масштабировании.\n\nБилинейная хорошо работает для 3D-игр и является настройкой по умолчанию.\n\nСтупенчатая рекомендуется для пиксельных игр.\n\nFSR это фильтр резкости, который не рекомендуется использовать с FXAA или SMAA.\n\nЗональная рекомендуется в случае использования разрешения больше разрешения окна. Можно использовать для достижения эффекта суперсемплига (SSAA) при даунскейле более чем в 2 раза.\n\nЭта опция может быть изменена во время игры по нажатию кнопки «Применить» ниже; \nВы можете просто переместить окно настроек в сторону и поэкспериментировать, пока не подберете подходящие настройки для конкретной игры.\n\nРекомендуется использовать «Билинейная».",
|
"ru_RU": "Фильтрация текстур, которая будет применяться при масштабировании.\n\nБилинейная хорошо работает для 3D-игр и является настройкой по умолчанию.\n\nСтупенчатая рекомендуется для пиксельных игр.\n\nFSR 1.0 это фильтр резкости, который не рекомендуется использовать с FXAA или SMAA.\n\nЗональная рекомендуется в случае использования разрешения больше разрешения окна. Можно использовать для достижения эффекта суперсемплига (SSAA) при даунскейле более чем в 2 раза.\n\nЭта опция может быть изменена во время игры по нажатию кнопки «Применить» ниже; \nВы можете просто переместить окно настроек в сторону и поэкспериментировать, пока не подберете подходящие настройки для конкретной игры.\n\nРекомендуется использовать «Билинейная».",
|
||||||
"sv_SE": "Välj det skalfilter som ska tillämpas vid användning av upplösningsskala.\n\nBilinjär fungerar bra för 3D-spel och är ett säkert standardalternativ.\n\nNärmast rekommenderas för pixel art-spel.\n\nFSR 1.0 är bara ett skarpningsfilter, rekommenderas inte för FXAA eller SMAA.\n\nOmrådesskalning rekommenderas vid nedskalning av upplösning som är större än utdatafönstret. Det kan användas för att uppnå en supersamplad anti-alias-effekt vid nedskalning med mer än 2x.\n\nDetta alternativ kan ändras medan ett spel körs genom att klicka på \"Tillämpa\" nedan. du kan helt enkelt flytta inställningsfönstret åt sidan och experimentera tills du hittar ditt föredragna utseende för ett spel.\n\nLämna som BILINJÄR om du är osäker.",
|
"sv_SE": "Välj det skalfilter som ska tillämpas vid användning av upplösningsskala.\n\nBilinjär fungerar bra för 3D-spel och är ett säkert standardalternativ.\n\nNärmast rekommenderas för pixel art-spel.\n\nFSR 1.0 är bara ett skarpningsfilter, rekommenderas inte för FXAA eller SMAA.\n\nOmrådesskalning rekommenderas vid nedskalning av upplösning som är större än utdatafönstret. Det kan användas för att uppnå en supersamplad anti-alias-effekt vid nedskalning med mer än 2x.\n\nDetta alternativ kan ändras medan ett spel körs genom att klicka på \"Tillämpa\" nedan. du kan helt enkelt flytta inställningsfönstret åt sidan och experimentera tills du hittar ditt föredragna utseende för ett spel.\n\nLämna som BILINJÄR om du är osäker.",
|
||||||
"th_TH": "เลือกตัวกรองสเกลที่จะใช้เมื่อใช้สเกลความละเอียด\n\nBilinear ทำงานได้ดีกับเกม 3D และเป็นตัวเลือกเริ่มต้นที่ปลอดภัย\n\nแนะนำให้ใช้เกมภาพพิกเซลที่ใกล้เคียงที่สุด\n\nFSR 1.0 เป็นเพียงตัวกรองความคมชัด ไม่แนะนำให้ใช้กับ FXAA หรือ SMAA\n\nตัวเลือกนี้สามารถเปลี่ยนแปลงได้ในขณะที่เกมกำลังทำงานอยู่โดยคลิก \"นำไปใช้\" ด้านล่าง คุณสามารถย้ายหน้าต่างการตั้งค่าไปด้านข้างและทดลองจนกว่าคุณจะพบรูปลักษณ์ที่คุณต้องการสำหรับเกม",
|
"th_TH": "เลือกตัวกรองสเกลที่จะใช้เมื่อใช้สเกลความละเอียด\n\nBilinear ทำงานได้ดีกับเกม 3D และเป็นตัวเลือกเริ่มต้นที่ปลอดภัย\n\nแนะนำให้ใช้เกมภาพพิกเซลที่ใกล้เคียงที่สุด\n\nFSR 1.0 เป็นเพียงตัวกรองความคมชัด ไม่แนะนำให้ใช้กับ FXAA หรือ SMAA\n\nตัวเลือกนี้สามารถเปลี่ยนแปลงได้ในขณะที่เกมกำลังทำงานอยู่โดยคลิก \"นำไปใช้\" ด้านล่าง คุณสามารถย้ายหน้าต่างการตั้งค่าไปด้านข้างและทดลองจนกว่าคุณจะพบรูปลักษณ์ที่คุณต้องการสำหรับเกม",
|
||||||
"tr_TR": "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.",
|
"tr_TR": "",
|
||||||
"uk_UA": "Оберіть фільтр масштабування, який буде використовуватися при збільшенні роздільної здатності.\n\n\"Білінійний (Bilinear)\" добре виглядає в 3D іграх та є хорошим варіантом за замовчуванням.\n\n\"Найближчий (Nearest)\" рекомендується для піксельних ігор.\n\n\"FSR 1.0\" - фільтр різкості. Не варто використовувати разом з FXAA або SMAA.\n\nЦю опцію можна міняти під час гри натисканням \"Застосувати\" в цьому вікні; щоб знайти найкращий варіант, просто відсуньте вікно налаштувань і поекспериментуйте.\n\nЗалиште \"Білінійний\", якщо не впевнені.",
|
"uk_UA": "Оберіть фільтр масштабування, який буде використовуватися при збільшенні роздільної здатності.\n\n\"Білінійний (Bilinear)\" добре виглядає в 3D іграх та є хорошим варіантом за замовчуванням.\n\n\"Найближчий (Nearest)\" рекомендується для піксельних ігор.\n\n\"FSR 1.0\" - фільтр різкості. Не варто використовувати разом з FXAA або SMAA.\n\nЦю опцію можна міняти під час гри натисканням \"Застосувати\" в цьому вікні; щоб знайти найкращий варіант, просто відсуньте вікно налаштувань і поекспериментуйте.\n\nЗалиште \"Білінійний\", якщо не впевнені.",
|
||||||
"zh_CN": "选择在分辨率缩放时将使用的缩放过滤器。\n\nBilinear(双线性过滤)对于3D游戏效果较好,是一个安全的默认选项。\n\nNearest(最近邻过滤)推荐用于像素艺术游戏。\n\nFSR(超级分辨率锐画)只是一个锐化过滤器,不推荐与 FXAA 或 SMAA 抗锯齿一起使用。\n\nArea(局部过滤),当渲染分辨率大于窗口实际分辨率,推荐该选项。该选项在渲染比例大于2.0的情况下,可以实现超采样的效果。\n\n在游戏运行时,通过点击下面的“应用”按钮可以使设置生效;你可以将设置窗口移开,并试验找到您喜欢的游戏画面效果。\n\n如果不确定,请保持为“Bilinear(双线性过滤)”。",
|
"zh_CN": "选择在分辨率缩放时将使用的缩放过滤器。\n\nBilinear(双线性过滤)对于3D游戏效果较好,是一个安全的默认选项。\n\nNearest(最近邻过滤)推荐用于像素艺术游戏。\n\nFSR 1.0(超级分辨率锐画)只是一个锐化过滤器,不推荐与 FXAA 或 SMAA 抗锯齿一起使用。\n\nArea(局部过滤),当渲染分辨率大于窗口实际分辨率,推荐该选项。该选项在渲染比例大于2.0的情况下,可以实现超采样的效果。\n\n在游戏运行时,通过点击下面的“应用”按钮可以使设置生效;你可以将设置窗口移开,并试验找到您喜欢的游戏画面效果。\n\n如果不确定,请保持为“Bilinear(双线性过滤)”。",
|
||||||
"zh_TW": "選擇使用解析度縮放時套用的縮放過濾器。\n\n雙線性 (Bilinear) 濾鏡適用於 3D 遊戲,是一個安全的預設選項。\n\n建議像素美術遊戲使用近鄰性 (Nearest) 濾鏡。\n\nFSR 1.0 只是一個銳化濾鏡,不建議與 FXAA 或 SMAA 一起使用。\n\n此選項可在遊戲執行時透過點選下方的「套用」進行變更;您只需將設定視窗移到一旁,然後進行試驗,直到找到您喜歡的遊戲效果。\n\n如果不確定,請保持雙線性 (Bilinear) 狀態。"
|
"zh_TW": "選擇使用解析度縮放時套用的縮放過濾器。\n\n雙線性 (Bilinear) 濾鏡適用於 3D 遊戲,是一個安全的預設選項。\n\n建議像素美術遊戲使用近鄰性 (Nearest) 濾鏡。\n\nFSR 1.0 只是一個銳化濾鏡,不建議與 FXAA 或 SMAA 一起使用。\n\n此選項可在遊戲執行時透過點選下方的「套用」進行變更;您只需將設定視窗移到一旁,然後進行試驗,直到找到您喜歡的遊戲效果。\n\n如果不確定,請保持雙線性 (Bilinear) 狀態。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -22073,7 +22131,7 @@
|
||||||
"ar_SA": null,
|
"ar_SA": null,
|
||||||
"de_DE": null,
|
"de_DE": null,
|
||||||
"el_GR": null,
|
"el_GR": null,
|
||||||
"en_US": "FSR",
|
"en_US": "FSR 1.0",
|
||||||
"es_ES": null,
|
"es_ES": null,
|
||||||
"fr_FR": null,
|
"fr_FR": null,
|
||||||
"he_IL": null,
|
"he_IL": null,
|
||||||
|
|
@ -22150,7 +22208,7 @@
|
||||||
"el_GR": "",
|
"el_GR": "",
|
||||||
"en_US": "Set FSR 1.0 sharpening level. Higher is sharper.",
|
"en_US": "Set FSR 1.0 sharpening level. Higher is sharper.",
|
||||||
"es_ES": "Ajuste el nivel de nitidez FSR 1.0. Mayor es más nítido.",
|
"es_ES": "Ajuste el nivel de nitidez FSR 1.0. Mayor es más nítido.",
|
||||||
"fr_FR": "Définis le niveau de netteté FSR 1.0. Plus la valeur est élevée, plus l'image est nette.",
|
"fr_FR": "Définit le niveau de netteté FSR 1.0. Plus la valeur est élevée, plus l'image est nette.",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "Imposta il livello di nitidezza di FSR 1.0. Valori più alti comportano una maggiore nitidezza.",
|
"it_IT": "Imposta il livello di nitidezza di FSR 1.0. Valori più alti comportano una maggiore nitidezza.",
|
||||||
"ja_JP": "FSR 1.0のシャープ化レベルを設定します. 高い値ほどシャープになります.",
|
"ja_JP": "FSR 1.0のシャープ化レベルを設定します. 高い値ほどシャープになります.",
|
||||||
|
|
@ -22520,26 +22578,26 @@
|
||||||
{
|
{
|
||||||
"ID": "MultiplayerModeTooltip",
|
"ID": "MultiplayerModeTooltip",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
"ar_SA": "تغيير وضع LDN متعدد اللاعبين.\n\nسوف يقوم LdnMitm بتعديل وظيفة اللعب المحلية/اللاسلكية المحلية في الألعاب لتعمل كما لو كانت شبكة LAN، مما يسمح باتصالات الشبكة المحلية نفسها مع محاكيات ريوجينكس الأخرى وأجهزة نينتندو سويتش المخترقة التي تم تثبيت وحدة ldn_mitm عليها.\n\nيتطلب وضع اللاعبين المتعددين أن يكون جميع اللاعبين على نفس إصدار اللعبة (على سبيل المثال، يتعذر على الإصدار 13.0.1 من سوبر سماش برذرز ألتميت الاتصال بالإصدار 13.0.0).\n\nاتركه معطلا إذا لم تكن متأكدا.",
|
"ar_SA": "تغيير وضع LDN متعدد اللاعبين.\n\nسوف يقوم ldn_mitm بتعديل وظيفة اللعب المحلية/اللاسلكية المحلية في الألعاب لتعمل كما لو كانت شبكة LAN، مما يسمح باتصالات الشبكة المحلية نفسها مع محاكيات ريوجينكس الأخرى وأجهزة نينتندو سويتش المخترقة التي تم تثبيت وحدة ldn_mitm عليها.\n\nيتطلب وضع اللاعبين المتعددين أن يكون جميع اللاعبين على نفس إصدار اللعبة (على سبيل المثال، يتعذر على الإصدار 13.0.1 من سوبر سماش برذرز ألتميت الاتصال بالإصدار 13.0.0).\n\nاتركه معطلا إذا لم تكن متأكدا.",
|
||||||
"de_DE": "Ändert den LDN-Mehrspielermodus.\n\nLdnMitm ändert die lokale drahtlose/lokale Spielfunktionalität in Spielen so, dass sie wie ein LAN funktioniert und lokale, netzwerkgleiche Verbindungen mit anderen Ryujinx-Instanzen und gehackten Nintendo Switch-Konsolen ermöglicht, auf denen das ldn_mitm-Modul installiert ist.\n\nMultiplayer erfordert, dass alle Spieler die gleiche Spielversion verwenden (d.h. Super Smash Bros. Ultimate v13.0.1 kann sich nicht mit v13.0.0 verbinden).\n\nIm Zweifelsfall auf DISABLED lassen.",
|
"de_DE": "Ändert den LDN-Mehrspielermodus.\n\nldn_mitm ändert die lokale drahtlose/lokale Spielfunktionalität in Spielen so, dass sie wie ein LAN funktioniert und lokale, netzwerkgleiche Verbindungen mit anderen Ryujinx-Instanzen und gehackten Nintendo Switch-Konsolen ermöglicht, auf denen das ldn_mitm-Modul installiert ist.\n\nMultiplayer erfordert, dass alle Spieler die gleiche Spielversion verwenden (d.h. Super Smash Bros. Ultimate v13.0.1 kann sich nicht mit v13.0.0 verbinden).\n\nIm Zweifelsfall auf DISABLED lassen.",
|
||||||
"el_GR": "",
|
"el_GR": "",
|
||||||
"en_US": "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.",
|
"en_US": "Change LDN multiplayer mode.\n\nldn_mitm 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.",
|
||||||
"es_ES": "Cambiar modo LDN multijugador.\n\nLdnMitm modificará la funcionalidad local de juego inalámbrico para funcionar como si fuera LAN, permitiendo locales conexiones de la misma red con otras instancias de Ryujinx y consolas hackeadas de Nintendo Switch que tienen instalado el módulo ldn_mitm.\n\nMultijugador requiere que todos los jugadores estén en la misma versión del juego (por ejemplo, Super Smash Bros. Ultimate v13.0.1 no se puede conectar a v13.0.0).\n\nDejar DESACTIVADO si no está seguro.",
|
"es_ES": "Cambiar modo LDN multijugador.\n\nldn_mitm modificará la funcionalidad local de juego inalámbrico para funcionar como si fuera LAN, permitiendo locales conexiones de la misma red con otras instancias de Ryujinx y consolas hackeadas de Nintendo Switch que tienen instalado el módulo ldn_mitm.\n\nMultijugador requiere que todos los jugadores estén en la misma versión del juego (por ejemplo, Super Smash Bros. Ultimate v13.0.1 no se puede conectar a v13.0.0).\n\nDejar DESACTIVADO si no está seguro.",
|
||||||
"fr_FR": "Change le mode multijoueur LDN.\n\nLdnMitm modifiera la fonctionnalité de jeu sans fil local/jeu local dans les jeux pour fonctionner comme s'il s'agissait d'un LAN, permettant des connexions locales sur le même réseau avec d'autres instances de Ryujinx et des consoles Nintendo Switch piratées ayant le module ldn_mitm installé.\n\nLe multijoueur nécessite que tous les joueurs soient sur la même version du jeu (par exemple, Super Smash Bros. Ultimate v13.0.1 ne peut pas se connecter à v13.0.0).\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.",
|
"fr_FR": "Change le mode multijoueur LDN.\n\nldn_mitm modifiera la fonctionnalité de jeu sans fil local/jeu local dans les jeux pour fonctionner comme s'il s'agissait d'un LAN, permettant des connexions locales sur le même réseau avec d'autres instances de Ryujinx et des consoles Nintendo Switch piratées ayant le module ldn_mitm installé.\n\nLe multijoueur nécessite que tous les joueurs soient sur la même version du jeu (par exemple, Super Smash Bros. Ultimate v13.0.1 ne peut pas se connecter à v13.0.0).\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "Cambia la modalità multigiocatore LDN.\n\nLdnMitm modificherà la funzionalità locale wireless/local play nei giochi per funzionare come se fosse in modalità LAN, consentendo connessioni locali sulla stessa rete con altre istanze di Ryujinx e console Nintendo Switch modificate che hanno il modulo ldn_mitm installato.\n\nLa modalità multigiocatore richiede che tutti i giocatori usino la stessa versione del gioco (es. Super Smash Bros. Ultimate v13.0.1 non può connettersi con la v13.0.0).\n\nNel dubbio, lascia l'opzione su Disabilitato.",
|
"it_IT": "Cambia la modalità multigiocatore LDN.\n\nldn_mitm modificherà la funzionalità locale wireless/local play nei giochi per funzionare come se fosse in modalità LAN, consentendo connessioni locali sulla stessa rete con altre istanze di Ryujinx e console Nintendo Switch modificate che hanno il modulo ldn_mitm installato.\n\nLa modalità multigiocatore richiede che tutti i giocatori usino la stessa versione del gioco (es. Super Smash Bros. Ultimate v13.0.1 non può connettersi con la v13.0.0).\n\nNel dubbio, lascia l'opzione su Disabilitato.",
|
||||||
"ja_JP": "LDNマルチプレイヤーモードを変更します.\n\nldn_mitmモジュールがインストールされた, 他のRyujinxインスタンスや,ハックされたNintendo Switchコンソールとのローカル/同一ネットワーク接続を可能にします.\n\nマルチプレイでは, すべてのプレイヤーが同じゲームバージョンである必要があります(例:Super Smash Bros. Ultimate v13.0.1はv13.0.0に接続できません).\n\n不明な場合は「無効」のままにしてください.",
|
"ja_JP": "LDNマルチプレイヤーモードを変更します.\n\nldn_mitmモジュールがインストールされた, 他のRyujinxインスタンスや,ハックされたNintendo Switchコンソールとのローカル/同一ネットワーク接続を可能にします.\n\nマルチプレイでは, すべてのプレイヤーが同じゲームバージョンである必要があります(例:Super Smash Bros. Ultimate v13.0.1はv13.0.0に接続できません).\n\n不明な場合は「無効」のままにしてください.",
|
||||||
"ko_KR": "LDN 멀티플레이어 모드를 변경합니다.\n\nLdnMitm은 게임의 로컬 무선/로컬 플레이 기능을 LAN처럼 작동하도록 수정하여 다른 Ryujinx 인스턴스나 ldn_mitm 모듈이 설치된 해킹된 Nintendo Switch 콘솔과 로컬, 동일 네트워크 연결이 가능합니다.\n\n멀티플레이어는 모든 플레이어가 동일한 게임 버전을 사용해야 합니다(예 : 슈퍼 스매시브라더스 얼티밋 v13.0.1은 v13.0.0에 연결할 수 없음).\n\n모르면 비활성화 상태로 두세요.",
|
"ko_KR": "LDN 멀티플레이어 모드를 변경합니다.\n\nldn_mitm은 게임의 로컬 무선/로컬 플레이 기능을 LAN처럼 작동하도록 수정하여 다른 Ryujinx 인스턴스나 ldn_mitm 모듈이 설치된 해킹된 Nintendo Switch 콘솔과 로컬, 동일 네트워크 연결이 가능합니다.\n\n멀티플레이어는 모든 플레이어가 동일한 게임 버전을 사용해야 합니다(예 : 슈퍼 스매시브라더스 얼티밋 v13.0.1은 v13.0.0에 연결할 수 없음).\n\n모르면 비활성화 상태로 두세요.",
|
||||||
"no_NO": "Endre LDN flerspillermodus.\n\nLdnMitm vil endre lokal trådløst/lokal spillfunksjonalitet i spill som skal fungere som om den var LAN, noe som tillater lokal, samme nettverk forbindelser med andre Ryujinx instanser og hacket Nintendo Switch konsoller som har installert ldn_mitm-modulen.\n\nFlerspiller krever at alle spillerne er på samme versjon (dvs. Super Smash Bros. Ultimat v13.0.1 kan ikke koble til v13.0.0).\n\nForlat DEAKTIVERT hvis usikker.",
|
"no_NO": "Endre LDN flerspillermodus.\n\nldn_mitm vil endre lokal trådløst/lokal spillfunksjonalitet i spill som skal fungere som om den var LAN, noe som tillater lokal, samme nettverk forbindelser med andre Ryujinx instanser og hacket Nintendo Switch konsoller som har installert ldn_mitm-modulen.\n\nFlerspiller krever at alle spillerne er på samme versjon (dvs. Super Smash Bros. Ultimat v13.0.1 kan ikke koble til v13.0.0).\n\nForlat DEAKTIVERT hvis usikker.",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Alterar o modo multiplayer LDN.\n\nLdnMitm modificará a funcionalidade de jogo sem fio/local nos jogos para funcionar como se fosse LAN, permitindo conexões locais, na mesma rede, com outras instâncias do Ryujinx e consoles Nintendo Switch hackeados que possuem o módulo ldn_mitm instalado.\n\nO multiplayer exige que todos os jogadores estejam na mesma versão do jogo (ex.: Super Smash Bros. Ultimate v13.0.1 não consegue se conectar à v13.0.0).\n\nDeixe DESATIVADO se estiver em dúvida.",
|
"pt_BR": "Alterar o modo multiplayer LDN.\n\nldn_mitm modificará a funcionalidade de jogo sem fio/local nos jogos para funcionar como se fosse LAN, permitindo conexões locais, na mesma rede, com outras instâncias do Ryujinx e consoles Nintendo Switch hackeados que possuem o módulo ldn_mitm instalado.\n\nO multiplayer exige que todos os jogadores estejam na mesma versão do jogo (ex.: Super Smash Bros. Ultimate v13.0.1 não consegue se conectar à v13.0.0).\n\nDeixe DESATIVADO se estiver em dúvida.",
|
||||||
"ru_RU": "Меняет многопользовательский режим LDN.\n\nLdnMitm модифицирует функциональность локальной беспроводной игры на одном устройстве в играх, позволяя играть с другими пользователями Ryujinx или взломанными консолями Nintendo Switch с установленным модулем ldn_mitm, находящимися в одной локальной сети друг с другом.\n\nМногопользовательская игра требует наличия у всех игроков одной и той же версии игры (т.е. Super Smash Bros. Ultimate v13.0.1 не может подключиться к v13.0.0).\n\nРекомендуется оставить выключенным.",
|
"ru_RU": "Меняет многопользовательский режим LDN.\n\nldn_mitm модифицирует функциональность локальной беспроводной игры на одном устройстве в играх, позволяя играть с другими пользователями Ryujinx или взломанными консолями Nintendo Switch с установленным модулем ldn_mitm, находящимися в одной локальной сети друг с другом.\n\nМногопользовательская игра требует наличия у всех игроков одной и той же версии игры (т.е. Super Smash Bros. Ultimate v13.0.1 не может подключиться к v13.0.0).\n\nРекомендуется оставить выключенным.",
|
||||||
"sv_SE": "Ändra LDN-flerspelarläge\n\nLdnMitm kommer att ändra lokal funktionalitet för trådlös/lokalt spel att fungera som om det vore ett LAN, vilket ger stöd för anslutningar med local och same-network med andra Ryujinx-instanser och hackade Nintendo Switch-konsoller som har modulen ldn_mitm installerad.\n\nFlerspelare kräver att alla spelare har samma spelversion (t.ex. Super Smash Bros. Ultimate v13.0.1 kan inte ansluta till v13.0.0).\n\nLämna INAKTIVERAD om du är osäker.",
|
"sv_SE": "Ändra LDN-flerspelarläge\n\nldn_mitm kommer att ändra lokal funktionalitet för trådlös/lokalt spel att fungera som om det vore ett LAN, vilket ger stöd för anslutningar med local och same-network med andra Ryujinx-instanser och hackade Nintendo Switch-konsoller som har modulen ldn_mitm installerad.\n\nFlerspelare kräver att alla spelare har samma spelversion (t.ex. Super Smash Bros. Ultimate v13.0.1 kan inte ansluta till v13.0.0).\n\nLämna INAKTIVERAD om du är osäker.",
|
||||||
"th_TH": "เปลี่ยนโหมดผู้เล่นหลายคนของ LDN\n\nLdnMitm จะปรับเปลี่ยนฟังก์ชันการเล่นแบบไร้สาย/ภายใน จะให้เกมทำงานเหมือนกับว่าเป็น LAN ช่วยให้สามารถเชื่อมต่อภายในเครือข่ายเดียวกันกับอินสแตนซ์ Ryujinx อื่น ๆ และคอนโซล Nintendo Switch ที่ถูกแฮ็กซึ่งมีโมดูล ldn_mitm ติดตั้งอยู่\n\nผู้เล่นหลายคนต้องการให้ผู้เล่นทุกคนอยู่ในเกมเวอร์ชันเดียวกัน (เช่น Super Smash Bros. Ultimate v13.0.1 ไม่สามารถเชื่อมต่อกับ v13.0.0)\n\nปล่อยให้ปิดการใช้งานหากไม่แน่ใจ",
|
"th_TH": "เปลี่ยนโหมดผู้เล่นหลายคนของ LDN\n\nldn_mitm จะปรับเปลี่ยนฟังก์ชันการเล่นแบบไร้สาย/ภายใน จะให้เกมทำงานเหมือนกับว่าเป็น LAN ช่วยให้สามารถเชื่อมต่อภายในเครือข่ายเดียวกันกับอินสแตนซ์ Ryujinx อื่น ๆ และคอนโซล Nintendo Switch ที่ถูกแฮ็กซึ่งมีโมดูล ldn_mitm ติดตั้งอยู่\n\nผู้เล่นหลายคนต้องการให้ผู้เล่นทุกคนอยู่ในเกมเวอร์ชันเดียวกัน (เช่น Super Smash Bros. Ultimate v13.0.1 ไม่สามารถเชื่อมต่อกับ v13.0.0)\n\nปล่อยให้ปิดการใช้งานหากไม่แน่ใจ",
|
||||||
"tr_TR": "",
|
"tr_TR": "",
|
||||||
"uk_UA": "Змінити LDN мультиплеєру.\n\nLdnMitm змінить функціонал бездротової/локальної гри в іграх, щоб вони працювали так, ніби це LAN, що дозволяє локальні підключення в тій самій мережі з іншими екземплярами Ryujinx та хакнутими консолями Nintendo Switch, які мають встановлений модуль ldn_mitm.\n\nМультиплеєр вимагає, щоб усі гравці були на одній і тій же версії гри (наприклад Super Smash Bros. Ultimate v13.0.1 не зможе під'єднатися до v13.0.0).\n\nЗалиште на \"Вимкнено\", якщо не впевнені.",
|
"uk_UA": "Змінити LDN мультиплеєру.\n\nldn_mitm змінить функціонал бездротової/локальної гри в іграх, щоб вони працювали так, ніби це LAN, що дозволяє локальні підключення в тій самій мережі з іншими екземплярами Ryujinx та хакнутими консолями Nintendo Switch, які мають встановлений модуль ldn_mitm.\n\nМультиплеєр вимагає, щоб усі гравці були на одній і тій же версії гри (наприклад Super Smash Bros. Ultimate v13.0.1 не зможе під'єднатися до v13.0.0).\n\nЗалиште на \"Вимкнено\", якщо не впевнені.",
|
||||||
"zh_CN": "修改 LDN 多人联机游玩模式。\n\nldn_mitm 联机插件将修改游戏中的本地无线和本地游玩功能,使其表现得像局域网一样,允许和其他安装了 ldn_mitm 插件的 Ryujinx 模拟器和破解的任天堂 Switch 主机在同一网络下进行本地连接,实现多人联机游玩。\n\n多人联机游玩要求所有玩家必须运行相同的游戏版本(例如,游戏版本 v13.0.1 无法与 v13.0.0 联机)。\n\n如果不确定,请保持为“禁用”。",
|
"zh_CN": "修改 LDN 多人联机游玩模式。\n\nldn_mitm 联机插件将修改游戏中的本地无线和本地游玩功能,使其表现得像局域网一样,允许和其他安装了 ldn_mitm 插件的 Ryujinx 模拟器和破解的任天堂 Switch 主机在同一网络下进行本地连接,实现多人联机游玩。\n\n多人联机游玩要求所有玩家必须运行相同的游戏版本(例如,游戏版本 v13.0.1 无法与 v13.0.0 联机)。\n\n如果不确定,请保持为“禁用”。",
|
||||||
"zh_TW": "變更 LDN 多人遊戲模式。\n\nLdnMitm 將修改遊戲中的本機無線/本機遊戲功能,使其如同區域網路一樣執行,允許與其他安裝了 ldn_mitm 模組的 Ryujinx 實例和已破解的 Nintendo Switch 遊戲機進行本機同網路連線。\n\n多人遊戲要求所有玩家使用相同的遊戲版本 (例如,Super Smash Bros. Ultimate v13.0.1 無法連接 v13.0.0)。\n\n如果不確定,請保持 Disabled (停用) 狀態。"
|
"zh_TW": "變更 LDN 多人遊戲模式。\n\nldn_mitm 將修改遊戲中的本機無線/本機遊戲功能,使其如同區域網路一樣執行,允許與其他安裝了 ldn_mitm 模組的 Ryujinx 實例和已破解的 Nintendo Switch 遊戲機進行本機同網路連線。\n\n多人遊戲要求所有玩家使用相同的遊戲版本 (例如,Super Smash Bros. Ultimate v13.0.1 無法連接 v13.0.0)。\n\n如果不確定,請保持 Disabled (停用) 狀態。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -22800,7 +22858,7 @@
|
||||||
"el_GR": "",
|
"el_GR": "",
|
||||||
"en_US": "Generates a new passphrase, which can be shared with other players.",
|
"en_US": "Generates a new passphrase, which can be shared with other players.",
|
||||||
"es_ES": "Genera una nueva frase de contraseña, que puede ser compartida con otros jugadores.",
|
"es_ES": "Genera una nueva frase de contraseña, que puede ser compartida con otros jugadores.",
|
||||||
"fr_FR": "Génére un nouveau mot de passe, qui peut être partagé avec les autres.",
|
"fr_FR": "Génère un nouveau mot de passe, qui peut être partagé avec les autres.",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "Genera una nuova passphrase, che può essere condivisa con altri giocatori.",
|
"it_IT": "Genera una nuova passphrase, che può essere condivisa con altri giocatori.",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
|
|
@ -24843,4 +24901,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -22,5 +22,5 @@ chmod +x AppDir/AppRun AppDir/usr/bin/Ryujinx*
|
||||||
|
|
||||||
mkdir -p "$OUTDIR"
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
appimagetool -n --comp zstd --mksquashfs-opt -Xcompression-level --mksquashfs-opt 21 \
|
appimagetool --appimage-extract-and-run -n --comp zstd --mksquashfs-opt -Xcompression-level --mksquashfs-opt 21 \
|
||||||
AppDir "$OUTDIR"/Ryujinx.AppImage
|
AppDir "$OUTDIR"/Ryujinx.AppImage
|
||||||
64
distribution/macos/create_macos_build_headless.sh → distribution/macos/create_macos_pr_build_ava.sh
Executable file → Normal file
64
distribution/macos/create_macos_build_headless.sh → distribution/macos/create_macos_pr_build_ava.sh
Executable file → Normal file
|
|
@ -3,7 +3,7 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [ "$#" -lt 8 ]; then
|
if [ "$#" -lt 8 ]; then
|
||||||
echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION> <CANARY>"
|
echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION>"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -18,7 +18,6 @@ ENTITLEMENTS_FILE_PATH=$(readlink -f "$4")
|
||||||
VERSION=$5
|
VERSION=$5
|
||||||
SOURCE_REVISION_ID=$6
|
SOURCE_REVISION_ID=$6
|
||||||
CONFIGURATION=$7
|
CONFIGURATION=$7
|
||||||
CANARY=$8
|
|
||||||
|
|
||||||
if [[ "$(uname)" == "Darwin" ]]; then
|
if [[ "$(uname)" == "Darwin" ]]; then
|
||||||
echo "Clearing xattr on all dot undercsore files"
|
echo "Clearing xattr on all dot undercsore files"
|
||||||
|
|
@ -32,18 +31,12 @@ if [[ "$(uname)" == "Darwin" ]]; then
|
||||||
' sh {} +
|
' sh {} +
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$CANARY" == "1" ]; then
|
RELEASE_TAR_FILE_NAME=ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.app.tar
|
||||||
RELEASE_TAR_FILE_NAME=nogui-ryujinx-canary-$VERSION-macos_universal.tar
|
|
||||||
elif [ "$VERSION" == "1.1.0" ]; then
|
|
||||||
RELEASE_TAR_FILE_NAME=nogui-ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.tar
|
|
||||||
else
|
|
||||||
RELEASE_TAR_FILE_NAME=nogui-ryujinx-$VERSION-macos_universal.tar
|
|
||||||
fi
|
|
||||||
|
|
||||||
ARM64_OUTPUT="$TEMP_DIRECTORY/publish_arm64"
|
ARM64_APP_BUNDLE="$TEMP_DIRECTORY/output_arm64/Ryujinx.app"
|
||||||
X64_OUTPUT="$TEMP_DIRECTORY/publish_x64"
|
X64_APP_BUNDLE="$TEMP_DIRECTORY/output_x64/Ryujinx.app"
|
||||||
UNIVERSAL_OUTPUT="$OUTPUT_DIRECTORY/publish"
|
UNIVERSAL_APP_BUNDLE="$OUTPUT_DIRECTORY/Ryujinx.app"
|
||||||
EXECUTABLE_SUB_PATH=Ryujinx.Headless.SDL3
|
EXECUTABLE_SUB_PATH=Contents/MacOS/Ryujinx
|
||||||
|
|
||||||
rm -rf "$TEMP_DIRECTORY"
|
rm -rf "$TEMP_DIRECTORY"
|
||||||
mkdir -p "$TEMP_DIRECTORY"
|
mkdir -p "$TEMP_DIRECTORY"
|
||||||
|
|
@ -51,9 +44,9 @@ mkdir -p "$TEMP_DIRECTORY"
|
||||||
DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS)
|
DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS)
|
||||||
|
|
||||||
dotnet restore
|
dotnet restore
|
||||||
dotnet build -c "$CONFIGURATION" src/Ryujinx.Headless.SDL3
|
dotnet build -c "$CONFIGURATION" src/Ryujinx
|
||||||
dotnet publish -c "$CONFIGURATION" -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL3
|
dotnet publish -c "$CONFIGURATION" -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx
|
||||||
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL3
|
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx
|
||||||
|
|
||||||
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
|
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
|
||||||
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
|
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
|
||||||
|
|
@ -62,15 +55,20 @@ rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
|
||||||
# TODO: remove this once done
|
# TODO: remove this once done
|
||||||
rm -rf "$TEMP_DIRECTORY/publish_arm64/libsoundio.dylib"
|
rm -rf "$TEMP_DIRECTORY/publish_arm64/libsoundio.dylib"
|
||||||
|
|
||||||
rm -rf "$OUTPUT_DIRECTORY"
|
pushd "$BASE_DIR/distribution/macos"
|
||||||
|
./create_app_bundle.sh "$TEMP_DIRECTORY/publish_x64" "$TEMP_DIRECTORY/output_x64" "$ENTITLEMENTS_FILE_PATH"
|
||||||
|
./create_app_bundle.sh "$TEMP_DIRECTORY/publish_arm64" "$TEMP_DIRECTORY/output_arm64" "$ENTITLEMENTS_FILE_PATH"
|
||||||
|
popd
|
||||||
|
|
||||||
|
rm -rf "$UNIVERSAL_APP_BUNDLE"
|
||||||
mkdir -p "$OUTPUT_DIRECTORY"
|
mkdir -p "$OUTPUT_DIRECTORY"
|
||||||
|
|
||||||
# Let's copy one of the two different outputs and remove the executable
|
# Let's copy one of the two different app bundle and remove the executable
|
||||||
cp -R "$ARM64_OUTPUT/" "$UNIVERSAL_OUTPUT"
|
cp -R "$ARM64_APP_BUNDLE" "$UNIVERSAL_APP_BUNDLE"
|
||||||
rm "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH"
|
rm "$UNIVERSAL_APP_BUNDLE/$EXECUTABLE_SUB_PATH"
|
||||||
|
|
||||||
# Make its libraries universal
|
# Make its libraries universal
|
||||||
python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTPUT" "$X64_OUTPUT" "$UNIVERSAL_OUTPUT" "**/*.dylib"
|
python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_APP_BUNDLE" "$X64_APP_BUNDLE" "$UNIVERSAL_APP_BUNDLE" "**/*.dylib"
|
||||||
|
|
||||||
if ! [ -x "$(command -v lipo)" ];
|
if ! [ -x "$(command -v lipo)" ];
|
||||||
then
|
then
|
||||||
|
|
@ -85,7 +83,12 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Make the executable universal
|
# Make the executable universal
|
||||||
$LIPO "$ARM64_OUTPUT/$EXECUTABLE_SUB_PATH" "$X64_OUTPUT/$EXECUTABLE_SUB_PATH" -output "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH" -create
|
$LIPO "$ARM64_APP_BUNDLE/$EXECUTABLE_SUB_PATH" "$X64_APP_BUNDLE/$EXECUTABLE_SUB_PATH" -output "$UNIVERSAL_APP_BUNDLE/$EXECUTABLE_SUB_PATH" -create
|
||||||
|
|
||||||
|
# Patch up the Info.plist to have appropriate version
|
||||||
|
sed -r -i.bck "s/\%\%RYUJINX_BUILD_VERSION\%\%/$VERSION/g;" "$UNIVERSAL_APP_BUNDLE/Contents/Info.plist"
|
||||||
|
sed -r -i.bck "s/\%\%RYUJINX_BUILD_GIT_HASH\%\%/$SOURCE_REVISION_ID/g;" "$UNIVERSAL_APP_BUNDLE/Contents/Info.plist"
|
||||||
|
rm "$UNIVERSAL_APP_BUNDLE/Contents/Info.plist.bck"
|
||||||
|
|
||||||
# Now sign it
|
# Now sign it
|
||||||
if ! [ -x "$(command -v codesign)" ];
|
if ! [ -x "$(command -v codesign)" ];
|
||||||
|
|
@ -99,26 +102,19 @@ then
|
||||||
# NOTE: Currently require https://github.com/indygreg/apple-platform-rs/pull/44 to work on other OSes.
|
# NOTE: Currently require https://github.com/indygreg/apple-platform-rs/pull/44 to work on other OSes.
|
||||||
# cargo install --git "https://github.com/marysaka/apple-platform-rs" --branch "fix/adhoc-app-bundle" apple-codesign --bin "rcodesign"
|
# cargo install --git "https://github.com/marysaka/apple-platform-rs" --branch "fix/adhoc-app-bundle" apple-codesign --bin "rcodesign"
|
||||||
echo "Using rcodesign for ad-hoc signing"
|
echo "Using rcodesign for ad-hoc signing"
|
||||||
for FILE in "$UNIVERSAL_OUTPUT"/*; do
|
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$UNIVERSAL_APP_BUNDLE"
|
||||||
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
|
|
||||||
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$FILE"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
else
|
||||||
echo "Using codesign for ad-hoc signing"
|
echo "Using codesign for ad-hoc signing"
|
||||||
for FILE in "$UNIVERSAL_OUTPUT"/*; do
|
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$UNIVERSAL_APP_BUNDLE"
|
||||||
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
|
|
||||||
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$FILE"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Creating archive"
|
echo "Creating archive"
|
||||||
pushd "$OUTPUT_DIRECTORY"
|
pushd "$OUTPUT_DIRECTORY"
|
||||||
tar --exclude "publish/Ryujinx.Headless.SDL3" -cvf "$RELEASE_TAR_FILE_NAME" publish 1> /dev/null
|
tar --exclude "Ryujinx.app/Contents/MacOS/Ryujinx" -cvf "$RELEASE_TAR_FILE_NAME" Ryujinx.app 1> /dev/null
|
||||||
python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "publish/Ryujinx.Headless.SDL3" "publish/Ryujinx.Headless.SDL3"
|
python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "Ryujinx.app/Contents/MacOS/Ryujinx" "Ryujinx.app/Contents/MacOS/Ryujinx"
|
||||||
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
|
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
|
||||||
rm "$RELEASE_TAR_FILE_NAME"
|
rm "$RELEASE_TAR_FILE_NAME"
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
echo "Done"
|
echo "Done"
|
||||||
|
|
@ -2050,7 +2050,9 @@
|
||||||
010003C00B868000,"Ninjin: Clash of Carrots",online-broken,playable,2024-07-10 05:12:26
|
010003C00B868000,"Ninjin: Clash of Carrots",online-broken,playable,2024-07-10 05:12:26
|
||||||
0100746010E4C000,"NinNinDays",,playable,2022-11-20 15:17:29
|
0100746010E4C000,"NinNinDays",,playable,2022-11-20 15:17:29
|
||||||
0100C9A00ECE6000,"Nintendo 64™ – Nintendo Switch Online",gpu;vulkan,ingame,2024-04-23 20:21:07
|
0100C9A00ECE6000,"Nintendo 64™ – Nintendo Switch Online",gpu;vulkan,ingame,2024-04-23 20:21:07
|
||||||
|
010057D00ECE4000,"Nintendo 64™ – Nintendo Switch Online",gpu;vulkan,ingame,2024-04-23 20:21:07
|
||||||
0100e0601c632000,"Nintendo 64™ – Nintendo Switch Online: MATURE 17+",,ingame,2025-02-03 22:27:00
|
0100e0601c632000,"Nintendo 64™ – Nintendo Switch Online: MATURE 17+",,ingame,2025-02-03 22:27:00
|
||||||
|
010037A0170D2000,"NINTENDO 64™ – Nintendo Switch Online 18+",,ingame,2025-02-03 22:27:00
|
||||||
0100D870045B6000,"Nintendo Entertainment System™ - Nintendo Switch Online",online,playable,2022-07-01 15:45:06
|
0100D870045B6000,"Nintendo Entertainment System™ - Nintendo Switch Online",online,playable,2022-07-01 15:45:06
|
||||||
0100C4B0034B2000,"Nintendo Labo Toy-Con 01 Variety Kit",gpu,ingame,2022-08-07 12:56:07
|
0100C4B0034B2000,"Nintendo Labo Toy-Con 01 Variety Kit",gpu,ingame,2022-08-07 12:56:07
|
||||||
01001E9003502000,"Nintendo Labo Toy-Con 03 Vehicle Kit",services;crash,menus,2022-08-03 17:20:11
|
01001E9003502000,"Nintendo Labo Toy-Con 03 Vehicle Kit",services;crash,menus,2022-08-03 17:20:11
|
||||||
|
|
@ -2638,6 +2640,7 @@
|
||||||
0100B16009C10000,"SINNER: Sacrifice for Redemption",nvdec;UE4;vulkan-backend-bug,playable,2022-08-12 20:37:33
|
0100B16009C10000,"SINNER: Sacrifice for Redemption",nvdec;UE4;vulkan-backend-bug,playable,2022-08-12 20:37:33
|
||||||
0100E9201410E000,"Sir Lovelot",,playable,2021-04-05 16:21:46
|
0100E9201410E000,"Sir Lovelot",,playable,2021-04-05 16:21:46
|
||||||
0100134011E32000,"Skate City",,playable,2022-11-04 11:37:39
|
0100134011E32000,"Skate City",,playable,2022-11-04 11:37:39
|
||||||
|
0100a8501b66e000,"Skateboard Drifting with Maxwell Cat: The Game Simulator",,playable,2026-02-17 19:05:00
|
||||||
0100B2F008BD8000,"Skee-Ball",,playable,2020-11-16 04:44:07
|
0100B2F008BD8000,"Skee-Ball",,playable,2020-11-16 04:44:07
|
||||||
01001A900F862000,"Skelattack",,playable,2021-06-09 15:26:26
|
01001A900F862000,"Skelattack",,playable,2021-06-09 15:26:26
|
||||||
01008E700F952000,"Skelittle: A Giant Party!",,playable,2021-06-09 19:08:34
|
01008E700F952000,"Skelittle: A Giant Party!",,playable,2021-06-09 19:08:34
|
||||||
|
|
@ -3307,6 +3310,7 @@
|
||||||
0100AFA011068000,"Voxel Pirates",,playable,2022-09-28 22:55:02
|
0100AFA011068000,"Voxel Pirates",,playable,2022-09-28 22:55:02
|
||||||
0100BFB00D1F4000,"Voxel Sword",,playable,2022-08-30 14:57:27
|
0100BFB00D1F4000,"Voxel Sword",,playable,2022-08-30 14:57:27
|
||||||
01004E90028A2000,"Vroom in the night sky",Needs Update;vulkan-backend-bug,playable,2023-02-20 02:32:29
|
01004E90028A2000,"Vroom in the night sky",Needs Update;vulkan-backend-bug,playable,2023-02-20 02:32:29
|
||||||
|
0100BFC01D976000,"Virtual Boy – Nintendo Classics",services,nothing,2026-02-17 11:26:59
|
||||||
0100C7C00AE6C000,"VSR: Void Space Racing",,playable,2021-01-27 14:08:59
|
0100C7C00AE6C000,"VSR: Void Space Racing",,playable,2021-01-27 14:08:59
|
||||||
0100B130119D0000,"Waifu Uncovered",crash,ingame,2023-02-27 01:17:46
|
0100B130119D0000,"Waifu Uncovered",crash,ingame,2023-02-27 01:17:46
|
||||||
0100E29010A4A000,"Wanba Warriors",,playable,2020-10-04 17:56:22
|
0100E29010A4A000,"Wanba Warriors",,playable,2020-10-04 17:56:22
|
||||||
|
|
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
<clear />
|
<clear />
|
||||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||||
<!-- Only needed when using pre-release versions of Ryujinx.LibHac. -->
|
<!-- Only needed when using pre-release versions of Ryujinx.LibHac. -->
|
||||||
<add key="LibHacAlpha" value="https://git.ryujinx.app/api/v4/projects/17/packages/nuget/index.json" />
|
<add key="LibHacAlpha" value="https://git.ryujinx.app/api/packages/projects/nuget/index.json" />
|
||||||
<add key="Ryujinx.UpdateClient" value="https://git.ryujinx.app/api/v4/projects/71/packages/nuget/index.json" />
|
|
||||||
</packageSources>
|
</packageSources>
|
||||||
<packageSourceMapping>
|
<packageSourceMapping>
|
||||||
<!-- key value for <packageSource> should match key values from <packageSources> element -->
|
<!-- key value for <packageSource> should match key values from <packageSources> element -->
|
||||||
|
|
@ -14,10 +13,6 @@
|
||||||
<packageSource key="nuget.org">
|
<packageSource key="nuget.org">
|
||||||
<package pattern="*" />
|
<package pattern="*" />
|
||||||
</packageSource>
|
</packageSource>
|
||||||
<packageSource key="Ryujinx.UpdateClient">
|
|
||||||
<package pattern="Ryujinx.UpdateClient" />
|
|
||||||
<package pattern="Ryujinx.Systems.Update.Common" />
|
|
||||||
</packageSource>
|
|
||||||
<packageSource key="LibHacAlpha">
|
<packageSource key="LibHacAlpha">
|
||||||
<package pattern="Ryujinx.LibHac" />
|
<package pattern="Ryujinx.LibHac" />
|
||||||
</packageSource>
|
</packageSource>
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,7 @@ namespace ARMeilleure.Common
|
||||||
{
|
{
|
||||||
_allocated.Dispose();
|
_allocated.Dispose();
|
||||||
|
|
||||||
foreach (IntPtr page in _pages.Values)
|
foreach (nint page in _pages.Values)
|
||||||
{
|
{
|
||||||
NativeAllocator.Instance.Free((void*)page);
|
NativeAllocator.Instance.Free((void*)page);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
context.LoadFromContext();
|
context.LoadFromContext();
|
||||||
|
|
||||||
context.Return(Const(op.Address));
|
InstEmitFlowHelper.EmitReturn(context, Const(op.Address));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Svc(ArmEmitterContext context)
|
public static void Svc(ArmEmitterContext context)
|
||||||
|
|
@ -49,7 +49,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
context.LoadFromContext();
|
context.LoadFromContext();
|
||||||
|
|
||||||
context.Return(Const(op.Address));
|
InstEmitFlowHelper.EmitReturn(context, Const(op.Address));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
context.LoadFromContext();
|
context.LoadFromContext();
|
||||||
|
|
||||||
context.Return(Const(context.CurrOp.Address));
|
InstEmitFlowHelper.EmitReturn(context, Const(context.CurrOp.Address));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
|
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
|
||||||
|
|
||||||
context.Return(GetIntOrZR(context, op.Rn));
|
EmitReturn(context, GetIntOrZR(context, op.Rn));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);
|
public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
static class InstEmitFlowHelper
|
static class InstEmitFlowHelper
|
||||||
{
|
{
|
||||||
|
// How many calls we can have in our call stack before we give up and return to the dispatcher.
|
||||||
|
// This prevents stack overflows caused by deep recursive calls.
|
||||||
|
private const int MaxCallDepth = 200;
|
||||||
|
|
||||||
public static void EmitCondBranch(ArmEmitterContext context, Operand target, Condition cond)
|
public static void EmitCondBranch(ArmEmitterContext context, Operand target, Condition cond)
|
||||||
{
|
{
|
||||||
if (cond != Condition.Al)
|
if (cond != Condition.Al)
|
||||||
|
|
@ -182,12 +186,7 @@ namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
if (isReturn || context.IsSingleStep)
|
if (isReturn || context.IsSingleStep)
|
||||||
{
|
{
|
||||||
if (target.Type == OperandType.I32)
|
EmitReturn(context, target);
|
||||||
{
|
|
||||||
target = context.ZeroExtend32(OperandType.I64, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Return(target);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -195,6 +194,19 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EmitReturn(ArmEmitterContext context, Operand target)
|
||||||
|
{
|
||||||
|
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||||
|
DecreaseCallDepth(context, nativeContext);
|
||||||
|
|
||||||
|
if (target.Type == OperandType.I32)
|
||||||
|
{
|
||||||
|
target = context.ZeroExtend32(OperandType.I64, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Return(target);
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitTableBranch(ArmEmitterContext context, Operand guestAddress, bool isJump)
|
private static void EmitTableBranch(ArmEmitterContext context, Operand guestAddress, bool isJump)
|
||||||
{
|
{
|
||||||
context.StoreToContext();
|
context.StoreToContext();
|
||||||
|
|
@ -257,6 +269,8 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
if (isJump)
|
if (isJump)
|
||||||
{
|
{
|
||||||
|
DecreaseCallDepth(context, nativeContext);
|
||||||
|
|
||||||
context.Tailcall(hostAddress, nativeContext);
|
context.Tailcall(hostAddress, nativeContext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -278,8 +292,42 @@ namespace ARMeilleure.Instructions
|
||||||
Operand lblContinue = context.GetLabel(nextAddr.Value);
|
Operand lblContinue = context.GetLabel(nextAddr.Value);
|
||||||
context.BranchIf(lblContinue, returnAddress, nextAddr, Comparison.Equal, BasicBlockFrequency.Cold);
|
context.BranchIf(lblContinue, returnAddress, nextAddr, Comparison.Equal, BasicBlockFrequency.Cold);
|
||||||
|
|
||||||
|
DecreaseCallDepth(context, nativeContext);
|
||||||
|
|
||||||
context.Return(returnAddress);
|
context.Return(returnAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EmitCallDepthCheckAndIncrement(EmitterContext context, Operand guestAddress)
|
||||||
|
{
|
||||||
|
if (!Optimizations.EnableDeepCallRecursionProtection)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||||
|
Operand callDepthAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||||
|
Operand currentCallDepth = context.Load(OperandType.I32, callDepthAddr);
|
||||||
|
Operand lblDoCall = Label();
|
||||||
|
|
||||||
|
context.BranchIf(lblDoCall, currentCallDepth, Const(MaxCallDepth), Comparison.LessUI);
|
||||||
|
context.Store(callDepthAddr, context.Subtract(currentCallDepth, Const(1)));
|
||||||
|
context.Return(guestAddress);
|
||||||
|
|
||||||
|
context.MarkLabel(lblDoCall);
|
||||||
|
context.Store(callDepthAddr, context.Add(currentCallDepth, Const(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DecreaseCallDepth(EmitterContext context, Operand nativeContext)
|
||||||
|
{
|
||||||
|
if (!Optimizations.EnableDeepCallRecursionProtection)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand callDepthAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||||
|
Operand currentCallDepth = context.Load(OperandType.I32, callDepthAddr);
|
||||||
|
context.Store(callDepthAddr, context.Subtract(currentCallDepth, Const(1)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ namespace ARMeilleure
|
||||||
public static bool AllowLcqInFunctionTable { get; set; } = true;
|
public static bool AllowLcqInFunctionTable { get; set; } = true;
|
||||||
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
|
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
|
||||||
public static bool EnableDebugging { get; set; } = false;
|
public static bool EnableDebugging { get; set; } = false;
|
||||||
|
public static bool EnableDeepCallRecursionProtection { get; set; } = true;
|
||||||
|
|
||||||
public static bool UseAdvSimdIfAvailable { get; set; } = true;
|
public static bool UseAdvSimdIfAvailable { get; set; } = true;
|
||||||
public static bool UseArm64AesIfAvailable { get; set; } = true;
|
public static bool UseArm64AesIfAvailable { get; set; } = true;
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,11 @@ namespace ARMeilleure.State
|
||||||
public bool GetFPstateFlag(FPState flag) => _nativeContext.GetFPStateFlag(flag);
|
public bool GetFPstateFlag(FPState flag) => _nativeContext.GetFPStateFlag(flag);
|
||||||
public void SetFPstateFlag(FPState flag, bool value) => _nativeContext.SetFPStateFlag(flag, value);
|
public void SetFPstateFlag(FPState flag, bool value) => _nativeContext.SetFPStateFlag(flag, value);
|
||||||
|
|
||||||
|
internal void ResetCallDepth()
|
||||||
|
{
|
||||||
|
_nativeContext.ResetCallDepth();
|
||||||
|
}
|
||||||
|
|
||||||
internal void CheckInterrupt()
|
internal void CheckInterrupt()
|
||||||
{
|
{
|
||||||
if (Interrupted)
|
if (Interrupted)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ namespace ARMeilleure.State
|
||||||
public ulong ExclusiveValueHigh;
|
public ulong ExclusiveValueHigh;
|
||||||
public int Running;
|
public int Running;
|
||||||
public long Tpidr2El0;
|
public long Tpidr2El0;
|
||||||
|
public int CallDepth;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Precise PC value used for debugging.
|
/// Precise PC value used for debugging.
|
||||||
|
|
@ -199,6 +200,8 @@ namespace ARMeilleure.State
|
||||||
public bool GetRunning() => GetStorage().Running != 0;
|
public bool GetRunning() => GetStorage().Running != 0;
|
||||||
public void SetRunning(bool value) => GetStorage().Running = value ? 1 : 0;
|
public void SetRunning(bool value) => GetStorage().Running = value ? 1 : 0;
|
||||||
|
|
||||||
|
public void ResetCallDepth() => GetStorage().CallDepth = 0;
|
||||||
|
|
||||||
public unsafe static int GetRegisterOffset(Register reg)
|
public unsafe static int GetRegisterOffset(Register reg)
|
||||||
{
|
{
|
||||||
if (reg.Type == RegisterType.Integer)
|
if (reg.Type == RegisterType.Integer)
|
||||||
|
|
@ -284,6 +287,11 @@ namespace ARMeilleure.State
|
||||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.DebugPrecisePc);
|
return StorageOffset(ref _dummyStorage, ref _dummyStorage.DebugPrecisePc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int GetCallDepthOffset()
|
||||||
|
{
|
||||||
|
return StorageOffset(ref _dummyStorage, ref _dummyStorage.CallDepth);
|
||||||
|
}
|
||||||
|
|
||||||
private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
|
private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
|
||||||
{
|
{
|
||||||
return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);
|
return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace ARMeilleure.Translation.PTC
|
||||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||||
|
|
||||||
private const uint InternalVersion = 7009; //! To be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 7010; //! To be incremented manually for each change to the ARMeilleure project.
|
||||||
|
|
||||||
private const string ActualDir = "0";
|
private const string ActualDir = "0";
|
||||||
private const string BackupDir = "1";
|
private const string BackupDir = "1";
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,7 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
Statistics.StartTimer();
|
Statistics.StartTimer();
|
||||||
|
|
||||||
|
context.ResetCallDepth();
|
||||||
ulong nextAddr = func.Execute(Stubs.ContextWrapper, context);
|
ulong nextAddr = func.Execute(Stubs.ContextWrapper, context);
|
||||||
|
|
||||||
Statistics.StopTimer(address);
|
Statistics.StopTimer(address);
|
||||||
|
|
@ -260,6 +261,7 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
Logger.StartPass(PassName.Translation);
|
Logger.StartPass(PassName.Translation);
|
||||||
|
|
||||||
|
InstEmitFlowHelper.EmitCallDepthCheckAndIncrement(context, Const(address));
|
||||||
EmitSynchronization(context);
|
EmitSynchronization(context);
|
||||||
|
|
||||||
if (blocks[0].Address != address)
|
if (blocks[0].Address != address)
|
||||||
|
|
|
||||||
|
|
@ -262,10 +262,18 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
Operand runningAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetRunningOffset()));
|
Operand runningAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetRunningOffset()));
|
||||||
Operand dispatchAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset()));
|
Operand dispatchAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset()));
|
||||||
|
Operand callDepthAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||||
|
|
||||||
EmitSyncFpContext(context, nativeContext, true);
|
EmitSyncFpContext(context, nativeContext, true);
|
||||||
|
|
||||||
context.MarkLabel(beginLbl);
|
context.MarkLabel(beginLbl);
|
||||||
|
|
||||||
|
if (Optimizations.EnableDeepCallRecursionProtection)
|
||||||
|
{
|
||||||
|
// Reset the call depth counter, since this is our first guest function call.
|
||||||
|
context.Store(callDepthAddress, Const(0));
|
||||||
|
}
|
||||||
|
|
||||||
context.Store(dispatchAddress, guestAddress);
|
context.Store(dispatchAddress, guestAddress);
|
||||||
context.Copy(guestAddress, context.Call(Const((ulong)DispatchStub), OperandType.I64, nativeContext));
|
context.Copy(guestAddress, context.Call(Const((ulong)DispatchStub), OperandType.I64, nativeContext));
|
||||||
context.BranchIfFalse(endLbl, guestAddress);
|
context.BranchIfFalse(endLbl, guestAddress);
|
||||||
|
|
|
||||||
16
src/Ryujinx.Audio.Backends.Apple/AppleAudioBuffer.cs
Normal file
16
src/Ryujinx.Audio.Backends.Apple/AppleAudioBuffer.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
namespace Ryujinx.Audio.Backends.Apple
|
||||||
|
{
|
||||||
|
class AppleAudioBuffer
|
||||||
|
{
|
||||||
|
public readonly ulong DriverIdentifier;
|
||||||
|
public readonly ulong SampleCount;
|
||||||
|
public ulong SamplePlayed;
|
||||||
|
|
||||||
|
public AppleAudioBuffer(ulong driverIdentifier, ulong sampleCount)
|
||||||
|
{
|
||||||
|
DriverIdentifier = driverIdentifier;
|
||||||
|
SampleCount = sampleCount;
|
||||||
|
SamplePlayed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
196
src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceDriver.cs
Normal file
196
src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceDriver.cs
Normal file
|
|
@ -0,0 +1,196 @@
|
||||||
|
using Ryujinx.Audio.Common;
|
||||||
|
using Ryujinx.Audio.Integration;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Memory;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
using Ryujinx.Audio.Backends.Apple.Native;
|
||||||
|
using static Ryujinx.Audio.Backends.Apple.Native.AudioToolbox;
|
||||||
|
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
|
||||||
|
|
||||||
|
namespace Ryujinx.Audio.Backends.Apple
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
[SupportedOSPlatform("ios")]
|
||||||
|
public sealed class AppleHardwareDeviceDriver : IHardwareDeviceDriver
|
||||||
|
{
|
||||||
|
private readonly ManualResetEvent _updateRequiredEvent;
|
||||||
|
private readonly ManualResetEvent _pauseEvent;
|
||||||
|
private readonly ConcurrentDictionary<AppleHardwareDeviceSession, byte> _sessions;
|
||||||
|
private readonly bool _supportSurroundConfiguration;
|
||||||
|
|
||||||
|
public float Volume { get; set; }
|
||||||
|
|
||||||
|
public AppleHardwareDeviceDriver()
|
||||||
|
{
|
||||||
|
_updateRequiredEvent = new ManualResetEvent(false);
|
||||||
|
_pauseEvent = new ManualResetEvent(true);
|
||||||
|
_sessions = new ConcurrentDictionary<AppleHardwareDeviceSession, byte>();
|
||||||
|
|
||||||
|
_supportSurroundConfiguration = TestSurroundSupport();
|
||||||
|
|
||||||
|
Volume = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TestSurroundSupport()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AudioStreamBasicDescription format =
|
||||||
|
GetAudioFormat(SampleFormat.PcmFloat, Constants.TargetSampleRate, 6);
|
||||||
|
|
||||||
|
int result = AudioQueueNewOutput(
|
||||||
|
ref format,
|
||||||
|
nint.Zero,
|
||||||
|
nint.Zero,
|
||||||
|
nint.Zero,
|
||||||
|
nint.Zero,
|
||||||
|
0,
|
||||||
|
out nint testQueue);
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
{
|
||||||
|
AudioChannelLayout layout = new AudioChannelLayout
|
||||||
|
{
|
||||||
|
AudioChannelLayoutTag = kAudioChannelLayoutTag_MPEG_5_1_A,
|
||||||
|
AudioChannelBitmap = 0,
|
||||||
|
NumberChannelDescriptions = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
int layoutResult = AudioQueueSetProperty(
|
||||||
|
testQueue,
|
||||||
|
kAudioQueueProperty_ChannelLayout,
|
||||||
|
ref layout,
|
||||||
|
(uint)Marshal.SizeOf<AudioChannelLayout>());
|
||||||
|
|
||||||
|
if (layoutResult == 0)
|
||||||
|
{
|
||||||
|
AudioQueueDispose(testQueue, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioQueueDispose(testQueue, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsSupported => OperatingSystem.IsMacOSVersionAtLeast(10, 5);
|
||||||
|
|
||||||
|
public ManualResetEvent GetUpdateRequiredEvent()
|
||||||
|
=> _updateRequiredEvent;
|
||||||
|
|
||||||
|
public ManualResetEvent GetPauseEvent()
|
||||||
|
=> _pauseEvent;
|
||||||
|
|
||||||
|
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager,
|
||||||
|
SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
||||||
|
{
|
||||||
|
if (channelCount == 0)
|
||||||
|
{
|
||||||
|
channelCount = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sampleRate == 0)
|
||||||
|
{
|
||||||
|
sampleRate = Constants.TargetSampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction != Direction.Output)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Input direction is currently not implemented on Apple backend!");
|
||||||
|
}
|
||||||
|
|
||||||
|
AppleHardwareDeviceSession session = new(this, memoryManager, sampleFormat, sampleRate, channelCount);
|
||||||
|
|
||||||
|
_sessions.TryAdd(session, 0);
|
||||||
|
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool Unregister(AppleHardwareDeviceSession session)
|
||||||
|
=> _sessions.TryRemove(session, out _);
|
||||||
|
|
||||||
|
internal static AudioStreamBasicDescription GetAudioFormat(SampleFormat sampleFormat, uint sampleRate,
|
||||||
|
uint channelCount)
|
||||||
|
{
|
||||||
|
uint formatFlags;
|
||||||
|
uint bitsPerChannel;
|
||||||
|
|
||||||
|
switch (sampleFormat)
|
||||||
|
{
|
||||||
|
case SampleFormat.PcmInt8:
|
||||||
|
formatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||||
|
bitsPerChannel = 8;
|
||||||
|
break;
|
||||||
|
case SampleFormat.PcmInt16:
|
||||||
|
formatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||||
|
bitsPerChannel = 16;
|
||||||
|
break;
|
||||||
|
case SampleFormat.PcmInt32:
|
||||||
|
formatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||||
|
bitsPerChannel = 32;
|
||||||
|
break;
|
||||||
|
case SampleFormat.PcmFloat:
|
||||||
|
formatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
|
||||||
|
bitsPerChannel = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException($"Unsupported sample format {sampleFormat}");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint bytesPerFrame = (bitsPerChannel / 8) * channelCount;
|
||||||
|
|
||||||
|
return new AudioStreamBasicDescription
|
||||||
|
{
|
||||||
|
SampleRate = sampleRate,
|
||||||
|
FormatID = kAudioFormatLinearPCM,
|
||||||
|
FormatFlags = formatFlags,
|
||||||
|
BytesPerPacket = bytesPerFrame,
|
||||||
|
FramesPerPacket = 1,
|
||||||
|
BytesPerFrame = bytesPerFrame,
|
||||||
|
ChannelsPerFrame = channelCount,
|
||||||
|
BitsPerChannel = bitsPerChannel,
|
||||||
|
Reserved = 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
foreach (AppleHardwareDeviceSession session in _sessions.Keys)
|
||||||
|
{
|
||||||
|
session.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
_pauseEvent.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SupportsDirection(Direction direction)
|
||||||
|
=> direction != Direction.Input;
|
||||||
|
|
||||||
|
public bool SupportsSampleRate(uint sampleRate) => true;
|
||||||
|
|
||||||
|
public bool SupportsSampleFormat(SampleFormat sampleFormat)
|
||||||
|
=> sampleFormat != SampleFormat.PcmInt24;
|
||||||
|
|
||||||
|
public bool SupportsChannelCount(uint channelCount)
|
||||||
|
=> channelCount != 6 || _supportSurroundConfiguration;
|
||||||
|
}
|
||||||
|
}
|
||||||
285
src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceSession.cs
Normal file
285
src/Ryujinx.Audio.Backends.Apple/AppleHardwareDeviceSession.cs
Normal file
|
|
@ -0,0 +1,285 @@
|
||||||
|
using Ryujinx.Audio.Backends.Common;
|
||||||
|
using Ryujinx.Audio.Common;
|
||||||
|
using Ryujinx.Memory;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
using static Ryujinx.Audio.Backends.Apple.Native.AudioToolbox;
|
||||||
|
|
||||||
|
namespace Ryujinx.Audio.Backends.Apple
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
[SupportedOSPlatform("ios")]
|
||||||
|
class AppleHardwareDeviceSession : HardwareDeviceSessionOutputBase
|
||||||
|
{
|
||||||
|
private const int NumBuffers = 3;
|
||||||
|
|
||||||
|
private readonly AppleHardwareDeviceDriver _driver;
|
||||||
|
private readonly ConcurrentQueue<AppleAudioBuffer> _queuedBuffers = new();
|
||||||
|
private readonly DynamicRingBuffer _ringBuffer = new();
|
||||||
|
private readonly ManualResetEvent _updateRequiredEvent;
|
||||||
|
|
||||||
|
private readonly AudioQueueOutputCallback _callbackDelegate;
|
||||||
|
private readonly GCHandle _gcHandle;
|
||||||
|
|
||||||
|
private nint _audioQueue;
|
||||||
|
private readonly nint[] _audioQueueBuffers = new nint[NumBuffers];
|
||||||
|
private readonly int[] _bufferBytesFilled = new int[NumBuffers];
|
||||||
|
|
||||||
|
private readonly int _bytesPerFrame;
|
||||||
|
|
||||||
|
private ulong _playedSampleCount;
|
||||||
|
private bool _started;
|
||||||
|
private float _volume = 1f;
|
||||||
|
|
||||||
|
private readonly object _lock = new();
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
private delegate void AudioQueueOutputCallback(
|
||||||
|
nint userData,
|
||||||
|
nint audioQueue,
|
||||||
|
nint buffer);
|
||||||
|
|
||||||
|
public AppleHardwareDeviceSession(
|
||||||
|
AppleHardwareDeviceDriver driver,
|
||||||
|
IVirtualMemoryManager memoryManager,
|
||||||
|
SampleFormat requestedSampleFormat,
|
||||||
|
uint requestedSampleRate,
|
||||||
|
uint requestedChannelCount)
|
||||||
|
: base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||||
|
{
|
||||||
|
_driver = driver;
|
||||||
|
_updateRequiredEvent = driver.GetUpdateRequiredEvent();
|
||||||
|
_callbackDelegate = OutputCallback;
|
||||||
|
_bytesPerFrame = BackendHelper.GetSampleSize(requestedSampleFormat) * (int)requestedChannelCount;
|
||||||
|
|
||||||
|
_gcHandle = GCHandle.Alloc(this, GCHandleType.Normal);
|
||||||
|
|
||||||
|
SetupAudioQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupAudioQueue()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
AudioStreamBasicDescription format = AppleHardwareDeviceDriver.GetAudioFormat(
|
||||||
|
RequestedSampleFormat,
|
||||||
|
RequestedSampleRate,
|
||||||
|
RequestedChannelCount);
|
||||||
|
|
||||||
|
nint callbackPtr = Marshal.GetFunctionPointerForDelegate(_callbackDelegate);
|
||||||
|
nint userData = GCHandle.ToIntPtr(_gcHandle);
|
||||||
|
|
||||||
|
int result = AudioQueueNewOutput(
|
||||||
|
ref format,
|
||||||
|
callbackPtr,
|
||||||
|
userData,
|
||||||
|
nint.Zero,
|
||||||
|
nint.Zero,
|
||||||
|
0,
|
||||||
|
out _audioQueue);
|
||||||
|
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"AudioQueueNewOutput failed: {result}");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint framesPerBuffer = RequestedSampleRate / 100;
|
||||||
|
uint bufferSize = framesPerBuffer * (uint)_bytesPerFrame;
|
||||||
|
|
||||||
|
for (int i = 0; i < NumBuffers; i++)
|
||||||
|
{
|
||||||
|
AudioQueueAllocateBuffer(_audioQueue, bufferSize, out _audioQueueBuffers[i]);
|
||||||
|
_bufferBytesFilled[i] = 0;
|
||||||
|
|
||||||
|
PrimeBuffer(_audioQueueBuffers[i], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void PrimeBuffer(nint bufferPtr, int bufferIndex)
|
||||||
|
{
|
||||||
|
AudioQueueBuffer* buffer = (AudioQueueBuffer*)bufferPtr;
|
||||||
|
|
||||||
|
int capacityBytes = (int)buffer->AudioDataBytesCapacity;
|
||||||
|
int framesPerBuffer = capacityBytes / _bytesPerFrame;
|
||||||
|
|
||||||
|
int availableFrames = _ringBuffer.Length / _bytesPerFrame;
|
||||||
|
int framesToRead = Math.Min(availableFrames, framesPerBuffer);
|
||||||
|
int bytesToRead = framesToRead * _bytesPerFrame;
|
||||||
|
|
||||||
|
Span<byte> dst = new((void*)buffer->AudioData, capacityBytes);
|
||||||
|
dst.Clear();
|
||||||
|
|
||||||
|
if (bytesToRead > 0)
|
||||||
|
{
|
||||||
|
Span<byte> audio = dst.Slice(0, bytesToRead);
|
||||||
|
_ringBuffer.Read(audio, 0, bytesToRead);
|
||||||
|
ApplyVolume(buffer->AudioData, bytesToRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->AudioDataByteSize = (uint)capacityBytes;
|
||||||
|
_bufferBytesFilled[bufferIndex] = bytesToRead;
|
||||||
|
|
||||||
|
AudioQueueEnqueueBuffer(_audioQueue, bufferPtr, 0, nint.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OutputCallback(nint userData, nint audioQueue, nint bufferPtr)
|
||||||
|
{
|
||||||
|
if (!_started || bufferPtr == nint.Zero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int bufferIndex = Array.IndexOf(_audioQueueBuffers, bufferPtr);
|
||||||
|
if (bufferIndex < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int bytesPlayed = _bufferBytesFilled[bufferIndex];
|
||||||
|
if (bytesPlayed > 0)
|
||||||
|
{
|
||||||
|
ProcessPlayedSamples(bytesPlayed);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimeBuffer(bufferPtr, bufferIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessPlayedSamples(int bytesPlayed)
|
||||||
|
{
|
||||||
|
ulong samplesPlayed = GetSampleCount(bytesPlayed);
|
||||||
|
ulong remaining = samplesPlayed;
|
||||||
|
bool needUpdate = false;
|
||||||
|
|
||||||
|
while (remaining > 0 && _queuedBuffers.TryPeek(out AppleAudioBuffer buffer))
|
||||||
|
{
|
||||||
|
ulong needed = buffer.SampleCount - Interlocked.Read(ref buffer.SamplePlayed);
|
||||||
|
ulong take = Math.Min(needed, remaining);
|
||||||
|
|
||||||
|
ulong played = Interlocked.Add(ref buffer.SamplePlayed, take);
|
||||||
|
remaining -= take;
|
||||||
|
|
||||||
|
if (played == buffer.SampleCount)
|
||||||
|
{
|
||||||
|
_queuedBuffers.TryDequeue(out _);
|
||||||
|
needUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Interlocked.Add(ref _playedSampleCount, take);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needUpdate)
|
||||||
|
{
|
||||||
|
_updateRequiredEvent.Set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void ApplyVolume(nint dataPtr, int byteSize)
|
||||||
|
{
|
||||||
|
float volume = Math.Clamp(_volume * _driver.Volume, 0f, 1f);
|
||||||
|
if (volume >= 0.999f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int sampleCount = byteSize / BackendHelper.GetSampleSize(RequestedSampleFormat);
|
||||||
|
|
||||||
|
switch (RequestedSampleFormat)
|
||||||
|
{
|
||||||
|
case SampleFormat.PcmInt16:
|
||||||
|
short* s16 = (short*)dataPtr;
|
||||||
|
for (int i = 0; i < sampleCount; i++)
|
||||||
|
s16[i] = (short)(s16[i] * volume);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SampleFormat.PcmFloat:
|
||||||
|
float* f32 = (float*)dataPtr;
|
||||||
|
for (int i = 0; i < sampleCount; i++)
|
||||||
|
f32[i] *= volume;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SampleFormat.PcmInt32:
|
||||||
|
int* s32 = (int*)dataPtr;
|
||||||
|
for (int i = 0; i < sampleCount; i++)
|
||||||
|
s32[i] = (int)(s32[i] * volume);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SampleFormat.PcmInt8:
|
||||||
|
sbyte* s8 = (sbyte*)dataPtr;
|
||||||
|
for (int i = 0; i < sampleCount; i++)
|
||||||
|
s8[i] = (sbyte)(s8[i] * volume);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void QueueBuffer(AudioBuffer buffer)
|
||||||
|
{
|
||||||
|
_ringBuffer.Write(buffer.Data, 0, buffer.Data.Length);
|
||||||
|
_queuedBuffers.Enqueue(new AppleAudioBuffer(buffer.DataPointer, GetSampleCount(buffer)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (_started)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_started = true;
|
||||||
|
AudioQueueStart(_audioQueue, nint.Zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Stop()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (!_started)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_started = false;
|
||||||
|
AudioQueuePause(_audioQueue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ulong GetPlayedSampleCount()
|
||||||
|
=> Interlocked.Read(ref _playedSampleCount);
|
||||||
|
|
||||||
|
public override float GetVolume() => _volume;
|
||||||
|
public override void SetVolume(float volume) => _volume = volume;
|
||||||
|
|
||||||
|
public override bool WasBufferFullyConsumed(AudioBuffer buffer)
|
||||||
|
{
|
||||||
|
if (!_queuedBuffers.TryPeek(out AppleAudioBuffer driverBuffer))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return driverBuffer.DriverIdentifier != buffer.DataPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PrepareToClose() { }
|
||||||
|
public override void UnregisterBuffer(AudioBuffer buffer) { }
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
|
||||||
|
if (_audioQueue != nint.Zero)
|
||||||
|
{
|
||||||
|
AudioQueueStop(_audioQueue, true);
|
||||||
|
AudioQueueDispose(_audioQueue, true);
|
||||||
|
_audioQueue = nint.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_gcHandle.IsAllocated)
|
||||||
|
{
|
||||||
|
_gcHandle.Free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
102
src/Ryujinx.Audio.Backends.Apple/Native/AudioToolbox.cs
Normal file
102
src/Ryujinx.Audio.Backends.Apple/Native/AudioToolbox.cs
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
namespace Ryujinx.Audio.Backends.Apple.Native
|
||||||
|
{
|
||||||
|
public static partial class AudioToolbox
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct AudioStreamBasicDescription
|
||||||
|
{
|
||||||
|
public double SampleRate;
|
||||||
|
public uint FormatID;
|
||||||
|
public uint FormatFlags;
|
||||||
|
public uint BytesPerPacket;
|
||||||
|
public uint FramesPerPacket;
|
||||||
|
public uint BytesPerFrame;
|
||||||
|
public uint ChannelsPerFrame;
|
||||||
|
public uint BitsPerChannel;
|
||||||
|
public uint Reserved;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct AudioChannelLayout
|
||||||
|
{
|
||||||
|
public uint AudioChannelLayoutTag;
|
||||||
|
public uint AudioChannelBitmap;
|
||||||
|
public uint NumberChannelDescriptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal const uint kAudioFormatLinearPCM = 0x6C70636D;
|
||||||
|
internal const uint kAudioQueueProperty_ChannelLayout = 0x6171636c;
|
||||||
|
internal const uint kAudioChannelLayoutTag_MPEG_5_1_A = 0x650006;
|
||||||
|
internal const uint kAudioFormatFlagIsFloat = (1 << 0);
|
||||||
|
internal const uint kAudioFormatFlagIsSignedInteger = (1 << 2);
|
||||||
|
internal const uint kAudioFormatFlagIsPacked = (1 << 3);
|
||||||
|
internal const uint kAudioFormatFlagIsBigEndian = (1 << 1);
|
||||||
|
internal const uint kAudioFormatFlagIsAlignedHigh = (1 << 4);
|
||||||
|
internal const uint kAudioFormatFlagIsNonInterleaved = (1 << 5);
|
||||||
|
|
||||||
|
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||||
|
internal static partial int AudioQueueNewOutput(
|
||||||
|
ref AudioStreamBasicDescription format,
|
||||||
|
nint callback,
|
||||||
|
nint userData,
|
||||||
|
nint callbackRunLoop,
|
||||||
|
nint callbackRunLoopMode,
|
||||||
|
uint flags,
|
||||||
|
out nint audioQueue);
|
||||||
|
|
||||||
|
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||||
|
internal static partial int AudioQueueSetProperty(
|
||||||
|
nint audioQueue,
|
||||||
|
uint propertyID,
|
||||||
|
ref AudioChannelLayout layout,
|
||||||
|
uint layoutSize);
|
||||||
|
|
||||||
|
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||||
|
internal static partial int AudioQueueDispose(nint audioQueue, [MarshalAs(UnmanagedType.I1)] bool immediate);
|
||||||
|
|
||||||
|
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||||
|
internal static partial int AudioQueueAllocateBuffer(
|
||||||
|
nint audioQueue,
|
||||||
|
uint bufferByteSize,
|
||||||
|
out nint buffer);
|
||||||
|
|
||||||
|
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||||
|
internal static partial int AudioQueueStart(nint audioQueue, nint startTime);
|
||||||
|
|
||||||
|
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||||
|
internal static partial int AudioQueuePause(nint audioQueue);
|
||||||
|
|
||||||
|
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||||
|
internal static partial int AudioQueueStop(nint audioQueue, [MarshalAs(UnmanagedType.I1)] bool immediate);
|
||||||
|
|
||||||
|
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||||
|
internal static partial int AudioQueueSetParameter(
|
||||||
|
nint audioQueue,
|
||||||
|
uint parameterID,
|
||||||
|
float value);
|
||||||
|
|
||||||
|
[LibraryImport("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox")]
|
||||||
|
internal static partial int AudioQueueEnqueueBuffer(
|
||||||
|
nint audioQueue,
|
||||||
|
nint buffer,
|
||||||
|
uint numPacketDescs,
|
||||||
|
nint packetDescs);
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct AudioQueueBuffer
|
||||||
|
{
|
||||||
|
public uint AudioDataBytesCapacity;
|
||||||
|
public nint AudioData;
|
||||||
|
public uint AudioDataByteSize;
|
||||||
|
public nint UserData;
|
||||||
|
public uint PacketDescriptionCapacity;
|
||||||
|
public nint PacketDescriptions;
|
||||||
|
public uint PacketDescriptionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal const uint kAudioQueueParam_Volume = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ryujinx.Audio\Ryujinx.Audio.csproj" />
|
||||||
|
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -10,7 +10,8 @@ using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Backends.OpenAL
|
namespace Ryujinx.Audio.Backends.OpenAL
|
||||||
{
|
{
|
||||||
public class OpenALHardwareDeviceDriver : IHardwareDeviceDriver
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public sealed class OpenALHardwareDeviceDriver : IHardwareDeviceDriver
|
||||||
{
|
{
|
||||||
private readonly ALDevice _device;
|
private readonly ALDevice _device;
|
||||||
private readonly ALContext _context;
|
private readonly ALContext _context;
|
||||||
|
|
@ -148,7 +149,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Backends.OpenAL
|
namespace Ryujinx.Audio.Backends.OpenAL
|
||||||
{
|
{
|
||||||
class OpenALHardwareDeviceSession : HardwareDeviceSessionOutputBase
|
// ReSharper disable once InconsistentNaming
|
||||||
|
sealed class OpenALHardwareDeviceSession : HardwareDeviceSessionOutputBase
|
||||||
{
|
{
|
||||||
private readonly OpenALHardwareDeviceDriver _driver;
|
private readonly OpenALHardwareDeviceDriver _driver;
|
||||||
private readonly int _sourceId;
|
private readonly int _sourceId;
|
||||||
|
|
@ -190,7 +191,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing && _driver.Unregister(this))
|
if (disposing && _driver.Unregister(this))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Ryujinx.Audio.Backends.SDL3
|
||||||
|
|
||||||
using unsafe SDL_AudioStreamCallbackPointer = delegate* unmanaged[Cdecl]<nint, SDL_AudioStream*, int, int, void>;
|
using unsafe SDL_AudioStreamCallbackPointer = delegate* unmanaged[Cdecl]<nint, SDL_AudioStream*, int, int, void>;
|
||||||
|
|
||||||
public class SDL3HardwareDeviceDriver : IHardwareDeviceDriver
|
public sealed class SDL3HardwareDeviceDriver : IHardwareDeviceDriver
|
||||||
{
|
{
|
||||||
private readonly ManualResetEvent _updateRequiredEvent;
|
private readonly ManualResetEvent _updateRequiredEvent;
|
||||||
private readonly ManualResetEvent _pauseEvent;
|
private readonly ManualResetEvent _pauseEvent;
|
||||||
|
|
@ -162,7 +162,7 @@ namespace Ryujinx.Audio.Backends.SDL3
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,7 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Backends.SDL3
|
namespace Ryujinx.Audio.Backends.SDL3
|
||||||
{
|
{
|
||||||
|
sealed unsafe class SDL3HardwareDeviceSession : HardwareDeviceSessionOutputBase
|
||||||
|
|
||||||
|
|
||||||
unsafe class SDL3HardwareDeviceSession : HardwareDeviceSessionOutputBase
|
|
||||||
{
|
{
|
||||||
private readonly SDL3HardwareDeviceDriver _driver;
|
private readonly SDL3HardwareDeviceDriver _driver;
|
||||||
private readonly ConcurrentQueue<SDL3AudioBuffer> _queuedBuffers;
|
private readonly ConcurrentQueue<SDL3AudioBuffer> _queuedBuffers;
|
||||||
|
|
@ -226,7 +223,7 @@ namespace Ryujinx.Audio.Backends.SDL3
|
||||||
return driverBuffer.DriverIdentifier != buffer.DataPointer;
|
return driverBuffer.DriverIdentifier != buffer.DataPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing && _driver.Unregister(this))
|
if (disposing && _driver.Unregister(this))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ namespace Ryujinx.Audio.Backends.SoundIo.Native
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
int* frameCountPtr = &nativeFrameCount;
|
int* frameCountPtr = &nativeFrameCount;
|
||||||
IntPtr* arenasPtr = &arenas;
|
nint* arenasPtr = &arenas;
|
||||||
CheckError(soundio_outstream_begin_write(_context, (nint)arenasPtr, (nint)frameCountPtr));
|
CheckError(soundio_outstream_begin_write(_context, (nint)arenasPtr, (nint)frameCountPtr));
|
||||||
|
|
||||||
frameCount = *frameCountPtr;
|
frameCount = *frameCountPtr;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Backends.SoundIo
|
namespace Ryujinx.Audio.Backends.SoundIo
|
||||||
{
|
{
|
||||||
public class SoundIoHardwareDeviceDriver : IHardwareDeviceDriver
|
public sealed class SoundIoHardwareDeviceDriver : IHardwareDeviceDriver
|
||||||
{
|
{
|
||||||
private readonly SoundIoContext _audioContext;
|
private readonly SoundIoContext _audioContext;
|
||||||
private readonly SoundIoDeviceContext _audioDevice;
|
private readonly SoundIoDeviceContext _audioDevice;
|
||||||
|
|
@ -227,7 +227,7 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ using static Ryujinx.Audio.Backends.SoundIo.Native.SoundIo;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Backends.SoundIo
|
namespace Ryujinx.Audio.Backends.SoundIo
|
||||||
{
|
{
|
||||||
class SoundIoHardwareDeviceSession : HardwareDeviceSessionOutputBase
|
sealed class SoundIoHardwareDeviceSession : HardwareDeviceSessionOutputBase
|
||||||
{
|
{
|
||||||
private readonly SoundIoHardwareDeviceDriver _driver;
|
private readonly SoundIoHardwareDeviceDriver _driver;
|
||||||
private readonly ConcurrentQueue<SoundIoAudioBuffer> _queuedBuffers;
|
private readonly ConcurrentQueue<SoundIoAudioBuffer> _queuedBuffers;
|
||||||
|
|
@ -428,7 +428,7 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing && _driver.Unregister(this))
|
if (disposing && _driver.Unregister(this))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Ryujinx.Audio.Renderer.Common
|
||||||
public uint MixesSize;
|
public uint MixesSize;
|
||||||
public uint SinksSize;
|
public uint SinksSize;
|
||||||
public uint PerformanceBufferSize;
|
public uint PerformanceBufferSize;
|
||||||
public uint Unknown24;
|
public uint SplitterSize;
|
||||||
public uint RenderInfoSize;
|
public uint RenderInfoSize;
|
||||||
|
|
||||||
#pragma warning disable IDE0051, CS0169 // Remove unused field
|
#pragma warning disable IDE0051, CS0169 // Remove unused field
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,11 @@ namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||||
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Array6<byte> Output;
|
public Array6<byte> Output;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved/unused.
|
||||||
|
/// </summary>
|
||||||
|
private readonly uint _padding;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Biquad filter numerator (b0, b1, b2).
|
/// Biquad filter numerator (b0, b1, b2).
|
||||||
|
|
|
||||||
|
|
@ -433,8 +433,12 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
|
|
||||||
public ResultCode UpdateSplitter(SplitterContext context)
|
public ResultCode UpdateSplitter(SplitterContext context)
|
||||||
{
|
{
|
||||||
|
long initialInputConsumed = _inputReader.Consumed;
|
||||||
|
|
||||||
if (context.Update(ref _inputReader))
|
if (context.Update(ref _inputReader))
|
||||||
{
|
{
|
||||||
|
_inputReader.SetConsumed(initialInputConsumed + _inputHeader.SplitterSize);
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,7 @@ namespace Ryujinx.BuildValidationTasks
|
||||||
{
|
{
|
||||||
static readonly JsonSerializerOptions _jsonOptions = new()
|
static readonly JsonSerializerOptions _jsonOptions = new()
|
||||||
{
|
{
|
||||||
WriteIndented = true,
|
WriteIndented = true, NewLine = "\n", Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||||
NewLine = "\n",
|
|
||||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public LocalesValidationTask() { }
|
public LocalesValidationTask() { }
|
||||||
|
|
@ -22,77 +20,116 @@ namespace Ryujinx.BuildValidationTasks
|
||||||
{
|
{
|
||||||
Console.WriteLine("Running Locale Validation Task...");
|
Console.WriteLine("Running Locale Validation Task...");
|
||||||
|
|
||||||
string path = projectPath + "assets/locales.json";
|
bool encounteredIssue = false;
|
||||||
|
string langPath = projectPath + "assets/Languages.json";
|
||||||
string data;
|
string data;
|
||||||
|
|
||||||
using (StreamReader sr = new(path))
|
using (StreamReader sr = new(langPath))
|
||||||
{
|
{
|
||||||
data = sr.ReadToEnd();
|
data = sr.ReadToEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalesJson json;
|
|
||||||
|
|
||||||
if (isGitRunner && data.Contains("\r\n"))
|
if (isGitRunner && data.Contains("\r\n"))
|
||||||
throw new FormatException("locales.json is using CRLF line endings! It should be using LF line endings, rebuild locally to fix...");
|
throw new FormatException("Languages.json is using CRLF line endings! It should be using LF line endings, rebuild locally to fix...");
|
||||||
|
|
||||||
|
LanguagesJson langJson;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
json = JsonSerializer.Deserialize<LocalesJson>(data);
|
langJson = JsonSerializer.Deserialize<LanguagesJson>(data);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (JsonException e)
|
catch (JsonException e)
|
||||||
{
|
{
|
||||||
throw new JsonException(e.Message); //shorter and easier stacktrace
|
throw new JsonException(e.Message); //shorter and easier stacktrace
|
||||||
}
|
}
|
||||||
|
|
||||||
bool encounteredIssue = false;
|
foreach ((string code, string lang) in langJson.Languages)
|
||||||
|
|
||||||
for (int i = 0; i < json.Locales.Count; i++)
|
|
||||||
{
|
{
|
||||||
LocalesEntry locale = json.Locales[i];
|
if (string.IsNullOrEmpty(lang))
|
||||||
|
|
||||||
foreach (string langCode in json.Languages.Where(lang => !locale.Translations.ContainsKey(lang)))
|
|
||||||
{
|
{
|
||||||
encounteredIssue = true;
|
throw new JsonException($"{code} language name missing!");
|
||||||
|
|
||||||
if (!isGitRunner)
|
|
||||||
{
|
|
||||||
locale.Translations.Add(langCode, string.Empty);
|
|
||||||
Console.WriteLine($"Added '{langCode}' to Locale '{locale.ID}'");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Missing '{langCode}' in Locale '{locale.ID}'!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string langCode in json.Languages.Where(lang => locale.Translations.ContainsKey(lang) && lang != "en_US" && locale.Translations[lang] == locale.Translations["en_US"]))
|
|
||||||
{
|
|
||||||
encounteredIssue = true;
|
|
||||||
|
|
||||||
if (!isGitRunner)
|
|
||||||
{
|
|
||||||
locale.Translations[langCode] = string.Empty;
|
|
||||||
Console.WriteLine($"Lanugage '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'! Resetting it...");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Lanugage '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
|
|
||||||
json.Locales[i] = locale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isGitRunner && encounteredIssue)
|
string folderPath = projectPath + "assets/Locales/";
|
||||||
throw new JsonException("1 or more locales are invalid! Rebuild locally to fix...");
|
|
||||||
|
|
||||||
string jsonString = JsonSerializer.Serialize(json, _jsonOptions);
|
string[] paths = Directory.GetFiles(folderPath, "*.json", SearchOption.AllDirectories);
|
||||||
|
|
||||||
using (StreamWriter sw = new(path))
|
foreach (string path in paths)
|
||||||
{
|
{
|
||||||
sw.Write(jsonString);
|
using (StreamReader sr = new(path))
|
||||||
|
{
|
||||||
|
data = sr.ReadToEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isGitRunner && data.Contains("\r\n"))
|
||||||
|
throw new FormatException($"{Path.GetFileName(path)} is using CRLF line endings! It should be using LF line endings, rebuild locally to fix...");
|
||||||
|
|
||||||
|
LocalesJson json;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
json = JsonSerializer.Deserialize<LocalesJson>(data);
|
||||||
|
}
|
||||||
|
catch (JsonException e)
|
||||||
|
{
|
||||||
|
throw new JsonException(e.Message); //shorter and easier stacktrace
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < json.Locales.Count; i++)
|
||||||
|
{
|
||||||
|
LocalesEntry locale = json.Locales[i];
|
||||||
|
|
||||||
|
foreach (string langCode in
|
||||||
|
langJson.Languages.Keys.Where(lang => !locale.Translations.ContainsKey(lang)))
|
||||||
|
{
|
||||||
|
encounteredIssue = true;
|
||||||
|
|
||||||
|
if (!isGitRunner)
|
||||||
|
{
|
||||||
|
locale.Translations.Add(langCode, string.Empty);
|
||||||
|
Console.WriteLine($"Added '{langCode}' to Locale '{locale.ID}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Missing '{langCode}' in Locale '{locale.ID}'!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string langCode in langJson.Languages.Keys.Where(lang =>
|
||||||
|
locale.Translations.ContainsKey(lang) && lang != "en_US" &&
|
||||||
|
locale.Translations[lang] == locale.Translations["en_US"]))
|
||||||
|
{
|
||||||
|
encounteredIssue = true;
|
||||||
|
|
||||||
|
if (!isGitRunner)
|
||||||
|
{
|
||||||
|
locale.Translations[langCode] = string.Empty;
|
||||||
|
Console.WriteLine(
|
||||||
|
$"Language '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'! Resetting it...");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(
|
||||||
|
$"Language '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
locale.Translations = locale.Translations.OrderBy(pair => pair.Key)
|
||||||
|
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||||
|
json.Locales[i] = locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isGitRunner && encounteredIssue)
|
||||||
|
throw new JsonException("1 or more locales are invalid! Rebuild locally to fix...");
|
||||||
|
|
||||||
|
string jsonString = JsonSerializer.Serialize(json, _jsonOptions);
|
||||||
|
|
||||||
|
using (StreamWriter sw = new(path))
|
||||||
|
{
|
||||||
|
sw.Write(jsonString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Finished Locale Validation Task!");
|
Console.WriteLine("Finished Locale Validation Task!");
|
||||||
|
|
@ -100,10 +137,13 @@ namespace Ryujinx.BuildValidationTasks
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LanguagesJson
|
||||||
|
{
|
||||||
|
public Dictionary<string, string> Languages { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
struct LocalesJson
|
struct LocalesJson
|
||||||
{
|
{
|
||||||
public Dictionary<string, string> Info { get; set; }
|
|
||||||
public List<string> Languages { get; set; }
|
|
||||||
public List<LocalesEntry> Locales { get; set; }
|
public List<LocalesEntry> Locales { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration
|
namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<AntiAliasing>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<AntiAliasing>))]
|
||||||
public enum AntiAliasing
|
public enum AntiAliasing
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration
|
namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<AspectRatio>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<AspectRatio>))]
|
||||||
public enum AspectRatio
|
public enum AspectRatio
|
||||||
{
|
{
|
||||||
Fixed4x3,
|
Fixed4x3,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration
|
namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<BackendThreading>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<BackendThreading>))]
|
||||||
public enum BackendThreading
|
public enum BackendThreading
|
||||||
{
|
{
|
||||||
Auto,
|
Auto,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration
|
namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<GraphicsBackend>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<GraphicsBackend>))]
|
||||||
public enum GraphicsBackend
|
public enum GraphicsBackend
|
||||||
{
|
{
|
||||||
Vulkan,
|
Vulkan,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration
|
namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<GraphicsDebugLevel>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<GraphicsDebugLevel>))]
|
||||||
public enum GraphicsDebugLevel
|
public enum GraphicsDebugLevel
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration.Hid.Controller
|
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<GamepadInputId>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<GamepadInputId>))]
|
||||||
public enum GamepadInputId : byte
|
public enum GamepadInputId : byte
|
||||||
{
|
{
|
||||||
Unbound,
|
Unbound,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<MotionInputBackendType>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<MotionInputBackendType>))]
|
||||||
public enum MotionInputBackendType : byte
|
public enum MotionInputBackendType : byte
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration.Hid.Controller
|
namespace Ryujinx.Common.Configuration.Hid.Controller
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<StickInputId>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<StickInputId>))]
|
||||||
public enum StickInputId : byte
|
public enum StickInputId : byte
|
||||||
{
|
{
|
||||||
Unbound,
|
Unbound,
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
|
|
||||||
Count,
|
Count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
|
@ -6,7 +5,7 @@ namespace Ryujinx.Common.Configuration.Hid
|
||||||
{
|
{
|
||||||
// This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical
|
// This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical
|
||||||
[Flags]
|
[Flags]
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<ControllerType>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<ControllerType>))]
|
||||||
public enum ControllerType
|
public enum ControllerType
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration.Hid
|
namespace Ryujinx.Common.Configuration.Hid
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<InputBackendType>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<InputBackendType>))]
|
||||||
public enum InputBackendType
|
public enum InputBackendType
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration.Hid
|
namespace Ryujinx.Common.Configuration.Hid
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<Key>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<Key>))]
|
||||||
public enum Key
|
public enum Key
|
||||||
{
|
{
|
||||||
Unknown,
|
Unknown,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration.Hid
|
namespace Ryujinx.Common.Configuration.Hid
|
||||||
{
|
{
|
||||||
// This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical
|
// This enum was duplicated from Ryujinx.HLE.HOS.Services.Hid.PlayerIndex and should be kept identical
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<PlayerIndex>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<PlayerIndex>))]
|
||||||
public enum PlayerIndex
|
public enum PlayerIndex
|
||||||
{
|
{
|
||||||
Player1 = 0,
|
Player1 = 0,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration
|
namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<MemoryManagerMode>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<MemoryManagerMode>))]
|
||||||
public enum MemoryManagerMode : byte
|
public enum MemoryManagerMode : byte
|
||||||
{
|
{
|
||||||
SoftwarePageTable,
|
SoftwarePageTable,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration
|
namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<ScalingFilter>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<ScalingFilter>))]
|
||||||
public enum ScalingFilter
|
public enum ScalingFilter
|
||||||
{
|
{
|
||||||
Bilinear,
|
Bilinear,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Logging
|
namespace Ryujinx.Common.Logging
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<LogClass>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<LogClass>))]
|
||||||
public enum LogClass
|
public enum LogClass
|
||||||
{
|
{
|
||||||
Application,
|
Application,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
using Ryujinx.Common.Utilities;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Logging
|
namespace Ryujinx.Common.Logging
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(TypedStringEnumConverter<LogLevel>))]
|
[JsonConverter(typeof(JsonStringEnumConverter<LogLevel>))]
|
||||||
public enum LogLevel
|
public enum LogLevel
|
||||||
{
|
{
|
||||||
Debug,
|
Debug,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ namespace Ryujinx.Common.Memory
|
||||||
{
|
{
|
||||||
private static readonly RecyclableMemoryStreamManager _shared = new();
|
private static readonly RecyclableMemoryStreamManager _shared = new();
|
||||||
|
|
||||||
|
private static readonly ObjectPool<RecyclableMemoryStream> _streamPool =
|
||||||
|
new(() => new RecyclableMemoryStream(_shared, Guid.NewGuid(), null, 0));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// We don't expose the <c>RecyclableMemoryStreamManager</c> directly because version 2.x
|
/// We don't expose the <c>RecyclableMemoryStreamManager</c> directly because version 2.x
|
||||||
/// returns them as <c>MemoryStream</c>. This Shared class is here to a) offer only the GetStream() versions we use
|
/// returns them as <c>MemoryStream</c>. This Shared class is here to a) offer only the GetStream() versions we use
|
||||||
|
|
@ -19,7 +22,12 @@ namespace Ryujinx.Common.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A <c>RecyclableMemoryStream</c></returns>
|
/// <returns>A <c>RecyclableMemoryStream</c></returns>
|
||||||
public static RecyclableMemoryStream GetStream()
|
public static RecyclableMemoryStream GetStream()
|
||||||
=> new(_shared);
|
{
|
||||||
|
RecyclableMemoryStream stream = _streamPool.Allocate();
|
||||||
|
stream.SetLength(0);
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieve a new <c>MemoryStream</c> object with the contents copied from the provided
|
/// Retrieve a new <c>MemoryStream</c> object with the contents copied from the provided
|
||||||
|
|
@ -55,7 +63,8 @@ namespace Ryujinx.Common.Memory
|
||||||
RecyclableMemoryStream stream = null;
|
RecyclableMemoryStream stream = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
stream = new RecyclableMemoryStream(_shared, id, tag, buffer.Length);
|
stream = _streamPool.Allocate();
|
||||||
|
stream.SetLength(0);
|
||||||
stream.Write(buffer);
|
stream.Write(buffer);
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
return stream;
|
return stream;
|
||||||
|
|
@ -83,7 +92,8 @@ namespace Ryujinx.Common.Memory
|
||||||
RecyclableMemoryStream stream = null;
|
RecyclableMemoryStream stream = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
stream = new RecyclableMemoryStream(_shared, id, tag, count);
|
stream = _streamPool.Allocate();
|
||||||
|
stream.SetLength(0);
|
||||||
stream.Write(buffer, offset, count);
|
stream.Write(buffer, offset, count);
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
return stream;
|
return stream;
|
||||||
|
|
@ -94,6 +104,11 @@ namespace Ryujinx.Common.Memory
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ReleaseStream(RecyclableMemoryStream stream)
|
||||||
|
{
|
||||||
|
_streamPool.Release(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
public static string GetChangelogUrl(Version currentVersion, Version newVersion) =>
|
public static string GetChangelogUrl(Version currentVersion, Version newVersion) =>
|
||||||
IsCanaryBuild
|
IsCanaryBuild
|
||||||
? $"https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-{currentVersion}...Canary-{newVersion}"
|
? $"https://git.ryujinx.app/projects/Ryubing/compare/Canary-{currentVersion}...Canary-{newVersion}"
|
||||||
: $"https://git.ryujinx.app/ryubing/ryujinx/-/releases/{newVersion}";
|
: $"https://git.ryujinx.app/projects/Ryubing/releases/tag/{newVersion}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" />
|
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" />
|
||||||
<PackageReference Include="MsgPack.Cli" />
|
<PackageReference Include="MsgPack.Cli" />
|
||||||
<PackageReference Include="System.Management" />
|
|
||||||
<PackageReference Include="Humanizer" />
|
<PackageReference Include="Humanizer" />
|
||||||
<PackageReference Include="Gommon" />
|
<PackageReference Include="Gommon" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,12 @@ namespace Ryujinx.Common
|
||||||
|
|
||||||
public const string AmiiboTagsUrl = "https://raw.githubusercontent.com/Ryubing/Nfc/refs/heads/main/tags.json";
|
public const string AmiiboTagsUrl = "https://raw.githubusercontent.com/Ryubing/Nfc/refs/heads/main/tags.json";
|
||||||
|
|
||||||
public const string FaqWikiUrl = "https://git.ryujinx.app/ryubing/ryujinx/-/wikis/FAQ-&-Troubleshooting";
|
public const string FaqWikiUrl = "https://git.ryujinx.app/projects/Ryubing/wiki/FAQ-%26-Troubleshooting";
|
||||||
|
|
||||||
public const string SetupGuideWikiUrl =
|
public const string SetupGuideWikiUrl =
|
||||||
"https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Setup-&-Configuration-Guide";
|
"https://git.ryujinx.app/projects/Ryubing/wiki/Setup-%26-Configuration-Guide";
|
||||||
|
|
||||||
public const string MultiplayerWikiUrl =
|
public const string MultiplayerWikiUrl =
|
||||||
"https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Multiplayer-(LDN-Local-Wireless)-Guide";
|
"https://git.ryujinx.app/projects/Ryubing/wiki/Multiplayer-(LDN-Local-Wireless)-Guide";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,7 @@ namespace Ryujinx.Common
|
||||||
"01001b300b9be000", // Diablo III: Eternal Collection
|
"01001b300b9be000", // Diablo III: Eternal Collection
|
||||||
"010027400cdc6000", // Divinity Original 2 - Definitive Edition
|
"010027400cdc6000", // Divinity Original 2 - Definitive Edition
|
||||||
"01008c8012920000", // Dying Light Platinum Edition
|
"01008c8012920000", // Dying Light Platinum Edition
|
||||||
|
"0100d11013e6a000", // Eschatos
|
||||||
"01001cc01b2d4000", // Goat Simulator 3
|
"01001cc01b2d4000", // Goat Simulator 3
|
||||||
"01003620068ea000", // Hand of Fate 2
|
"01003620068ea000", // Hand of Fate 2
|
||||||
"0100f7e00c70e000", // Hogwarts Legacy
|
"0100f7e00c70e000", // Hogwarts Legacy
|
||||||
|
|
@ -193,9 +194,15 @@ namespace Ryujinx.Common
|
||||||
"0100d71004694000", // Minecraft
|
"0100d71004694000", // Minecraft
|
||||||
"01007430037f6000", // Monopoly
|
"01007430037f6000", // Monopoly
|
||||||
"0100853015e86000", // No Man's Sky
|
"0100853015e86000", // No Man's Sky
|
||||||
|
"0100f85014ed0000", // No More Heroes
|
||||||
|
"0100463014ed4000", // No More Heroes 2
|
||||||
|
"0100e570094e8000", // Owlboy
|
||||||
"01007bb017812000", // Portal
|
"01007bb017812000", // Portal
|
||||||
"0100abd01785c000", // Portal 2
|
"0100abd01785c000", // Portal 2
|
||||||
|
"01009f100bc52000", // Psikyo Collection 1
|
||||||
|
"01009d400c4a8000", // Psikyo Collection 2
|
||||||
"01008e200c5c2000", // Muse Dash
|
"01008e200c5c2000", // Muse Dash
|
||||||
|
"01005ff002e2a000", // Rayman Legends
|
||||||
"01007820196a6000", // Red Dead Redemption
|
"01007820196a6000", // Red Dead Redemption
|
||||||
"0100e8300a67a000", // Risk
|
"0100e8300a67a000", // Risk
|
||||||
"01002f7013224000", // Rune Factory 5
|
"01002f7013224000", // Rune Factory 5
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ namespace Ryujinx.Common
|
||||||
public static string[] GetAllAvailableResources(string path, string ext = "")
|
public static string[] GetAllAvailableResources(string path, string ext = "")
|
||||||
{
|
{
|
||||||
return ResolveManifestPath(path).Item1.GetManifestResourceNames()
|
return ResolveManifestPath(path).Item1.GetManifestResourceNames()
|
||||||
.Where(r => r.EndsWith(ext))
|
.Where(r => r.StartsWith(path.Replace('/', '.')) && r.EndsWith(ext))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,30 @@ namespace Ryujinx.Common.Utilities
|
||||||
Debug.Assert(res != -1);
|
Debug.Assert(res != -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "dumpable" attribute of the calling process
|
||||||
|
private const int PR_GET_DUMPABLE = 3;
|
||||||
|
private const int PR_SET_DUMPABLE = 4;
|
||||||
|
|
||||||
|
[LibraryImport("libc", SetLastError = true)]
|
||||||
|
private static partial int prctl(int option, int arg2);
|
||||||
|
|
||||||
|
public static void SetCoreDumpable(bool dumpable)
|
||||||
|
{
|
||||||
|
if (OperatingSystem.IsLinux())
|
||||||
|
{
|
||||||
|
int dumpableInt = dumpable ? 1 : 0;
|
||||||
|
int result = prctl(PR_SET_DUMPABLE, dumpableInt);
|
||||||
|
Debug.Assert(result == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the below line to display dumpable status in the console:
|
||||||
|
// Console.WriteLine($"{OsUtils.IsCoreDumpable()}");
|
||||||
|
public static bool IsCoreDumpable()
|
||||||
|
{
|
||||||
|
int result = prctl(PR_GET_DUMPABLE, 0);
|
||||||
|
return result == 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
#nullable enable
|
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using System;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace Ryujinx.Common.Utilities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies that value of <see cref="TEnum"/> will be serialized as string in JSONs
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Trimming friendly alternative to <see cref="JsonStringEnumConverter"/>.
|
|
||||||
/// Get rid of this converter if dotnet supports similar functionality out of the box.
|
|
||||||
/// </remarks>
|
|
||||||
/// <typeparam name="TEnum">Type of enum to serialize</typeparam>
|
|
||||||
public sealed class TypedStringEnumConverter<TEnum> : JsonConverter<TEnum> where TEnum : struct, Enum
|
|
||||||
{
|
|
||||||
public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
|
||||||
{
|
|
||||||
string? enumValue = reader.GetString();
|
|
||||||
|
|
||||||
if (Enum.TryParse(enumValue, out TEnum value))
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Warning?.Print(LogClass.Configuration, $"Failed to parse enum value \"{enumValue}\" for {typeof(TEnum)}, using default \"{default(TEnum)}\"");
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options)
|
|
||||||
{
|
|
||||||
writer.WriteStringValue(value.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -30,9 +30,9 @@ namespace ARMeilleure.Common
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base address for the page.
|
/// Base address for the page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly IntPtr Address;
|
public readonly nint Address;
|
||||||
|
|
||||||
public AddressTablePage(bool isSparse, IntPtr address)
|
public AddressTablePage(bool isSparse, nint address)
|
||||||
{
|
{
|
||||||
IsSparse = isSparse;
|
IsSparse = isSparse;
|
||||||
Address = address;
|
Address = address;
|
||||||
|
|
@ -47,20 +47,20 @@ namespace ARMeilleure.Common
|
||||||
public readonly SparseMemoryBlock Block;
|
public readonly SparseMemoryBlock Block;
|
||||||
private readonly TrackingEventDelegate _trackingEvent;
|
private readonly TrackingEventDelegate _trackingEvent;
|
||||||
|
|
||||||
public TableSparseBlock(ulong size, Action<IntPtr> ensureMapped, PageInitDelegate pageInit)
|
public TableSparseBlock(ulong size, Action<nint> ensureMapped, PageInitDelegate pageInit)
|
||||||
{
|
{
|
||||||
SparseMemoryBlock block = new(size, pageInit, null);
|
SparseMemoryBlock block = new(size, pageInit, null);
|
||||||
|
|
||||||
_trackingEvent = (address, size, write) =>
|
_trackingEvent = (address, size, write) =>
|
||||||
{
|
{
|
||||||
ulong pointer = (ulong)block.Block.Pointer + address;
|
ulong pointer = (ulong)block.Block.Pointer + address;
|
||||||
ensureMapped((IntPtr)pointer);
|
ensureMapped((nint)pointer);
|
||||||
return pointer;
|
return pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool added = NativeSignalHandler.AddTrackedRegion(
|
bool added = NativeSignalHandler.AddTrackedRegion(
|
||||||
(nuint)block.Block.Pointer,
|
(nuint)block.Block.Pointer,
|
||||||
(nuint)(block.Block.Pointer + (IntPtr)block.Block.Size),
|
(nuint)(block.Block.Pointer + (nint)block.Block.Size),
|
||||||
Marshal.GetFunctionPointerForDelegate(_trackingEvent));
|
Marshal.GetFunctionPointerForDelegate(_trackingEvent));
|
||||||
|
|
||||||
if (!added)
|
if (!added)
|
||||||
|
|
@ -116,7 +116,7 @@ namespace ARMeilleure.Common
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IntPtr Base
|
public nint Base
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -124,7 +124,7 @@ namespace ARMeilleure.Common
|
||||||
|
|
||||||
lock (_pages)
|
lock (_pages)
|
||||||
{
|
{
|
||||||
return (IntPtr)GetRootPage();
|
return (nint)GetRootPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +240,7 @@ namespace ARMeilleure.Common
|
||||||
|
|
||||||
long index = Levels[^1].GetValue(address);
|
long index = Levels[^1].GetValue(address);
|
||||||
|
|
||||||
EnsureMapped((IntPtr)(page + index));
|
EnsureMapped((nint)(page + index));
|
||||||
|
|
||||||
return ref page[index];
|
return ref page[index];
|
||||||
}
|
}
|
||||||
|
|
@ -284,7 +284,7 @@ namespace ARMeilleure.Common
|
||||||
/// Ensure the given pointer is mapped in any overlapping sparse reservations.
|
/// Ensure the given pointer is mapped in any overlapping sparse reservations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ptr">Pointer to be mapped</param>
|
/// <param name="ptr">Pointer to be mapped</param>
|
||||||
private void EnsureMapped(IntPtr ptr)
|
private void EnsureMapped(nint ptr)
|
||||||
{
|
{
|
||||||
if (Sparse)
|
if (Sparse)
|
||||||
{
|
{
|
||||||
|
|
@ -299,7 +299,7 @@ namespace ARMeilleure.Common
|
||||||
{
|
{
|
||||||
SparseMemoryBlock sparse = reserved.Block;
|
SparseMemoryBlock sparse = reserved.Block;
|
||||||
|
|
||||||
if (ptr >= sparse.Block.Pointer && ptr < sparse.Block.Pointer + (IntPtr)sparse.Block.Size)
|
if (ptr >= sparse.Block.Pointer && ptr < sparse.Block.Pointer + (nint)sparse.Block.Size)
|
||||||
{
|
{
|
||||||
sparse.EnsureMapped((ulong)(ptr - sparse.Block.Pointer));
|
sparse.EnsureMapped((ulong)(ptr - sparse.Block.Pointer));
|
||||||
|
|
||||||
|
|
@ -319,15 +319,15 @@ namespace ARMeilleure.Common
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="level">Level to get the fill value for</param>
|
/// <param name="level">Level to get the fill value for</param>
|
||||||
/// <returns>The fill value</returns>
|
/// <returns>The fill value</returns>
|
||||||
private IntPtr GetFillValue(int level)
|
private nint GetFillValue(int level)
|
||||||
{
|
{
|
||||||
if (_fillBottomLevel != null && level == Levels.Length - 2)
|
if (_fillBottomLevel != null && level == Levels.Length - 2)
|
||||||
{
|
{
|
||||||
return (IntPtr)_fillBottomLevelPtr;
|
return (nint)_fillBottomLevelPtr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return IntPtr.Zero;
|
return nint.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -379,7 +379,7 @@ namespace ARMeilleure.Common
|
||||||
/// <param name="fill">Fill value</param>
|
/// <param name="fill">Fill value</param>
|
||||||
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword="false"/></param>
|
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword="false"/></param>
|
||||||
/// <returns>Allocated block</returns>
|
/// <returns>Allocated block</returns>
|
||||||
private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
|
private nint Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
|
||||||
{
|
{
|
||||||
int size = sizeof(T) * length;
|
int size = sizeof(T) * length;
|
||||||
|
|
||||||
|
|
@ -405,7 +405,7 @@ namespace ARMeilleure.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
page = new AddressTablePage(true, block.Block.Pointer + (IntPtr)_sparseReservedOffset);
|
page = new AddressTablePage(true, block.Block.Pointer + (nint)_sparseReservedOffset);
|
||||||
|
|
||||||
_sparseReservedOffset += (ulong)size;
|
_sparseReservedOffset += (ulong)size;
|
||||||
|
|
||||||
|
|
@ -413,7 +413,7 @@ namespace ARMeilleure.Common
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IntPtr address = (IntPtr)NativeAllocator.Instance.Allocate((uint)size);
|
nint address = (nint)NativeAllocator.Instance.Allocate((uint)size);
|
||||||
page = new AddressTablePage(false, address);
|
page = new AddressTablePage(false, address);
|
||||||
|
|
||||||
Span<T> span = new((void*)page.Address, length);
|
Span<T> span = new((void*)page.Address, length);
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ namespace Ryujinx.Graphics.GAL
|
||||||
void SetRasterizerDiscard(bool discard);
|
void SetRasterizerDiscard(bool discard);
|
||||||
|
|
||||||
void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask);
|
void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask);
|
||||||
void SetRenderTargets(ITexture[] colors, ITexture depthStencil);
|
void SetRenderTargets(Span<ITexture> colors, ITexture depthStencil);
|
||||||
|
|
||||||
void SetScissors(ReadOnlySpan<Rectangle<int>> regions);
|
void SetScissors(ReadOnlySpan<Rectangle<int>> regions);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||||
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
||||||
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||||
|
|
@ -8,11 +9,13 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||||
{
|
{
|
||||||
public static readonly ArrayPool<ITexture> ArrayPool = ArrayPool<ITexture>.Create(512, 50);
|
public static readonly ArrayPool<ITexture> ArrayPool = ArrayPool<ITexture>.Create(512, 50);
|
||||||
public readonly CommandType CommandType => CommandType.SetRenderTargets;
|
public readonly CommandType CommandType => CommandType.SetRenderTargets;
|
||||||
|
private int _colorsCount;
|
||||||
private TableRef<ITexture[]> _colors;
|
private TableRef<ITexture[]> _colors;
|
||||||
private TableRef<ITexture> _depthStencil;
|
private TableRef<ITexture> _depthStencil;
|
||||||
|
|
||||||
public void Set(TableRef<ITexture[]> colors, TableRef<ITexture> depthStencil)
|
public void Set(int colorsCount, TableRef<ITexture[]> colors, TableRef<ITexture> depthStencil)
|
||||||
{
|
{
|
||||||
|
_colorsCount = colorsCount;
|
||||||
_colors = colors;
|
_colors = colors;
|
||||||
_depthStencil = depthStencil;
|
_depthStencil = depthStencil;
|
||||||
}
|
}
|
||||||
|
|
@ -20,16 +23,15 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||||
public static void Run(ref SetRenderTargetsCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
public static void Run(ref SetRenderTargetsCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
{
|
{
|
||||||
ITexture[] colors = command._colors.Get(threaded);
|
ITexture[] colors = command._colors.Get(threaded);
|
||||||
ITexture[] colorsCopy = ArrayPool.Rent(colors.Length);
|
Span<ITexture> colorsSpan = colors.AsSpan(0, command._colorsCount);
|
||||||
|
|
||||||
for (int i = 0; i < colors.Length; i++)
|
for (int i = 0; i < colorsSpan.Length; i++)
|
||||||
{
|
{
|
||||||
colorsCopy[i] = ((ThreadedTexture)colors[i])?.Base;
|
colorsSpan[i] = ((ThreadedTexture)colorsSpan[i])?.Base;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.Pipeline.SetRenderTargets(colorsCopy, command._depthStencil.GetAs<ThreadedTexture>(threaded)?.Base);
|
renderer.Pipeline.SetRenderTargets(colorsSpan, command._depthStencil.GetAs<ThreadedTexture>(threaded)?.Base);
|
||||||
|
|
||||||
ArrayPool.Return(colorsCopy);
|
|
||||||
ArrayPool.Return(colors);
|
ArrayPool.Return(colors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -267,12 +267,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||||
_renderer.QueueCommand();
|
_renderer.QueueCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void SetRenderTargets(ITexture[] colors, ITexture depthStencil)
|
public unsafe void SetRenderTargets(Span<ITexture> colors, ITexture depthStencil)
|
||||||
{
|
{
|
||||||
ITexture[] colorsCopy = SetRenderTargetsCommand.ArrayPool.Rent(colors.Length);
|
ITexture[] colorsCopy = SetRenderTargetsCommand.ArrayPool.Rent(colors.Length);
|
||||||
colors.CopyTo(colorsCopy, 0);
|
colors.CopyTo(colorsCopy.AsSpan());
|
||||||
|
|
||||||
_renderer.New<SetRenderTargetsCommand>()->Set(Ref(colorsCopy), Ref(depthStencil));
|
_renderer.New<SetRenderTargetsCommand>()->Set(colors.Length, Ref(colorsCopy), Ref(depthStencil));
|
||||||
_renderer.QueueCommand();
|
_renderer.QueueCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ThreadedRenderer : IRenderer
|
public class ThreadedRenderer : IRenderer
|
||||||
{
|
{
|
||||||
private const int SpanPoolBytes = 4 * 1024 * 1024;
|
private const int SpanPoolBytes = 8 * 1024 * 1024;
|
||||||
private const int MaxRefsPerCommand = 2;
|
private const int MaxRefsPerCommand = 2;
|
||||||
private const int QueueCount = 10000;
|
private const int QueueCount = 10000;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -404,9 +404,12 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
|
|
||||||
if (force || _pendingSync || (syncPoint && SyncpointActions.Count > 0))
|
if (force || _pendingSync || (syncPoint && SyncpointActions.Count > 0))
|
||||||
{
|
{
|
||||||
foreach (ISyncActionHandler action in SyncActions)
|
for (int i = 0; i < SyncActions.Count; i++)
|
||||||
{
|
{
|
||||||
action.SyncPreAction(syncPoint);
|
if (SyncActions[i].SyncPreAction(syncPoint))
|
||||||
|
{
|
||||||
|
SyncActions.RemoveAt(i--);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (ISyncActionHandler action in SyncpointActions)
|
foreach (ISyncActionHandler action in SyncpointActions)
|
||||||
|
|
|
||||||
|
|
@ -658,7 +658,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
bool canImport = Storage.Info.IsLinear && Storage.Info.Stride >= Storage.Info.Width * Storage.Info.FormatInfo.BytesPerPixel;
|
bool canImport = Storage.Info.IsLinear && Storage.Info.Stride >= Storage.Info.Width * Storage.Info.FormatInfo.BytesPerPixel;
|
||||||
|
|
||||||
IntPtr hostPointer = canImport ? _physicalMemory.GetHostPointer(Storage.Range) : 0;
|
nint hostPointer = canImport ? _physicalMemory.GetHostPointer(Storage.Range) : 0;
|
||||||
|
|
||||||
if (hostPointer != 0 && _context.Renderer.PrepareHostMapping(hostPointer, Storage.Size))
|
if (hostPointer != 0 && _context.Renderer.PrepareHostMapping(hostPointer, Storage.Size))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -411,7 +411,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// flushes often enough, which is determined by the flush balance.
|
/// flushes often enough, which is determined by the flush balance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void SyncPreAction(bool syncpoint)
|
public bool SyncPreAction(bool syncpoint)
|
||||||
{
|
{
|
||||||
if (syncpoint || NextSyncCopies())
|
if (syncpoint || NextSyncCopies())
|
||||||
{
|
{
|
||||||
|
|
@ -421,6 +421,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
_registeredBufferSync = _modifiedSync;
|
_registeredBufferSync = _modifiedSync;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Buffer, used to store vertex and index data, uniform and storage buffers, and others.
|
/// Buffer, used to store vertex and index data, uniform and storage buffers, and others.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class Buffer : INonOverlappingRange, ISyncActionHandler, IDisposable
|
class Buffer : INonOverlappingRange<Buffer>, ISyncActionHandler, IDisposable
|
||||||
{
|
{
|
||||||
private const ulong GranularBufferThreshold = 4096;
|
private const ulong GranularBufferThreshold = 4096;
|
||||||
|
|
||||||
|
|
@ -41,6 +41,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// End address of the buffer in guest memory.
|
/// End address of the buffer in guest memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ulong EndAddress => Address + Size;
|
public ulong EndAddress => Address + Size;
|
||||||
|
|
||||||
|
public Buffer Next { get; set; }
|
||||||
|
public Buffer Previous { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Increments when the buffer is (partially) unmapped or disposed.
|
/// Increments when the buffer is (partially) unmapped or disposed.
|
||||||
|
|
@ -87,6 +90,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
private readonly bool _useGranular;
|
private readonly bool _useGranular;
|
||||||
private bool _syncActionRegistered;
|
private bool _syncActionRegistered;
|
||||||
|
private bool _bufferInherited;
|
||||||
|
|
||||||
private int _referenceCount = 1;
|
private int _referenceCount = 1;
|
||||||
|
|
||||||
|
|
@ -113,7 +117,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
ulong size,
|
ulong size,
|
||||||
BufferStage stage,
|
BufferStage stage,
|
||||||
bool sparseCompatible,
|
bool sparseCompatible,
|
||||||
RangeItem<Buffer>[] baseBuffers)
|
Buffer[] baseBuffers)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_physicalMemory = physicalMemory;
|
_physicalMemory = physicalMemory;
|
||||||
|
|
@ -134,15 +138,15 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
if (baseBuffers.Length != 0)
|
if (baseBuffers.Length != 0)
|
||||||
{
|
{
|
||||||
baseHandles = new List<IRegionHandle>();
|
baseHandles = new List<IRegionHandle>();
|
||||||
foreach (RangeItem<Buffer> item in baseBuffers)
|
foreach (Buffer item in baseBuffers)
|
||||||
{
|
{
|
||||||
if (item.Value._useGranular)
|
if (item._useGranular)
|
||||||
{
|
{
|
||||||
baseHandles.AddRange(item.Value._memoryTrackingGranular.Handles);
|
baseHandles.AddRange(item._memoryTrackingGranular.Handles);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
baseHandles.Add(item.Value._memoryTracking);
|
baseHandles.Add(item._memoryTracking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -247,14 +251,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// Checks if a given range overlaps with the buffer.
|
/// Checks if a given range overlaps with the buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Start address of the range</param>
|
/// <param name="address">Start address of the range</param>
|
||||||
/// <param name="size">Size in bytes of the range</param>
|
/// <param name="endAddress">End address of the range</param>
|
||||||
/// <returns>True if the range overlaps, false otherwise</returns>
|
/// <returns>True if the range overlaps, false otherwise</returns>
|
||||||
public bool OverlapsWith(ulong address, ulong size)
|
public bool OverlapsWith(ulong address, ulong endAddress)
|
||||||
{
|
{
|
||||||
return Address < address + size && address < EndAddress;
|
return Address < endAddress && address < EndAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public INonOverlappingRange Split(ulong splitAddress)
|
public INonOverlappingRange<Buffer> Split(ulong splitAddress)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
@ -389,11 +393,16 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// This will copy any buffer ranges designated for pre-flushing.
|
/// This will copy any buffer ranges designated for pre-flushing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="syncpoint">True if the action is a guest syncpoint</param>
|
/// <param name="syncpoint">True if the action is a guest syncpoint</param>
|
||||||
public void SyncPreAction(bool syncpoint)
|
public bool SyncPreAction(bool syncpoint)
|
||||||
{
|
{
|
||||||
|
if (_bufferInherited)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_referenceCount == 0)
|
if (_referenceCount == 0)
|
||||||
{
|
{
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BackingState.ShouldChangeBacking())
|
if (BackingState.ShouldChangeBacking())
|
||||||
|
|
@ -410,6 +419,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
_modifiedRanges?.GetRangesAtSync(Address, Size, _context.SyncNumber, _syncPreRangeAction);
|
_modifiedRanges?.GetRangesAtSync(Address, Size, _context.SyncNumber, _syncPreRangeAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyncPreRangeAction(ulong address, ulong size)
|
void SyncPreRangeAction(ulong address, ulong size)
|
||||||
|
|
@ -426,10 +437,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
_syncActionRegistered = false;
|
_syncActionRegistered = false;
|
||||||
|
|
||||||
|
if (_bufferInherited)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_useGranular)
|
if (_useGranular)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
_modifiedRanges?.GetRanges(Address, Size, _syncRangeAction);
|
_modifiedRanges?.GetRanges(Address, Size, _syncRangeAction);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -453,6 +467,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="from">The buffer to inherit from</param>
|
/// <param name="from">The buffer to inherit from</param>
|
||||||
public void InheritModifiedRanges(Buffer from)
|
public void InheritModifiedRanges(Buffer from)
|
||||||
{
|
{
|
||||||
|
from._bufferInherited = true;
|
||||||
|
|
||||||
if (from._modifiedRanges is { HasRanges: true })
|
if (from._modifiedRanges is { HasRanges: true })
|
||||||
{
|
{
|
||||||
if (from._syncActionRegistered && !_syncActionRegistered)
|
if (from._syncActionRegistered && !_syncActionRegistered)
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="parent">Parent buffer</param>
|
/// <param name="parent">Parent buffer</param>
|
||||||
/// <param name="stage">Initial buffer stage</param>
|
/// <param name="stage">Initial buffer stage</param>
|
||||||
/// <param name="baseBuffers">Buffers to inherit state from</param>
|
/// <param name="baseBuffers">Buffers to inherit state from</param>
|
||||||
public BufferBackingState(GpuContext context, Buffer parent, BufferStage stage, RangeItem<Buffer>[] baseBuffers)
|
public BufferBackingState(GpuContext context, Buffer parent, BufferStage stage, Buffer[] baseBuffers)
|
||||||
{
|
{
|
||||||
_size = (int)parent.Size;
|
_size = (int)parent.Size;
|
||||||
_systemMemoryType = context.Capabilities.MemoryType;
|
_systemMemoryType = context.Capabilities.MemoryType;
|
||||||
|
|
@ -102,9 +102,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
if (baseBuffers.Length != 0)
|
if (baseBuffers.Length != 0)
|
||||||
{
|
{
|
||||||
foreach (RangeItem<Buffer> item in baseBuffers)
|
foreach (Buffer item in baseBuffers)
|
||||||
{
|
{
|
||||||
CombineState(item.Value.BackingState);
|
CombineState(item.BackingState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,16 +79,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
for (int index = 0; index < range.Count; index++)
|
for (int index = 0; index < range.Count; index++)
|
||||||
{
|
{
|
||||||
MemoryRange subRange = range.GetSubRange(index);
|
MemoryRange subRange = range.GetSubRange(index);
|
||||||
|
|
||||||
_buffers.Lock.EnterReadLock();
|
ReadOnlySpan<Buffer> overlaps = _buffers.FindOverlapsAsSpan(subRange.Address, subRange.Size);
|
||||||
Span<RangeItem<Buffer>> overlaps = _buffers.FindOverlapsAsSpan(subRange.Address, subRange.Size);
|
|
||||||
|
|
||||||
for (int i = 0; i < overlaps.Length; i++)
|
for (int i = 0; i < overlaps.Length; i++)
|
||||||
{
|
{
|
||||||
overlaps[i].Value.Unmapped(subRange.Address, subRange.Size);
|
overlaps[i].Unmapped(subRange.Address, subRange.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffers.Lock.ExitReadLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -328,7 +325,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
ulong alignedEndAddress = (endAddress + alignmentMask) & ~alignmentMask;
|
ulong alignedEndAddress = (endAddress + alignmentMask) & ~alignmentMask;
|
||||||
ulong alignedSize = alignedEndAddress - alignedAddress;
|
ulong alignedSize = alignedEndAddress - alignedAddress;
|
||||||
|
|
||||||
Buffer buffer = _buffers.FindOverlap(alignedAddress, alignedSize).Value;
|
Buffer buffer = _buffers.FindOverlap(alignedAddress, alignedSize);
|
||||||
BufferRange bufferRange = buffer.GetRange(alignedAddress, alignedSize, false);
|
BufferRange bufferRange = buffer.GetRange(alignedAddress, alignedSize, false);
|
||||||
|
|
||||||
alignedSubRanges[i] = new MemoryRange(alignedAddress, alignedSize);
|
alignedSubRanges[i] = new MemoryRange(alignedAddress, alignedSize);
|
||||||
|
|
@ -395,7 +392,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
if (subRange.Address != MemoryManager.PteUnmapped)
|
if (subRange.Address != MemoryManager.PteUnmapped)
|
||||||
{
|
{
|
||||||
Buffer buffer = _buffers.FindOverlap(subRange.Address, subRange.Size).Value;
|
Buffer buffer = _buffers.FindOverlap(subRange.Address, subRange.Size);
|
||||||
|
|
||||||
virtualBuffer.AddPhysicalDependency(buffer, subRange.Address, dstOffset, subRange.Size);
|
virtualBuffer.AddPhysicalDependency(buffer, subRange.Address, dstOffset, subRange.Size);
|
||||||
physicalBuffers.Add(buffer);
|
physicalBuffers.Add(buffer);
|
||||||
|
|
@ -487,10 +484,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="stage">The type of usage that created the buffer</param>
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage)
|
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage)
|
||||||
{
|
{
|
||||||
Buffer newBuffer = null;
|
ReadOnlySpan<Buffer> overlaps = _buffers.FindOverlapsAsSpan(address, size);
|
||||||
|
|
||||||
_buffers.Lock.EnterWriteLock();
|
|
||||||
Span<RangeItem<Buffer>> overlaps = _buffers.FindOverlapsAsSpan(address, size);
|
|
||||||
|
|
||||||
if (overlaps.Length != 0)
|
if (overlaps.Length != 0)
|
||||||
{
|
{
|
||||||
|
|
@ -521,7 +515,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
// Try to grow the buffer by 1.5x of its current size.
|
// Try to grow the buffer by 1.5x of its current size.
|
||||||
// This improves performance in the cases where the buffer is resized often by small amounts.
|
// This improves performance in the cases where the buffer is resized often by small amounts.
|
||||||
ulong existingSize = overlaps[0].Value.Size;
|
ulong existingSize = overlaps[0].Size;
|
||||||
ulong growthSize = (existingSize + Math.Min(existingSize >> 1, MaxDynamicGrowthSize)) & ~BufferAlignmentMask;
|
ulong growthSize = (existingSize + Math.Min(existingSize >> 1, MaxDynamicGrowthSize)) & ~BufferAlignmentMask;
|
||||||
|
|
||||||
size = Math.Max(size, growthSize);
|
size = Math.Max(size, growthSize);
|
||||||
|
|
@ -535,39 +529,22 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
for (int i = 0; i < overlaps.Length; i++)
|
for (int i = 0; i < overlaps.Length; i++)
|
||||||
{
|
{
|
||||||
anySparseCompatible |= overlaps[i].Value.SparseCompatible;
|
anySparseCompatible |= overlaps[i].SparseCompatible;
|
||||||
}
|
}
|
||||||
|
|
||||||
RangeItem<Buffer>[] overlapsArray = overlaps.ToArray();
|
Buffer[] overlapsArray = overlaps.ToArray();
|
||||||
|
|
||||||
_buffers.RemoveRange(overlaps[0], overlaps[^1]);
|
_buffers.RemoveRange(overlaps[0], overlaps[^1]);
|
||||||
|
|
||||||
_buffers.Lock.ExitWriteLock();
|
|
||||||
|
|
||||||
ulong newSize = endAddress - address;
|
ulong newSize = endAddress - address;
|
||||||
|
|
||||||
newBuffer = CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlapsArray);
|
_buffers.Add(CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlapsArray));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_buffers.Lock.ExitWriteLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_buffers.Lock.ExitWriteLock();
|
|
||||||
|
|
||||||
// No overlap, just create a new buffer.
|
// No overlap, just create a new buffer.
|
||||||
newBuffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible: false, []);
|
_buffers.Add(new(_context, _physicalMemory, address, size, stage, sparseCompatible: false, []));
|
||||||
}
|
|
||||||
|
|
||||||
if (newBuffer is not null)
|
|
||||||
{
|
|
||||||
_buffers.Lock.EnterWriteLock();
|
|
||||||
|
|
||||||
_buffers.Add(newBuffer);
|
|
||||||
|
|
||||||
_buffers.Lock.ExitWriteLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -583,10 +560,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, ulong alignment)
|
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, ulong alignment)
|
||||||
{
|
{
|
||||||
bool sparseAligned = alignment >= SparseBufferAlignmentSize;
|
bool sparseAligned = alignment >= SparseBufferAlignmentSize;
|
||||||
Buffer newBuffer = null;
|
|
||||||
|
|
||||||
_buffers.Lock.EnterWriteLock();
|
ReadOnlySpan<Buffer> overlaps = _buffers.FindOverlapsAsSpan(address, size);
|
||||||
Span<RangeItem<Buffer>> overlaps = _buffers.FindOverlapsAsSpan(address, size);
|
|
||||||
|
|
||||||
if (overlaps.Length != 0)
|
if (overlaps.Length != 0)
|
||||||
{
|
{
|
||||||
|
|
@ -598,7 +573,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
if (overlaps[0].Address > address ||
|
if (overlaps[0].Address > address ||
|
||||||
overlaps[0].EndAddress < endAddress ||
|
overlaps[0].EndAddress < endAddress ||
|
||||||
(overlaps[0].Address & (alignment - 1)) != 0 ||
|
(overlaps[0].Address & (alignment - 1)) != 0 ||
|
||||||
(!overlaps[0].Value.SparseCompatible && sparseAligned))
|
(!overlaps[0].SparseCompatible && sparseAligned))
|
||||||
{
|
{
|
||||||
// We need to make sure the new buffer is properly aligned.
|
// We need to make sure the new buffer is properly aligned.
|
||||||
// However, after the range is aligned, it is possible that it
|
// However, after the range is aligned, it is possible that it
|
||||||
|
|
@ -622,35 +597,18 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
ulong newSize = endAddress - address;
|
ulong newSize = endAddress - address;
|
||||||
|
|
||||||
RangeItem<Buffer>[] overlapsArray = overlaps.ToArray();
|
Buffer[] overlapsArray = overlaps.ToArray();
|
||||||
|
|
||||||
_buffers.RemoveRange(overlaps[0], overlaps[^1]);
|
_buffers.RemoveRange(overlaps[0], overlaps[^1]);
|
||||||
|
|
||||||
_buffers.Lock.ExitWriteLock();
|
_buffers.Add(CreateBufferAligned(address, newSize, stage, sparseAligned, overlapsArray));
|
||||||
|
|
||||||
newBuffer = CreateBufferAligned(address, newSize, stage, sparseAligned, overlapsArray);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_buffers.Lock.ExitWriteLock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_buffers.Lock.ExitWriteLock();
|
|
||||||
|
|
||||||
// No overlap, just create a new buffer.
|
// No overlap, just create a new buffer.
|
||||||
newBuffer = new(_context, _physicalMemory, address, size, stage, sparseAligned, []);
|
_buffers.Add(new(_context, _physicalMemory, address, size, stage, sparseAligned, []));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newBuffer is not null)
|
|
||||||
{
|
|
||||||
_buffers.Lock.EnterWriteLock();
|
|
||||||
|
|
||||||
_buffers.Add(newBuffer);
|
|
||||||
|
|
||||||
_buffers.Lock.ExitWriteLock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -663,13 +621,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="stage">The type of usage that created the buffer</param>
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
/// <param name="sparseCompatible">Indicates if the buffer can be used in a sparse buffer mapping</param>
|
/// <param name="sparseCompatible">Indicates if the buffer can be used in a sparse buffer mapping</param>
|
||||||
/// <param name="overlaps">Buffers overlapping the range</param>
|
/// <param name="overlaps">Buffers overlapping the range</param>
|
||||||
private Buffer CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, RangeItem<Buffer>[] overlaps)
|
private Buffer CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, Buffer[] overlaps)
|
||||||
{
|
{
|
||||||
Buffer newBuffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible, overlaps);
|
Buffer newBuffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible, overlaps);
|
||||||
|
|
||||||
for (int index = 0; index < overlaps.Length; index++)
|
for (int index = 0; index < overlaps.Length; index++)
|
||||||
{
|
{
|
||||||
Buffer buffer = overlaps[index].Value;
|
Buffer buffer = overlaps[index];
|
||||||
|
|
||||||
int dstOffset = (int)(buffer.Address - newBuffer.Address);
|
int dstOffset = (int)(buffer.Address - newBuffer.Address);
|
||||||
|
|
||||||
|
|
@ -897,7 +855,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
MemoryRange subRange = range.GetSubRange(i);
|
MemoryRange subRange = range.GetSubRange(i);
|
||||||
|
|
||||||
Buffer subBuffer = _buffers.FindOverlap(subRange.Address, subRange.Size).Value;
|
Buffer subBuffer = _buffers.FindOverlap(subRange.Address, subRange.Size);
|
||||||
|
|
||||||
subBuffer.SynchronizeMemory(subRange.Address, subRange.Size);
|
subBuffer.SynchronizeMemory(subRange.Address, subRange.Size);
|
||||||
|
|
||||||
|
|
@ -945,7 +903,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
{
|
{
|
||||||
buffer = _buffers.FindOverlap(address, size).Value;
|
buffer = _buffers.FindOverlap(address, size);
|
||||||
|
|
||||||
buffer.CopyFromDependantVirtualBuffers();
|
buffer.CopyFromDependantVirtualBuffers();
|
||||||
buffer.SynchronizeMemory(address, size);
|
buffer.SynchronizeMemory(address, size);
|
||||||
|
|
@ -957,7 +915,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer = _buffers.FindOverlapFast(address, 1).Value;
|
buffer = _buffers.FindOverlapFast(address, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
@ -995,7 +953,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
{
|
{
|
||||||
Buffer buffer = _buffers.FindOverlap(address, size).Value;
|
Buffer buffer = _buffers.FindOverlap(address, size);
|
||||||
|
|
||||||
if (copyBackVirtual)
|
if (copyBackVirtual)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A range within a buffer that has been modified by the GPU.
|
/// A range within a buffer that has been modified by the GPU.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class BufferModifiedRange : INonOverlappingRange
|
class BufferModifiedRange : INonOverlappingRange<BufferModifiedRange>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start address of the range in guest memory.
|
/// Start address of the range in guest memory.
|
||||||
|
|
@ -24,6 +24,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// End address of the range in guest memory.
|
/// End address of the range in guest memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ulong EndAddress => Address + Size;
|
public ulong EndAddress => Address + Size;
|
||||||
|
|
||||||
|
public BufferModifiedRange Next { get; set; }
|
||||||
|
public BufferModifiedRange Previous { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The GPU sync number at the time of the last modification.
|
/// The GPU sync number at the time of the last modification.
|
||||||
|
|
@ -54,14 +57,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// Checks if a given range overlaps with the modified range.
|
/// Checks if a given range overlaps with the modified range.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Start address of the range</param>
|
/// <param name="address">Start address of the range</param>
|
||||||
/// <param name="size">Size in bytes of the range</param>
|
/// <param name="endAddress">End address of the range</param>
|
||||||
/// <returns>True if the range overlaps, false otherwise</returns>
|
/// <returns>True if the range overlaps, false otherwise</returns>
|
||||||
public bool OverlapsWith(ulong address, ulong size)
|
public bool OverlapsWith(ulong address, ulong endAddress)
|
||||||
{
|
{
|
||||||
return Address < address + size && address < EndAddress;
|
return Address < endAddress && address < EndAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public INonOverlappingRange Split(ulong splitAddress)
|
public INonOverlappingRange<BufferModifiedRange> Split(ulong splitAddress)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
@ -119,11 +122,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
// Slices a given region using the modified regions in the list. Calls the action for the new slices.
|
// Slices a given region using the modified regions in the list. Calls the action for the new slices.
|
||||||
Lock.EnterReadLock();
|
Lock.EnterReadLock();
|
||||||
|
|
||||||
Span<RangeItem<BufferModifiedRange>> overlaps = FindOverlapsAsSpan(address, size);
|
ReadOnlySpan<BufferModifiedRange> overlaps = FindOverlapsAsSpan(address, size);
|
||||||
|
|
||||||
for (int i = 0; i < overlaps.Length; i++)
|
for (int i = 0; i < overlaps.Length; i++)
|
||||||
{
|
{
|
||||||
BufferModifiedRange overlap = overlaps[i].Value;
|
BufferModifiedRange overlap = overlaps[i];
|
||||||
|
|
||||||
if (overlap.Address > address)
|
if (overlap.Address > address)
|
||||||
{
|
{
|
||||||
|
|
@ -157,7 +160,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
ulong syncNumber = _context.SyncNumber;
|
ulong syncNumber = _context.SyncNumber;
|
||||||
// We may overlap with some existing modified regions. They must be cut into by the new entry.
|
// We may overlap with some existing modified regions. They must be cut into by the new entry.
|
||||||
Lock.EnterWriteLock();
|
Lock.EnterWriteLock();
|
||||||
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> last) = FindOverlapsAsNodes(address, size);
|
(BufferModifiedRange first, BufferModifiedRange last) = FindOverlapsAsNodes(address, size);
|
||||||
|
|
||||||
if (first is null)
|
if (first is null)
|
||||||
{
|
{
|
||||||
|
|
@ -170,34 +173,39 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
if (first.Address == address && first.EndAddress == endAddress)
|
if (first.Address == address && first.EndAddress == endAddress)
|
||||||
{
|
{
|
||||||
first.Value.SyncNumber = syncNumber;
|
first.SyncNumber = syncNumber;
|
||||||
first.Value.Parent = this;
|
first.Parent = this;
|
||||||
Lock.ExitWriteLock();
|
Lock.ExitWriteLock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first.Address < address)
|
if (first.Address < address)
|
||||||
{
|
{
|
||||||
first.Value.Size = address - first.Address;
|
|
||||||
Update(first);
|
|
||||||
|
|
||||||
if (first.EndAddress > endAddress)
|
if (first.EndAddress > endAddress)
|
||||||
{
|
{
|
||||||
Add(new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
|
Add(new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
|
||||||
first.Value.SyncNumber, first.Value.Parent));
|
first.SyncNumber, first.Parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
first.Size = address - first.Address;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (first.EndAddress > endAddress)
|
if (first.EndAddress > endAddress)
|
||||||
{
|
{
|
||||||
first.Value.Size = first.EndAddress - endAddress;
|
first.Size = first.EndAddress - endAddress;
|
||||||
first.Value.Address = endAddress;
|
first.Address = endAddress;
|
||||||
Update(first);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Remove(first.Value);
|
first.Address = address;
|
||||||
|
first.Size = size;
|
||||||
|
first.SyncNumber = syncNumber;
|
||||||
|
first.Parent = this;
|
||||||
|
|
||||||
|
Lock.ExitWriteLock();
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,38 +215,39 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferModifiedRange buffPre = null;
|
|
||||||
BufferModifiedRange buffPost = null;
|
|
||||||
bool extendsPost = false;
|
|
||||||
bool extendsPre = false;
|
|
||||||
|
|
||||||
if (first.Address < address)
|
if (first.Address < address)
|
||||||
{
|
{
|
||||||
buffPre = new BufferModifiedRange(first.Address, address - first.Address,
|
first.Size = address - first.Address;
|
||||||
first.Value.SyncNumber, first.Value.Parent);
|
first = first.Next;
|
||||||
extendsPre = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last.EndAddress > endAddress)
|
if (last.EndAddress > endAddress)
|
||||||
{
|
{
|
||||||
buffPost = new BufferModifiedRange(endAddress, last.EndAddress - endAddress,
|
last.Size = last.EndAddress - endAddress;
|
||||||
last.Value.SyncNumber, last.Value.Parent);
|
last.Address = endAddress;
|
||||||
extendsPost = true;
|
last = last.Previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveRange(first, last);
|
if (first.Address < last.Address)
|
||||||
|
|
||||||
if (extendsPre)
|
|
||||||
{
|
{
|
||||||
Add(buffPre);
|
RemoveRange(first.Next, last);
|
||||||
|
first.Address = address;
|
||||||
|
first.Size = size;
|
||||||
|
first.SyncNumber = syncNumber;
|
||||||
|
first.Parent = this;
|
||||||
}
|
}
|
||||||
|
else if (first.Address == last.Address)
|
||||||
if (extendsPost)
|
|
||||||
{
|
{
|
||||||
Add(buffPost);
|
first.Address = address;
|
||||||
|
first.Size = size;
|
||||||
|
first.SyncNumber = syncNumber;
|
||||||
|
first.Parent = this;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
Add(new BufferModifiedRange(address, size, syncNumber, this));
|
{
|
||||||
|
Add(new BufferModifiedRange(address, size, syncNumber, this));
|
||||||
|
}
|
||||||
|
|
||||||
Lock.ExitWriteLock();
|
Lock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,11 +261,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
public void GetRangesAtSync(ulong address, ulong size, ulong syncNumber, Action<ulong, ulong> rangeAction)
|
public void GetRangesAtSync(ulong address, ulong size, ulong syncNumber, Action<ulong, ulong> rangeAction)
|
||||||
{
|
{
|
||||||
Lock.EnterReadLock();
|
Lock.EnterReadLock();
|
||||||
Span<RangeItem<BufferModifiedRange>> overlaps = FindOverlapsAsSpan(address, size);
|
ReadOnlySpan<BufferModifiedRange> overlaps = FindOverlapsAsSpan(address, size);
|
||||||
|
|
||||||
for (int i = 0; i < overlaps.Length; i++)
|
for (int i = 0; i < overlaps.Length; i++)
|
||||||
{
|
{
|
||||||
BufferModifiedRange overlap = overlaps[i].Value;
|
BufferModifiedRange overlap = overlaps[i];
|
||||||
|
|
||||||
if (overlap.SyncNumber == syncNumber)
|
if (overlap.SyncNumber == syncNumber)
|
||||||
{
|
{
|
||||||
|
|
@ -277,18 +286,18 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
// We use the non-span method here because keeping the lock will cause a deadlock.
|
// We use the non-span method here because keeping the lock will cause a deadlock.
|
||||||
Lock.EnterReadLock();
|
Lock.EnterReadLock();
|
||||||
RangeItem<BufferModifiedRange>[] overlaps = FindOverlapsAsArray(address, size, out int length);
|
BufferModifiedRange[] overlaps = FindOverlapsAsArray(address, size, out int length);
|
||||||
Lock.ExitReadLock();
|
Lock.ExitReadLock();
|
||||||
|
|
||||||
if (length != 0)
|
if (length != 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
BufferModifiedRange overlap = overlaps[i].Value;
|
BufferModifiedRange overlap = overlaps[i];
|
||||||
rangeAction(overlap.Address, overlap.Size);
|
rangeAction(overlap.Address, overlap.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayPool<RangeItem<BufferModifiedRange>>.Shared.Return(overlaps);
|
ArrayPool<BufferModifiedRange>.Shared.Return(overlaps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -301,7 +310,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
public bool HasRange(ulong address, ulong size)
|
public bool HasRange(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
Lock.EnterReadLock();
|
Lock.EnterReadLock();
|
||||||
RangeItem<BufferModifiedRange> first = FindOverlapFast(address, size);
|
BufferModifiedRange first = FindOverlapFast(address, size);
|
||||||
bool result = first is not null;
|
bool result = first is not null;
|
||||||
Lock.ExitReadLock();
|
Lock.ExitReadLock();
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -336,7 +345,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="address">The start address of the flush range</param>
|
/// <param name="address">The start address of the flush range</param>
|
||||||
/// <param name="endAddress">The end address of the flush range</param>
|
/// <param name="endAddress">The end address of the flush range</param>
|
||||||
private void RemoveRangesAndFlush(
|
private void RemoveRangesAndFlush(
|
||||||
RangeItem<BufferModifiedRange>[] overlaps,
|
BufferModifiedRange[] overlaps,
|
||||||
int rangeCount,
|
int rangeCount,
|
||||||
long highestDiff,
|
long highestDiff,
|
||||||
ulong currentSync,
|
ulong currentSync,
|
||||||
|
|
@ -349,7 +358,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
for (int i = 0; i < rangeCount; i++)
|
for (int i = 0; i < rangeCount; i++)
|
||||||
{
|
{
|
||||||
BufferModifiedRange overlap = overlaps[i].Value;
|
BufferModifiedRange overlap = overlaps[i];
|
||||||
|
|
||||||
long diff = (long)(overlap.SyncNumber - currentSync);
|
long diff = (long)(overlap.SyncNumber - currentSync);
|
||||||
|
|
||||||
|
|
@ -358,7 +367,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
ulong clampAddress = Math.Max(address, overlap.Address);
|
ulong clampAddress = Math.Max(address, overlap.Address);
|
||||||
ulong clampEnd = Math.Min(endAddress, overlap.EndAddress);
|
ulong clampEnd = Math.Min(endAddress, overlap.EndAddress);
|
||||||
|
|
||||||
ClearPart(overlap, clampAddress, clampEnd);
|
if (i == 0 || i == rangeCount - 1)
|
||||||
|
{
|
||||||
|
ClearPart(overlap, clampAddress, clampEnd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Remove(overlap);
|
||||||
|
}
|
||||||
|
|
||||||
RangeActionWithMigration(clampAddress, clampEnd - clampAddress, waitSync, _flushAction);
|
RangeActionWithMigration(clampAddress, clampEnd - clampAddress, waitSync, _flushAction);
|
||||||
}
|
}
|
||||||
|
|
@ -398,7 +414,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
Lock.EnterWriteLock();
|
Lock.EnterWriteLock();
|
||||||
// We use the non-span method here because the array is partially modified by the code, which would invalidate a span.
|
// We use the non-span method here because the array is partially modified by the code, which would invalidate a span.
|
||||||
RangeItem<BufferModifiedRange>[] overlaps = FindOverlapsAsArray(address, size, out int rangeCount);
|
BufferModifiedRange[] overlaps = FindOverlapsAsArray(address, size, out int rangeCount);
|
||||||
|
|
||||||
if (rangeCount == 0)
|
if (rangeCount == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -414,7 +430,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
for (int i = 0; i < rangeCount; i++)
|
for (int i = 0; i < rangeCount; i++)
|
||||||
{
|
{
|
||||||
BufferModifiedRange overlap = overlaps![i].Value;
|
BufferModifiedRange overlap = overlaps![i];
|
||||||
|
|
||||||
long diff = (long)(overlap.SyncNumber - currentSync);
|
long diff = (long)(overlap.SyncNumber - currentSync);
|
||||||
|
|
||||||
|
|
@ -436,7 +452,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
RemoveRangesAndFlush(overlaps, rangeCount, highestDiff, currentSync, address, endAddress);
|
RemoveRangesAndFlush(overlaps, rangeCount, highestDiff, currentSync, address, endAddress);
|
||||||
|
|
||||||
ArrayPool<RangeItem<BufferModifiedRange>>.Shared.Return(overlaps!);
|
ArrayPool<BufferModifiedRange>.Shared.Return(overlaps!);
|
||||||
|
|
||||||
Lock.ExitWriteLock();
|
Lock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
|
|
@ -452,7 +468,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
public void InheritRanges(BufferModifiedRangeList ranges, Action<ulong, ulong> registerRangeAction)
|
public void InheritRanges(BufferModifiedRangeList ranges, Action<ulong, ulong> registerRangeAction)
|
||||||
{
|
{
|
||||||
ranges.Lock.EnterReadLock();
|
ranges.Lock.EnterReadLock();
|
||||||
BufferModifiedRange[] inheritRanges = ranges.ToArray();
|
int rangesCount = ranges.Count;
|
||||||
|
BufferModifiedRange[] inheritRanges = ArrayPool<BufferModifiedRange>.Shared.Rent(ranges.Count);
|
||||||
|
ranges.Items.AsSpan(0, ranges.Count).CopyTo(inheritRanges);
|
||||||
ranges.Lock.ExitReadLock();
|
ranges.Lock.ExitReadLock();
|
||||||
|
|
||||||
// Copy over the migration from the previous range list
|
// Copy over the migration from the previous range list
|
||||||
|
|
@ -478,22 +496,26 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
ranges._migrationTarget = this;
|
ranges._migrationTarget = this;
|
||||||
|
|
||||||
Lock.EnterWriteLock();
|
Lock.EnterWriteLock();
|
||||||
|
|
||||||
foreach (BufferModifiedRange range in inheritRanges)
|
for (int i = 0; i < rangesCount; i++)
|
||||||
{
|
{
|
||||||
|
BufferModifiedRange range = inheritRanges[i];
|
||||||
Add(range);
|
Add(range);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lock.ExitWriteLock();
|
Lock.ExitWriteLock();
|
||||||
|
|
||||||
ulong currentSync = _context.SyncNumber;
|
ulong currentSync = _context.SyncNumber;
|
||||||
foreach (BufferModifiedRange range in inheritRanges)
|
for (int i = 0; i < rangesCount; i++)
|
||||||
{
|
{
|
||||||
|
BufferModifiedRange range = inheritRanges[i];
|
||||||
if (range.SyncNumber != currentSync)
|
if (range.SyncNumber != currentSync)
|
||||||
{
|
{
|
||||||
registerRangeAction(range.Address, range.Size);
|
registerRangeAction(range.Address, range.Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayPool<BufferModifiedRange>.Shared.Return(inheritRanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -534,18 +556,25 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
private void ClearPart(BufferModifiedRange overlap, ulong address, ulong endAddress)
|
private void ClearPart(BufferModifiedRange overlap, ulong address, ulong endAddress)
|
||||||
{
|
{
|
||||||
Remove(overlap);
|
|
||||||
|
|
||||||
// If the overlap extends outside of the clear range, make sure those parts still exist.
|
// If the overlap extends outside of the clear range, make sure those parts still exist.
|
||||||
|
|
||||||
if (overlap.Address < address)
|
if (overlap.Address < address)
|
||||||
{
|
{
|
||||||
Add(new BufferModifiedRange(overlap.Address, address - overlap.Address, overlap.SyncNumber, overlap.Parent));
|
if (overlap.EndAddress > endAddress)
|
||||||
|
{
|
||||||
|
Add(new BufferModifiedRange(endAddress, overlap.EndAddress - endAddress, overlap.SyncNumber, overlap.Parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
overlap.Size = address - overlap.Address;
|
||||||
}
|
}
|
||||||
|
else if (overlap.EndAddress > endAddress)
|
||||||
if (overlap.EndAddress > endAddress)
|
|
||||||
{
|
{
|
||||||
Add(new BufferModifiedRange(endAddress, overlap.EndAddress - endAddress, overlap.SyncNumber, overlap.Parent));
|
overlap.Size = overlap.EndAddress - endAddress;
|
||||||
|
overlap.Address = endAddress;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Remove(overlap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -558,7 +587,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
ulong endAddress = address + size;
|
ulong endAddress = address + size;
|
||||||
Lock.EnterWriteLock();
|
Lock.EnterWriteLock();
|
||||||
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> last) = FindOverlapsAsNodes(address, size);
|
(BufferModifiedRange first, BufferModifiedRange last) = FindOverlapsAsNodes(address, size);
|
||||||
|
|
||||||
if (first is null)
|
if (first is null)
|
||||||
{
|
{
|
||||||
|
|
@ -570,26 +599,24 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
if (first.Address < address)
|
if (first.Address < address)
|
||||||
{
|
{
|
||||||
first.Value.Size = address - first.Address;
|
first.Size = address - first.Address;
|
||||||
Update(first);
|
|
||||||
|
|
||||||
if (first.EndAddress > endAddress)
|
if (first.EndAddress > endAddress)
|
||||||
{
|
{
|
||||||
Add(new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
|
Add(new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
|
||||||
first.Value.SyncNumber, first.Value.Parent));
|
first.SyncNumber, first.Parent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (first.EndAddress > endAddress)
|
if (first.EndAddress > endAddress)
|
||||||
{
|
{
|
||||||
first.Value.Size = first.EndAddress - endAddress;
|
first.Size = first.EndAddress - endAddress;
|
||||||
first.Value.Address = endAddress;
|
first.Address = endAddress;
|
||||||
Update(first);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Remove(first.Value);
|
Remove(first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -605,14 +632,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
if (first.Address < address)
|
if (first.Address < address)
|
||||||
{
|
{
|
||||||
buffPre = new BufferModifiedRange(first.Address, address - first.Address,
|
buffPre = new BufferModifiedRange(first.Address, address - first.Address,
|
||||||
first.Value.SyncNumber, first.Value.Parent);
|
first.SyncNumber, first.Parent);
|
||||||
extendsPre = true;
|
extendsPre = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last.EndAddress > endAddress)
|
if (last.EndAddress > endAddress)
|
||||||
{
|
{
|
||||||
buffPost = new BufferModifiedRange(endAddress, last.EndAddress - endAddress,
|
buffPost = new BufferModifiedRange(endAddress, last.EndAddress - endAddress,
|
||||||
last.Value.SyncNumber, last.Value.Parent);
|
last.SyncNumber, last.Parent);
|
||||||
extendsPost = true;
|
extendsPost = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a GPU virtual memory range.
|
/// Represents a GPU virtual memory range.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private class VirtualRange : INonOverlappingRange
|
private class VirtualRange : INonOverlappingRange<VirtualRange>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GPU virtual address where the range starts.
|
/// GPU virtual address where the range starts.
|
||||||
|
|
@ -32,6 +32,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ulong EndAddress => Address + Size;
|
public ulong EndAddress => Address + Size;
|
||||||
|
|
||||||
|
public VirtualRange Next { get; set; }
|
||||||
|
public VirtualRange Previous { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Physical regions where the GPU virtual region is mapped.
|
/// Physical regions where the GPU virtual region is mapped.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -54,14 +57,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// Checks if a given range overlaps with the buffer.
|
/// Checks if a given range overlaps with the buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Start address of the range</param>
|
/// <param name="address">Start address of the range</param>
|
||||||
/// <param name="size">Size in bytes of the range</param>
|
/// <param name="endAddress">End address of the range</param>
|
||||||
/// <returns>True if the range overlaps, false otherwise</returns>
|
/// <returns>True if the range overlaps, false otherwise</returns>
|
||||||
public bool OverlapsWith(ulong address, ulong size)
|
public bool OverlapsWith(ulong address, ulong endAddress)
|
||||||
{
|
{
|
||||||
return Address < address + size && address < EndAddress;
|
return Address < endAddress && address < EndAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public INonOverlappingRange Split(ulong splitAddress)
|
public INonOverlappingRange<VirtualRange> Split(ulong splitAddress)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +125,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
ulong originalVa = gpuVa;
|
ulong originalVa = gpuVa;
|
||||||
|
|
||||||
_virtualRanges.Lock.EnterWriteLock();
|
_virtualRanges.Lock.EnterWriteLock();
|
||||||
(RangeItem<VirtualRange> first, RangeItem<VirtualRange> last) = _virtualRanges.FindOverlapsAsNodes(gpuVa, size);
|
(VirtualRange first, VirtualRange last) = _virtualRanges.FindOverlapsAsNodes(gpuVa, size);
|
||||||
|
|
||||||
if (first is not null)
|
if (first is not null)
|
||||||
{
|
{
|
||||||
|
|
@ -147,8 +150,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
found = first.Value.Range.Count == 1 || IsSparseAligned(first.Value.Range);
|
found = first.Range.Count == 1 || IsSparseAligned(first.Range);
|
||||||
range = first.Value.Range.Slice(gpuVa - first.Address, size);
|
range = first.Range.Slice(gpuVa - first.Address, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,6 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
||||||
/// Action to be performed immediately before sync is created.
|
/// Action to be performed immediately before sync is created.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="syncpoint">True if the action is a guest syncpoint</param>
|
/// <param name="syncpoint">True if the action is a guest syncpoint</param>
|
||||||
void SyncPreAction(bool syncpoint) { }
|
bool SyncPreAction(bool syncpoint) { return true; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1166,7 +1166,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetRenderTargets(ITexture[] colors, ITexture depthStencil)
|
public void SetRenderTargets(Span<ITexture> colors, ITexture depthStencil)
|
||||||
{
|
{
|
||||||
EnsureFramebuffer();
|
EnsureFramebuffer();
|
||||||
|
|
||||||
|
|
|
||||||
12
src/Ryujinx.Graphics.RenderDocApi/Capture.cs
Normal file
12
src/Ryujinx.Graphics.RenderDocApi/Capture.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.RenderDocApi
|
||||||
|
{
|
||||||
|
public readonly record struct Capture(int Index, string FileName, DateTime Timestamp)
|
||||||
|
{
|
||||||
|
public void SetComments(string comments)
|
||||||
|
{
|
||||||
|
RenderDoc.SetCaptureFileComments(FileName, comments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
100
src/Ryujinx.Graphics.RenderDocApi/CaptureOption.cs
Normal file
100
src/Ryujinx.Graphics.RenderDocApi/CaptureOption.cs
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
// ReSharper disable UnusedMember.Global
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.RenderDocApi
|
||||||
|
{
|
||||||
|
public enum CaptureOption
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// specifies whether the application is allowed to enable vsync. Default is on.
|
||||||
|
/// </summary>
|
||||||
|
AllowVsync = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// specifies whether the application is allowed to enter exclusive fullscreen. Default is on.
|
||||||
|
/// </summary>
|
||||||
|
AllowFullscreen = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// specifies whether (where possible) API-specific debugging is enabled. Default is off.
|
||||||
|
/// </summary>
|
||||||
|
ApiValidation = 2,
|
||||||
|
/// <summary>
|
||||||
|
/// specifies whether each API call should save a callstack. Default is off.
|
||||||
|
/// </summary>
|
||||||
|
CaptureCallstacks = 3,
|
||||||
|
/// <summary>
|
||||||
|
/// specifies whether, if <see cref="CaptureCallstacks"/> is enabled, callstacks are only saved on actions. Default is off.
|
||||||
|
/// </summary>
|
||||||
|
CaptureCallstacksOnlyDraws = 4,
|
||||||
|
/// <summary>
|
||||||
|
/// specifies a delay in seconds after launching a process to pause, to allow debuggers to attach. <br/>
|
||||||
|
/// This will only apply to child processes since the delay happens at process startup. Default is 0.
|
||||||
|
/// </summary>
|
||||||
|
DelayForDebugger = 5,
|
||||||
|
/// <summary>
|
||||||
|
/// specifies whether any mapped memory updates should be bounds-checked for overruns,
|
||||||
|
/// and uninitialised buffers are initialized to <code>0xDDDDDDDD</code> to catch use of uninitialised data.
|
||||||
|
/// Only supported on D3D11 and OpenGL. Default is off.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This option is only valid for OpenGL and D3D11. Explicit APIs such as D3D12 and Vulkan do
|
||||||
|
/// not do the same kind of interception & checking, and undefined contents are really undefined.
|
||||||
|
/// </remarks>
|
||||||
|
VerifyBufferAccess = 6,
|
||||||
|
/// <summary>
|
||||||
|
/// Hooks any system API calls that create child processes, and injects
|
||||||
|
/// RenderDoc into them recursively with the same options.
|
||||||
|
/// </summary>
|
||||||
|
HookIntoChildren = 7,
|
||||||
|
/// <summary>
|
||||||
|
/// specifies whether all live resources at the time of capture should be included in the capture,
|
||||||
|
/// even if they are not referenced by the frame. Default is off.
|
||||||
|
/// </summary>
|
||||||
|
RefAllSources = 8,
|
||||||
|
/// <summary>
|
||||||
|
/// By default, RenderDoc skips saving initial states for resources where the
|
||||||
|
/// previous contents don't appear to be used, assuming that writes before
|
||||||
|
/// reads indicate previous contents aren't used.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// **NOTE**: As of RenderDoc v1.1 this option has been deprecated. Setting or
|
||||||
|
/// getting it will be ignored, to allow compatibility with older versions.
|
||||||
|
/// In v1.1 the option acts as if it's always enabled.
|
||||||
|
/// </remarks>
|
||||||
|
SaveAllInitials = 9,
|
||||||
|
/// <summary>
|
||||||
|
/// In APIs that allow for the recording of command lists to be replayed later,
|
||||||
|
/// RenderDoc may choose to not capture command lists before a frame capture is
|
||||||
|
/// triggered, to reduce overheads. This means any command lists recorded once
|
||||||
|
/// and replayed many times will not be available and may cause a failure to
|
||||||
|
/// capture.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// NOTE: This is only true for APIs where multithreading is difficult or
|
||||||
|
/// discouraged. Newer APIs like Vulkan and D3D12 will ignore this option
|
||||||
|
/// and always capture all command lists since the API is heavily oriented
|
||||||
|
/// around it and the overheads have been reduced by API design.
|
||||||
|
/// </remarks>
|
||||||
|
CaptureAllCmdLists = 10,
|
||||||
|
/// <summary>
|
||||||
|
/// Mute API debugging output when the <see cref="ApiValidation"/> option is enabled.
|
||||||
|
/// </summary>
|
||||||
|
DebugOutputMute = 11,
|
||||||
|
/// <summary>
|
||||||
|
/// Allow vendor extensions to be used even when they may be
|
||||||
|
/// incompatible with RenderDoc and cause corrupted replays or crashes.
|
||||||
|
/// </summary>
|
||||||
|
AllowUnsupportedVendorExtensions = 12,
|
||||||
|
/// <summary>
|
||||||
|
/// Define a soft memory limit which some APIs may aim to keep overhead under where
|
||||||
|
/// possible. Anything above this limit will where possible be saved directly to disk during
|
||||||
|
/// capture.<br/>
|
||||||
|
/// This will cause increased disk space use (which may cause a capture to fail if disk space is
|
||||||
|
/// exhausted) as well as slower capture times.
|
||||||
|
/// <br/><br/>
|
||||||
|
/// Not all memory allocations may be deferred like this so it is not a guarantee of a memory
|
||||||
|
/// limit.
|
||||||
|
/// <br/><br/>
|
||||||
|
/// Units are in MBs, suggested values would range from 200MB to 1000MB.
|
||||||
|
/// </summary>
|
||||||
|
SoftMemoryLimit = 13,
|
||||||
|
}
|
||||||
|
}
|
||||||
83
src/Ryujinx.Graphics.RenderDocApi/InputButton.cs
Normal file
83
src/Ryujinx.Graphics.RenderDocApi/InputButton.cs
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
|
||||||
|
// ReSharper disable UnusedMember.Global
|
||||||
|
namespace Ryujinx.Graphics.RenderDocApi
|
||||||
|
{
|
||||||
|
public enum InputButton
|
||||||
|
{
|
||||||
|
// '0' - '9' matches ASCII values
|
||||||
|
Key0 = 0x30,
|
||||||
|
Key1 = 0x31,
|
||||||
|
Key2 = 0x32,
|
||||||
|
Key3 = 0x33,
|
||||||
|
Key4 = 0x34,
|
||||||
|
Key5 = 0x35,
|
||||||
|
Key6 = 0x36,
|
||||||
|
Key7 = 0x37,
|
||||||
|
Key8 = 0x38,
|
||||||
|
Key9 = 0x39,
|
||||||
|
|
||||||
|
// 'A' - 'Z' matches ASCII values
|
||||||
|
A = 0x41,
|
||||||
|
B = 0x42,
|
||||||
|
C = 0x43,
|
||||||
|
D = 0x44,
|
||||||
|
E = 0x45,
|
||||||
|
F = 0x46,
|
||||||
|
G = 0x47,
|
||||||
|
H = 0x48,
|
||||||
|
I = 0x49,
|
||||||
|
J = 0x4A,
|
||||||
|
K = 0x4B,
|
||||||
|
L = 0x4C,
|
||||||
|
M = 0x4D,
|
||||||
|
N = 0x4E,
|
||||||
|
O = 0x4F,
|
||||||
|
P = 0x50,
|
||||||
|
Q = 0x51,
|
||||||
|
R = 0x52,
|
||||||
|
S = 0x53,
|
||||||
|
T = 0x54,
|
||||||
|
U = 0x55,
|
||||||
|
V = 0x56,
|
||||||
|
W = 0x57,
|
||||||
|
X = 0x58,
|
||||||
|
Y = 0x59,
|
||||||
|
Z = 0x5A,
|
||||||
|
|
||||||
|
// leave the rest of the ASCII range free
|
||||||
|
// in case we want to use it later
|
||||||
|
NonPrintable = 0x100,
|
||||||
|
|
||||||
|
Divide,
|
||||||
|
Multiply,
|
||||||
|
Subtract,
|
||||||
|
Plus,
|
||||||
|
|
||||||
|
F1,
|
||||||
|
F2,
|
||||||
|
F3,
|
||||||
|
F4,
|
||||||
|
F5,
|
||||||
|
F6,
|
||||||
|
F7,
|
||||||
|
F8,
|
||||||
|
F9,
|
||||||
|
F10,
|
||||||
|
F11,
|
||||||
|
F12,
|
||||||
|
|
||||||
|
Home,
|
||||||
|
End,
|
||||||
|
Insert,
|
||||||
|
Delete,
|
||||||
|
PageUp,
|
||||||
|
PageDn,
|
||||||
|
|
||||||
|
Backspace,
|
||||||
|
Tab,
|
||||||
|
PrtScrn,
|
||||||
|
Pause,
|
||||||
|
|
||||||
|
Max,
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/Ryujinx.Graphics.RenderDocApi/OverlayBits.cs
Normal file
39
src/Ryujinx.Graphics.RenderDocApi/OverlayBits.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
// ReSharper disable UnusedMember.Global
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.RenderDocApi
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum OverlayBits
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This single bit controls whether the overlay is enabled or disabled globally
|
||||||
|
/// </summary>
|
||||||
|
Enabled = 1 << 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Show the average framerate over several seconds as well as min/max
|
||||||
|
/// </summary>
|
||||||
|
FrameRate = 1 << 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Show the current frame number
|
||||||
|
/// </summary>
|
||||||
|
FrameNumber = 1 << 2,
|
||||||
|
/// <summary>
|
||||||
|
/// Show a list of recent captures, and how many captures have been made
|
||||||
|
/// </summary>
|
||||||
|
CaptureList = 1 << 3,
|
||||||
|
/// <summary>
|
||||||
|
/// Default values for the overlay mask
|
||||||
|
/// </summary>
|
||||||
|
Default = Enabled | FrameRate | FrameNumber | CaptureList,
|
||||||
|
/// <summary>
|
||||||
|
/// Enable all bits
|
||||||
|
/// </summary>
|
||||||
|
All = ~0,
|
||||||
|
/// <summary>
|
||||||
|
/// Disable all bits
|
||||||
|
/// </summary>
|
||||||
|
None = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue