Compare commits
69 Commits
Canary-1.2
...
Canary-1.2
Author | SHA1 | Date | |
---|---|---|---|
978d2c132b | |||
5d63706cea | |||
732aafd3bb | |||
3fa714bb72 | |||
7c01633f13 | |||
27c5cba10b | |||
3525d5ecd4 | |||
6286501550 | |||
61ae427a4d | |||
19d2883a35 | |||
617c03119f | |||
e43d899e1d | |||
0cd09ea0c5 | |||
4135d74e4d | |||
bd29f658b1 | |||
df150f0788 | |||
e50198b37d | |||
f426945fec | |||
172869bfba | |||
b6f88514f9 | |||
e92f52e56c | |||
318498eab0 | |||
a5cde8e006 | |||
d0a344d632 | |||
ca66298817 | |||
9ae1c4380d | |||
c88518bce2 | |||
a3888ed7cf | |||
7cbbd02973 | |||
b2e1e553e4 | |||
699e1962b1 | |||
e486b902b1 | |||
0ab5b41c4b | |||
d10a478cce | |||
ec1020b165 | |||
4082ebad1a | |||
da8ea06074 | |||
7f9dccb293 | |||
8e4a77aba0 | |||
8fd8a776c9 | |||
eec92c242c | |||
42a739d34c | |||
f362bef43d | |||
f5ce539de9 | |||
4f699afe7a | |||
6caab1aa37 | |||
9baaa2b8f8 | |||
7f376b4f45 | |||
32cdccde12 | |||
cbd851d00e | |||
f463ea1c5d | |||
1dd69912b1 | |||
1fbb0d8e7d | |||
9ee3f1ff36 | |||
d052d74ac4 | |||
df91c4c57a | |||
2aaaa7872f | |||
b5999583d6 | |||
8b3a945b5f | |||
09107b67ff | |||
12b264af44 | |||
0c21b07f19 | |||
18625cf775 | |||
77a9246825 | |||
709eeda94a | |||
7d54424048 | |||
664c63c6a8 | |||
153d1ef06b | |||
e1e4e5d2d5 |
23
.github/workflows/build.yml
vendored
@ -64,14 +64,9 @@ jobs:
|
|||||||
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
|
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'
|
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
||||||
|
|
||||||
- name: Publish Ryujinx.Headless.SDL2
|
|
||||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
|
||||||
|
|
||||||
- name: Set executable bit
|
- name: Set executable bit
|
||||||
run: |
|
run: |
|
||||||
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
||||||
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
|
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
|
||||||
|
|
||||||
- name: Build AppImage
|
- name: Build AppImage
|
||||||
@ -119,13 +114,6 @@ jobs:
|
|||||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}-AppImage
|
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}-AppImage
|
||||||
path: publish_appimage
|
path: publish_appimage
|
||||||
|
|
||||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: nogui-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
|
|
||||||
path: publish_sdl2_headless
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
|
||||||
|
|
||||||
build_macos:
|
build_macos:
|
||||||
name: macOS Universal (${{ matrix.configuration }})
|
name: macOS Universal (${{ matrix.configuration }})
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -171,20 +159,9 @@ jobs:
|
|||||||
run: |
|
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"
|
./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: Publish macOS Ryujinx.Headless.SDL2
|
|
||||||
run: |
|
|
||||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
|
||||||
|
|
||||||
- name: Upload Ryujinx artifact
|
- name: Upload Ryujinx artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||||
path: "publish/*.tar.gz"
|
path: "publish/*.tar.gz"
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
|
|
||||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: nogui-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
|
||||||
path: "publish_headless/*.tar.gz"
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
|
20
.github/workflows/canary.yml
vendored
@ -116,7 +116,6 @@ jobs:
|
|||||||
- name: Publish
|
- name: Publish
|
||||||
run: |
|
run: |
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
|
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained
|
|
||||||
|
|
||||||
- name: Packing Windows builds
|
- name: Packing Windows builds
|
||||||
if: matrix.platform.os == 'windows-latest'
|
if: matrix.platform.os == 'windows-latest'
|
||||||
@ -125,11 +124,6 @@ jobs:
|
|||||||
rm publish/libarmeilleure-jitsupport.dylib
|
rm publish/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
|
||||||
|
|
||||||
pushd publish_sdl2_headless
|
|
||||||
rm publish/libarmeilleure-jitsupport.dylib
|
|
||||||
7z a ../release_output/nogui-ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
|
|
||||||
popd
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Packing Linux builds
|
- name: Packing Linux builds
|
||||||
@ -140,12 +134,6 @@ jobs:
|
|||||||
chmod +x publish/Ryujinx.sh publish/Ryujinx
|
chmod +x publish/Ryujinx.sh publish/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
|
||||||
|
|
||||||
pushd publish_sdl2_headless
|
|
||||||
rm publish/libarmeilleure-jitsupport.dylib
|
|
||||||
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
|
|
||||||
tar -czvf ../release_output/nogui-ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
|
||||||
popd
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
#- name: Build AppImage (Linux)
|
#- name: Build AppImage (Linux)
|
||||||
@ -191,7 +179,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: ${{ steps.version_info.outputs.build_version }}
|
name: ${{ steps.version_info.outputs.build_version }}
|
||||||
artifacts: "release_output/*.tar.gz,release_output/*.zip"
|
artifacts: "release_output/*.tar.gz,release_output/*.zip"
|
||||||
#artifacts: "release_output/*.tar.gz,release_output/*.zip/*AppImage*"
|
#artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: |
|
body: |
|
||||||
# Canary builds:
|
# Canary builds:
|
||||||
@ -262,15 +250,11 @@ jobs:
|
|||||||
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
|
||||||
|
|
||||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
|
||||||
run: |
|
|
||||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
|
|
||||||
|
|
||||||
- name: Pushing new release
|
- name: Pushing new release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
||||||
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
|
artifacts: "publish_ava/*.tar.gz"
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: ""
|
body: ""
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
|
12
.github/workflows/nightly_pr_comment.yml
vendored
@ -37,21 +37,17 @@ jobs:
|
|||||||
if (!artifacts.length) {
|
if (!artifacts.length) {
|
||||||
return core.error(`No artifacts found`);
|
return core.error(`No artifacts found`);
|
||||||
}
|
}
|
||||||
let body = `Download the artifacts for this pull request:\n`;
|
let body = `*You need to be logged into GitHub to download these files.*\n\nDownload the artifacts for this pull request:\n`;
|
||||||
let hidden_headless_artifacts = `\n\n <details><summary>GUI-less</summary>\n`;
|
|
||||||
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
|
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
|
||||||
for (const art of artifacts) {
|
for (const art of artifacts) {
|
||||||
|
const url = `https://github.com/Ryubing/Ryujinx/actions/runs/${run_id}/artifacts/${art.id}`;
|
||||||
if(art.name.includes('Debug')) {
|
if(art.name.includes('Debug')) {
|
||||||
hidden_debug_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
hidden_debug_artifacts += `\n* [${art.name}](${url})`;
|
||||||
} else if(art.name.includes('nogui-ryujinx')) {
|
|
||||||
hidden_headless_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
|
||||||
} else {
|
} else {
|
||||||
body += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
body += `\n* [${art.name}](${url})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hidden_headless_artifacts += `\n</details>`;
|
|
||||||
hidden_debug_artifacts += `\n</details>`;
|
hidden_debug_artifacts += `\n</details>`;
|
||||||
body += hidden_headless_artifacts;
|
|
||||||
body += hidden_debug_artifacts;
|
body += hidden_debug_artifacts;
|
||||||
|
|
||||||
const {data: comments} = await github.rest.issues.listComments({repo, owner, issue_number});
|
const {data: comments} = await github.rest.issues.listComments({repo, owner, issue_number});
|
||||||
|
17
.github/workflows/release.yml
vendored
@ -112,7 +112,6 @@ jobs:
|
|||||||
- name: Publish
|
- name: Publish
|
||||||
run: |
|
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
|
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_sdl2_headless -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained
|
|
||||||
|
|
||||||
- name: Packing Windows builds
|
- name: Packing Windows builds
|
||||||
if: matrix.platform.os == 'windows-latest'
|
if: matrix.platform.os == 'windows-latest'
|
||||||
@ -121,11 +120,6 @@ jobs:
|
|||||||
rm libarmeilleure-jitsupport.dylib
|
rm libarmeilleure-jitsupport.dylib
|
||||||
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd publish_sdl2_headless
|
|
||||||
rm libarmeilleure-jitsupport.dylib
|
|
||||||
7z a ../release_output/nogui-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
|
||||||
popd
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Build AppImage (Linux)
|
- name: Build AppImage (Linux)
|
||||||
@ -172,11 +166,6 @@ jobs:
|
|||||||
chmod +x Ryujinx.sh Ryujinx
|
chmod +x Ryujinx.sh Ryujinx
|
||||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd publish_sdl2_headless
|
|
||||||
chmod +x Ryujinx.sh Ryujinx.Headless.SDL2
|
|
||||||
tar -czvf ../release_output/nogui-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
|
||||||
popd
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Pushing new release
|
- name: Pushing new release
|
||||||
@ -251,15 +240,11 @@ jobs:
|
|||||||
run: |
|
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
|
./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: Publish macOS Ryujinx.Headless.SDL2
|
|
||||||
run: |
|
|
||||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
|
||||||
|
|
||||||
- name: Pushing new release
|
- name: Pushing new release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.version_info.outputs.build_version }}
|
name: ${{ steps.version_info.outputs.build_version }}
|
||||||
artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz"
|
artifacts: "publish/*.tar.gz"
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: ""
|
body: ""
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/>
|
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/>
|
||||||
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/>
|
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.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="Concentus" Version="2.2.0" />
|
<PackageVersion Include="Concentus" Version="2.2.0" />
|
||||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||||
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
||||||
@ -41,10 +42,10 @@
|
|||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||||
<PackageVersion Include="Gommon" Version="2.6.8" />
|
<PackageVersion Include="Gommon" Version="2.7.0.1" />
|
||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||||
<PackageVersion Include="SharpMetal" Version="1.0.0-preview20" />
|
<PackageVersion Include="SharpMetal" Version="1.0.0-preview21" />
|
||||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
|
||||||
|
17
Ryujinx.sln
@ -57,14 +57,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL2.Common", "src\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Headless.SDL2", "src\Ryujinx.Headless.SDL2\Ryujinx.Headless.SDL2.csproj", "{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.Common", "src\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}"
|
||||||
@ -213,10 +209,6 @@ Global
|
|||||||
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@ -225,10 +217,6 @@ Global
|
|||||||
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@ -261,13 +249,12 @@ Global
|
|||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.Build.0 = Release|Any CPU
|
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
@ -13,7 +13,7 @@ mkdir -p AppDir/usr/bin
|
|||||||
|
|
||||||
cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop
|
cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop
|
||||||
cp distribution/linux/appimage/AppRun AppDir/AppRun
|
cp distribution/linux/appimage/AppRun AppDir/AppRun
|
||||||
cp src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png AppDir/Ryujinx.svg
|
cp distribution/misc/Logo.svg AppDir/Ryujinx.svg
|
||||||
|
|
||||||
|
|
||||||
cp -r "$BUILDDIR"/* AppDir/usr/bin/
|
cp -r "$BUILDDIR"/* AppDir/usr/bin/
|
||||||
|
@ -9,20 +9,12 @@ namespace Ryujinx.Audio.Backends.Dummy
|
|||||||
{
|
{
|
||||||
public class DummyHardwareDeviceDriver : IHardwareDeviceDriver
|
public class DummyHardwareDeviceDriver : IHardwareDeviceDriver
|
||||||
{
|
{
|
||||||
private readonly ManualResetEvent _updateRequiredEvent;
|
private readonly ManualResetEvent _updateRequiredEvent = new(false);
|
||||||
private readonly ManualResetEvent _pauseEvent;
|
private readonly ManualResetEvent _pauseEvent = new(true);
|
||||||
|
|
||||||
public static bool IsSupported => true;
|
public static bool IsSupported => true;
|
||||||
|
|
||||||
public float Volume { get; set; }
|
public float Volume { get; set; } = 1f;
|
||||||
|
|
||||||
public DummyHardwareDeviceDriver()
|
|
||||||
{
|
|
||||||
_updateRequiredEvent = new ManualResetEvent(false);
|
|
||||||
_pauseEvent = new ManualResetEvent(true);
|
|
||||||
|
|
||||||
Volume = 1f;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
|
||||||
{
|
{
|
||||||
@ -60,7 +52,7 @@ namespace Ryujinx.Audio.Backends.Dummy
|
|||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
7
src/Ryujinx.BuildValidationTasks/IValidationTask.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace Ryujinx.BuildValidationTasks
|
||||||
|
{
|
||||||
|
public interface IValidationTask
|
||||||
|
{
|
||||||
|
public bool Execute(string projectPath, bool isGitRunner);
|
||||||
|
}
|
||||||
|
}
|
@ -1,73 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.Build.Utilities;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.IO;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Microsoft.Build.Framework;
|
|
||||||
|
|
||||||
namespace Ryujinx.BuildValidationTasks
|
|
||||||
{
|
|
||||||
public class LocaleValidationTask : Task
|
|
||||||
{
|
|
||||||
public override bool Execute()
|
|
||||||
{
|
|
||||||
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
|
||||||
|
|
||||||
if (path.Split(["src"], StringSplitOptions.None).Length == 1)
|
|
||||||
{
|
|
||||||
//i assume that we are in a build directory in the solution dir
|
|
||||||
path = new FileInfo(path).Directory!.Parent!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = path.Split(["src"], StringSplitOptions.None)[0];
|
|
||||||
path = new FileInfo(path).Directory!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
string data;
|
|
||||||
|
|
||||||
using (StreamReader sr = new(path))
|
|
||||||
{
|
|
||||||
data = sr.ReadToEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalesJson json = JsonConvert.DeserializeObject<LocalesJson>(data);
|
|
||||||
|
|
||||||
for (int i = 0; i < json.Locales.Count; i++)
|
|
||||||
{
|
|
||||||
LocalesEntry locale = json.Locales[i];
|
|
||||||
|
|
||||||
foreach (string langCode in json.Languages.Where(it => !locale.Translations.ContainsKey(it)))
|
|
||||||
{
|
|
||||||
locale.Translations.Add(langCode, string.Empty);
|
|
||||||
Log.LogMessage(MessageImportance.High, $"Added '{langCode}' to Locale '{locale.ID}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
|
|
||||||
json.Locales[i] = locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
string jsonString = JsonConvert.SerializeObject(json, Formatting.Indented);
|
|
||||||
|
|
||||||
using (StreamWriter sw = new(path))
|
|
||||||
{
|
|
||||||
sw.Write(jsonString);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LocalesJson
|
|
||||||
{
|
|
||||||
public List<string> Languages { get; set; }
|
|
||||||
public List<LocalesEntry> Locales { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LocalesEntry
|
|
||||||
{
|
|
||||||
public string ID { get; set; }
|
|
||||||
public Dictionary<string, string> Translations { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
117
src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
|
||||||
|
namespace Ryujinx.BuildValidationTasks
|
||||||
|
{
|
||||||
|
public class LocalesValidationTask : IValidationTask
|
||||||
|
{
|
||||||
|
public LocalesValidationTask() { }
|
||||||
|
|
||||||
|
public bool Execute(string projectPath, bool isGitRunner)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Running Locale Validation Task...");
|
||||||
|
|
||||||
|
string path = projectPath + "src/Ryujinx/Assets/locales.json";
|
||||||
|
string data;
|
||||||
|
|
||||||
|
using (StreamReader sr = new(path))
|
||||||
|
{
|
||||||
|
data = sr.ReadToEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalesJson json;
|
||||||
|
|
||||||
|
if (isGitRunner && data.Contains("\r\n"))
|
||||||
|
throw new FormatException("locales.json is using CRLF line endings! It should be using LF line endings, build locally to fix...");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
json = JsonSerializer.Deserialize<LocalesJson>(data);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (JsonException e)
|
||||||
|
{
|
||||||
|
throw new JsonException(e.Message); //shorter and easier stacktrace
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool encounteredIssue = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < json.Locales.Count; i++)
|
||||||
|
{
|
||||||
|
LocalesEntry locale = json.Locales[i];
|
||||||
|
|
||||||
|
foreach (string langCode in json.Languages.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 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)
|
||||||
|
throw new JsonException("1 or more locales are invalid!");
|
||||||
|
|
||||||
|
JsonSerializerOptions jsonOptions = new JsonSerializerOptions()
|
||||||
|
{
|
||||||
|
WriteIndented = true,
|
||||||
|
NewLine = "\n",
|
||||||
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||||
|
};
|
||||||
|
|
||||||
|
string jsonString = JsonSerializer.Serialize(json, jsonOptions);
|
||||||
|
|
||||||
|
using (StreamWriter sw = new(path))
|
||||||
|
{
|
||||||
|
sw.Write(jsonString);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("Finished Locale Validation Task!");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LocalesJson
|
||||||
|
{
|
||||||
|
public List<string> Languages { get; set; }
|
||||||
|
public List<LocalesEntry> Locales { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LocalesEntry
|
||||||
|
{
|
||||||
|
public string ID { get; set; }
|
||||||
|
public Dictionary<string, string> Translations { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
src/Ryujinx.BuildValidationTasks/Program.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.BuildValidationTasks
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// Display the number of command line arguments.
|
||||||
|
if (args.Length == 0)
|
||||||
|
throw new ArgumentException("Error: too few arguments!");
|
||||||
|
|
||||||
|
string path = args[0];
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
throw new ArgumentException("Error: path is null or empty!");
|
||||||
|
|
||||||
|
if (!Path.Exists(path))
|
||||||
|
throw new FileLoadException($"path {{{path}}} does not exist!");
|
||||||
|
|
||||||
|
path = Path.GetFullPath(path);
|
||||||
|
|
||||||
|
if (!Directory.GetDirectories(path).Contains($"{path}src"))
|
||||||
|
throw new FileLoadException($"path {{{path}}} is not a valid ryujinx project!");
|
||||||
|
|
||||||
|
bool isGitRunner = path.Contains("runner") || path.Contains("D:\\a\\Ryujinx\\Ryujinx");
|
||||||
|
if (isGitRunner)
|
||||||
|
Console.WriteLine("Is Git Runner!");
|
||||||
|
|
||||||
|
// Run tasks
|
||||||
|
// Pass extra info needed in the task constructors
|
||||||
|
new LocalesValidationTask().Execute(path, isGitRunner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,17 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<OutputType>Exe</OutputType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<Target Name="PostBuildTarget" AfterTargets="AfterBuild">
|
||||||
<PackageReference Include="Microsoft.Build.Utilities.Core" />
|
<Message Text="Running Validation Project" Importance="high" />
|
||||||
<PackageReference Include="Newtonsoft.Json" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<UsingTask TaskName="Ryujinx.BuildValidationTasks.LocaleValidationTask" TaskFactory="TaskHostFactory" AssemblyFile="$(OutDir)Ryujinx.BuildValidationTasks.dll" />
|
<Exec WorkingDirectory="$(ProjectDir)bin\Debug\$(TargetFramework)\"
|
||||||
|
Command="dotnet Ryujinx.BuildValidationTasks.dll "$(ProjectDir)..\..\\""
|
||||||
<Target Name="LocalesJsonValidation" AfterTargets="AfterRebuild">
|
ConsoleToMsBuild="true"
|
||||||
<LocaleValidationTask />
|
Condition="'$(RuntimeIdentifier)' == ''"
|
||||||
|
/>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -35,6 +35,8 @@ namespace Ryujinx.Common.Configuration
|
|||||||
#pragma warning restore IDE0055
|
#pragma warning restore IDE0055
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static float ToFloatY(this AspectRatio aspectRatio)
|
public static float ToFloatY(this AspectRatio aspectRatio)
|
||||||
{
|
{
|
||||||
|
60
src/Ryujinx.Common/Configuration/DirtyHack.cs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
using Gommon;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Configuration
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum DirtyHack : byte
|
||||||
|
{
|
||||||
|
Xc2MenuSoftlockFix = 1,
|
||||||
|
ShaderTranslationDelay = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct EnabledDirtyHack(DirtyHack hack, int value)
|
||||||
|
{
|
||||||
|
public DirtyHack Hack => hack;
|
||||||
|
public int Value => value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public ulong Pack() => Raw.PackBitFields(PackedFormat);
|
||||||
|
|
||||||
|
public static EnabledDirtyHack Unpack(ulong packedHack)
|
||||||
|
{
|
||||||
|
var unpackedFields = packedHack.UnpackBitFields(PackedFormat);
|
||||||
|
if (unpackedFields is not [var hack, var value])
|
||||||
|
throw new ArgumentException(nameof(packedHack));
|
||||||
|
|
||||||
|
return new EnabledDirtyHack((DirtyHack)hack, (int)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint[] Raw => [(uint)Hack, (uint)Value.CoerceAtLeast(0)];
|
||||||
|
|
||||||
|
public static readonly byte[] PackedFormat = [8, 32];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DirtyHacks : Dictionary<DirtyHack, int>
|
||||||
|
{
|
||||||
|
public DirtyHacks(IEnumerable<EnabledDirtyHack> hacks)
|
||||||
|
=> hacks.ForEach(edh => Add(edh.Hack, edh.Value));
|
||||||
|
|
||||||
|
public DirtyHacks(ulong[] packedHacks) : this(packedHacks.Select(EnabledDirtyHack.Unpack)) {}
|
||||||
|
|
||||||
|
public ulong[] PackEntries()
|
||||||
|
=> Entries.Select(it => it.Pack()).ToArray();
|
||||||
|
|
||||||
|
public EnabledDirtyHack[] Entries
|
||||||
|
=> this
|
||||||
|
.Select(it => new EnabledDirtyHack(it.Key, it.Value))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
public static implicit operator DirtyHacks(EnabledDirtyHack[] hacks) => new(hacks);
|
||||||
|
public static implicit operator DirtyHacks(ulong[] packedHacks) => new(packedHacks);
|
||||||
|
|
||||||
|
public new int this[DirtyHack hack] => TryGetValue(hack, out var value) ? value : -1;
|
||||||
|
|
||||||
|
public bool IsEnabled(DirtyHack hack) => ContainsKey(hack);
|
||||||
|
}
|
||||||
|
}
|
@ -9,5 +9,6 @@ namespace Ryujinx.Common.Configuration
|
|||||||
Bilinear,
|
Bilinear,
|
||||||
Nearest,
|
Nearest,
|
||||||
Fsr,
|
Fsr,
|
||||||
|
Area,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@ namespace Ryujinx.Common
|
|||||||
public static class StreamExtensions
|
public static class StreamExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Writes a <see cref="ReadOnlySpan{int}" /> to this stream.
|
/// Writes an int span to this stream.
|
||||||
///
|
///
|
||||||
/// This default implementation converts each buffer value to a stack-allocated
|
/// This default implementation converts each buffer value to a stack-allocated
|
||||||
/// byte array, then writes it to the Stream using <cref="System.Stream.Write(byte[])" />.
|
/// byte array, then writes it to the Stream using <see cref="Stream.Write(ReadOnlySpan{byte})" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stream">The stream to be written to</param>
|
/// <param name="stream">The stream to be written to</param>
|
||||||
/// <param name="buffer">The buffer of values to be written</param>
|
/// <param name="buffer">The buffer of values to be written</param>
|
||||||
|
@ -3,7 +3,7 @@ using System;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
public static partial class ConsoleHelper
|
public static partial class ConsoleHelper
|
||||||
{
|
{
|
@ -8,7 +8,7 @@ using System.Linq;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
public static partial class FileAssociationHelper
|
public static partial class FileAssociationHelper
|
||||||
{
|
{
|
||||||
@ -132,7 +132,7 @@ namespace Ryujinx.UI.Common.Helper
|
|||||||
|
|
||||||
if (uninstall)
|
if (uninstall)
|
||||||
{
|
{
|
||||||
// If the types don't already exist, there's nothing to do and we can call this operation successful.
|
// If the types don't already exist, there's nothing to do, and we can call this operation successful.
|
||||||
if (!AreMimeTypesRegisteredWindows())
|
if (!AreMimeTypesRegisteredWindows())
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
@ -3,7 +3,7 @@ using System.Diagnostics;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("linux")]
|
[SupportedOSPlatform("linux")]
|
||||||
public static class LinuxHelper
|
public static class LinuxHelper
|
@ -2,7 +2,7 @@ using System;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("macos")]
|
[SupportedOSPlatform("macos")]
|
||||||
public static partial class ObjectiveC
|
public static partial class ObjectiveC
|
@ -5,7 +5,7 @@ using System.Diagnostics;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
public static partial class OpenHelper
|
public static partial class OpenHelper
|
||||||
{
|
{
|
@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
@ -157,21 +158,16 @@ namespace Ryujinx.Common.Logging
|
|||||||
_time.Restart();
|
_time.Restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ILogTarget GetTarget(string targetName)
|
private static ILogTarget GetTarget(string targetName)
|
||||||
{
|
=> _logTargets.FirstOrDefault(target => target.Name.Equals(targetName));
|
||||||
foreach (var target in _logTargets)
|
|
||||||
{
|
|
||||||
if (target.Name.Equals(targetName))
|
|
||||||
{
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddTarget(ILogTarget target)
|
public static void AddTarget(ILogTarget target)
|
||||||
{
|
{
|
||||||
|
if (_logTargets.Any(t => t.Name == target.Name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_logTargets.Add(target);
|
_logTargets.Add(target);
|
||||||
|
|
||||||
Updated += target.Log;
|
Updated += target.Log;
|
||||||
|
@ -27,11 +27,7 @@ namespace Ryujinx.Common.Logging.Targets
|
|||||||
|
|
||||||
private readonly int _overflowTimeout;
|
private readonly int _overflowTimeout;
|
||||||
|
|
||||||
string ILogTarget.Name { get => _target.Name; }
|
string ILogTarget.Name => _target.Name;
|
||||||
|
|
||||||
public AsyncLogTargetWrapper(ILogTarget target)
|
|
||||||
: this(target, -1)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public AsyncLogTargetWrapper(ILogTarget target, int queueLimit = -1, AsyncLogTargetOverflowAction overflowAction = AsyncLogTargetOverflowAction.Block)
|
public AsyncLogTargetWrapper(ILogTarget target, int queueLimit = -1, AsyncLogTargetOverflowAction overflowAction = AsyncLogTargetOverflowAction.Block)
|
||||||
{
|
{
|
||||||
|
@ -53,6 +53,9 @@ namespace Ryujinx.Common
|
|||||||
{
|
{
|
||||||
public static void LogValueChange<T>(LogClass logClass, ReactiveEventArgs<T> eventArgs, string valueName)
|
public static void LogValueChange<T>(LogClass logClass, ReactiveEventArgs<T> eventArgs, string valueName)
|
||||||
{
|
{
|
||||||
|
if (eventArgs.AreValuesEqual)
|
||||||
|
return;
|
||||||
|
|
||||||
string message = string.Create(CultureInfo.InvariantCulture, $"{valueName} set to: {eventArgs.NewValue}");
|
string message = string.Create(CultureInfo.InvariantCulture, $"{valueName} set to: {eventArgs.NewValue}");
|
||||||
|
|
||||||
Logger.Info?.Print(logClass, message);
|
Logger.Info?.Print(logClass, message);
|
||||||
@ -65,5 +68,22 @@ namespace Ryujinx.Common
|
|||||||
{
|
{
|
||||||
public T OldValue { get; } = oldValue;
|
public T OldValue { get; } = oldValue;
|
||||||
public T NewValue { get; } = newValue;
|
public T NewValue { get; } = newValue;
|
||||||
|
|
||||||
|
public bool AreValuesEqual
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (OldValue == null && NewValue == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (OldValue == null && NewValue != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (OldValue != null && NewValue == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return OldValue!.Equals(NewValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ namespace Ryujinx.Common
|
|||||||
{
|
{
|
||||||
public static class TitleIDs
|
public static class TitleIDs
|
||||||
{
|
{
|
||||||
|
public static ReactiveObject<Optional<string>> CurrentApplication { get; set; } = new();
|
||||||
|
|
||||||
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend)
|
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend)
|
||||||
{
|
{
|
||||||
switch (currentBackend)
|
switch (currentBackend)
|
||||||
@ -33,6 +35,8 @@ namespace Ryujinx.Common
|
|||||||
"010028600EBDA000", // Mario 3D World
|
"010028600EBDA000", // Mario 3D World
|
||||||
"0100152000022000", // Mario Kart 8 Deluxe
|
"0100152000022000", // Mario Kart 8 Deluxe
|
||||||
"01005CA01580E000", // Persona 5
|
"01005CA01580E000", // Persona 5
|
||||||
|
"0100187003A36000", // Pokémon: Let's Go, Evoli!
|
||||||
|
"010003f003a34000", // Pokémon: Let's Go, Pikachu!
|
||||||
"01008C0016544000", // Sea of Stars
|
"01008C0016544000", // Sea of Stars
|
||||||
"01006A800016E000", // Smash Ultimate
|
"01006A800016E000", // Smash Ultimate
|
||||||
"0100000000010000", // Super Mario Odyessy
|
"0100000000010000", // Super Mario Odyessy
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
namespace Ryujinx.UI.Common
|
namespace Ryujinx.Common.UI
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represent a common error that could be reported to the user by the emulator.
|
/// Represent a common error that could be reported to the user by the emulator.
|
@ -40,5 +40,35 @@ namespace Ryujinx.Common
|
|||||||
|
|
||||||
return (value >> 32) | (value << 32);
|
return (value >> 32) | (value << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Never actually written bit packing logic before, so I looked it up.
|
||||||
|
// This code is from https://gist.github.com/Alan-FGR/04938e93e2bffdf5802ceb218a37c195
|
||||||
|
|
||||||
|
public static ulong PackBitFields(this uint[] values, byte[] bitFields)
|
||||||
|
{
|
||||||
|
ulong retVal = values[0]; //we set the first value right away
|
||||||
|
for (int f = 1; f < values.Length; f++)
|
||||||
|
{
|
||||||
|
retVal <<= bitFields[f]; // we shift the previous value
|
||||||
|
retVal += values[f];// and add our current value
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint[] UnpackBitFields(this ulong packed, byte[] bitFields)
|
||||||
|
{
|
||||||
|
int fields = bitFields.Length - 1; // number of fields to unpack
|
||||||
|
uint[] retArr = new uint[fields + 1]; // init return array
|
||||||
|
int curPos = 0; // current field bit position (start)
|
||||||
|
int lastEnd; // position where last field ended
|
||||||
|
for (int f = fields; f >= 0; f--) // loop from last
|
||||||
|
{
|
||||||
|
lastEnd = curPos; // we store where the last value ended
|
||||||
|
curPos += bitFields[f]; // we get where the current value starts
|
||||||
|
int leftShift = 64 - curPos; // we figure how much left shift we gotta apply for the other numbers to overflow into oblivion
|
||||||
|
retArr[f] = (uint)((packed << leftShift) >> leftShift + lastEnd); // we do magic
|
||||||
|
}
|
||||||
|
return retArr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
namespace Ryujinx.Graphics.GAL
|
|
||||||
{
|
|
||||||
public enum AntiAliasing
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Fxaa,
|
|
||||||
SmaaLow,
|
|
||||||
SmaaMedium,
|
|
||||||
SmaaHigh,
|
|
||||||
SmaaUltra,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
namespace Ryujinx.Graphics.GAL
|
|
||||||
{
|
|
||||||
public enum ScalingFilter
|
|
||||||
{
|
|
||||||
Bilinear,
|
|
||||||
Nearest,
|
|
||||||
Fsr,
|
|
||||||
Area,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,5 @@
|
|||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Graphics.Device;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
||||||
@ -90,6 +91,13 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
/// Support buffer updater.
|
/// Support buffer updater.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal SupportBufferUpdater SupportBufferUpdater { get; }
|
internal SupportBufferUpdater SupportBufferUpdater { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enabled dirty hacks.
|
||||||
|
/// Used for workarounds to emulator bugs we can't fix/don't know how to fix yet.
|
||||||
|
/// </summary>
|
||||||
|
internal DirtyHacks DirtyHacks { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Host hardware capabilities.
|
/// Host hardware capabilities.
|
||||||
@ -113,7 +121,7 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
/// Creates a new instance of the GPU emulation context.
|
/// Creates a new instance of the GPU emulation context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="renderer">Host renderer</param>
|
/// <param name="renderer">Host renderer</param>
|
||||||
public GpuContext(IRenderer renderer)
|
public GpuContext(IRenderer renderer, DirtyHacks hacks)
|
||||||
{
|
{
|
||||||
Renderer = renderer;
|
Renderer = renderer;
|
||||||
|
|
||||||
@ -136,6 +144,8 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
|
|
||||||
SupportBufferUpdater = new SupportBufferUpdater(renderer);
|
SupportBufferUpdater = new SupportBufferUpdater(renderer);
|
||||||
|
|
||||||
|
DirtyHacks = hacks;
|
||||||
|
|
||||||
_firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
|
_firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
/// Enables or disables high-level emulation of common GPU Macro code.
|
/// Enables or disables high-level emulation of common GPU Macro code.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool EnableMacroHLE = true;
|
public static bool EnableMacroHLE = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Title id of the current running game.
|
/// Title id of the current running game.
|
||||||
/// Used by the shader cache.
|
/// Used by the shader cache.
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
@ -366,6 +367,9 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (_context.DirtyHacks.IsEnabled(DirtyHack.ShaderTranslationDelay))
|
||||||
|
Thread.Sleep(_context.DirtyHacks[DirtyHack.ShaderTranslationDelay]);
|
||||||
|
|
||||||
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);
|
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);
|
||||||
_asyncTranslationQueue.Add(asyncTranslation, _cancellationToken);
|
_asyncTranslationQueue.Add(asyncTranslation, _cancellationToken);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using SharpMetal;
|
using SharpMetal;
|
||||||
|
using SharpMetal.Foundation;
|
||||||
using SharpMetal.ObjectiveCCore;
|
using SharpMetal.ObjectiveCCore;
|
||||||
using SharpMetal.QuartzCore;
|
using SharpMetal.QuartzCore;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
@ -9,22 +10,13 @@ namespace Ryujinx.Graphics.Metal.SharpMetalExtensions
|
|||||||
[SupportedOSPlatform("macOS")]
|
[SupportedOSPlatform("macOS")]
|
||||||
public static class CAMetalLayerExtensions
|
public static class CAMetalLayerExtensions
|
||||||
{
|
{
|
||||||
private static readonly Selector sel_displaySyncEnabled = "displaySyncEnabled";
|
|
||||||
private static readonly Selector sel_setDisplaySyncEnabled = "setDisplaySyncEnabled:";
|
|
||||||
|
|
||||||
private static readonly Selector sel_developerHUDProperties = "developerHUDProperties";
|
private static readonly Selector sel_developerHUDProperties = "developerHUDProperties";
|
||||||
private static readonly Selector sel_setDeveloperHUDProperties = "setDeveloperHUDProperties:";
|
private static readonly Selector sel_setDeveloperHUDProperties = "setDeveloperHUDProperties:";
|
||||||
|
|
||||||
public static bool IsDisplaySyncEnabled(this CAMetalLayer metalLayer)
|
|
||||||
=> ObjectiveCRuntime.bool_objc_msgSend(metalLayer.NativePtr, sel_displaySyncEnabled);
|
|
||||||
|
|
||||||
public static void SetDisplaySyncEnabled(this CAMetalLayer metalLayer, bool enabled)
|
public static NSDictionary GetDeveloperHudProperties(this CAMetalLayer metalLayer)
|
||||||
=> ObjectiveCRuntime.objc_msgSend(metalLayer.NativePtr, sel_setDisplaySyncEnabled, enabled);
|
=> new(ObjectiveCRuntime.IntPtr_objc_msgSend(metalLayer.NativePtr, sel_developerHUDProperties));
|
||||||
|
|
||||||
public static nint GetDeveloperHudProperties(this CAMetalLayer metalLayer)
|
public static void SetDeveloperHudProperties(this CAMetalLayer metalLayer, NSDictionary dictionary)
|
||||||
=> ObjectiveCRuntime.IntPtr_objc_msgSend(metalLayer.NativePtr, sel_developerHUDProperties);
|
=> ObjectiveCRuntime.objc_msgSend(metalLayer.NativePtr, sel_setDeveloperHUDProperties, dictionary);
|
||||||
|
|
||||||
public static void SetDeveloperHudProperties(this CAMetalLayer metalLayer, nint dictionaryPointer)
|
|
||||||
=> ObjectiveCRuntime.objc_msgSend(metalLayer.NativePtr, sel_setDeveloperHUDProperties, dictionaryPointer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
src/Ryujinx.Graphics.Metal.SharpMetalExtensions/NSHelper.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using SharpMetal.Foundation;
|
||||||
|
using SharpMetal.ObjectiveCCore;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Metal.SharpMetalExtensions
|
||||||
|
{
|
||||||
|
[SupportedOSPlatform("macOS")]
|
||||||
|
public static class NSHelper
|
||||||
|
{
|
||||||
|
private static readonly Selector sel_getCStringMaxLengthEncoding = "getCString:maxLength:encoding:";
|
||||||
|
private static readonly Selector sel_stringWithUTF8String = "stringWithUTF8String:";
|
||||||
|
|
||||||
|
public static unsafe string ToDotNetString(this NSString source)
|
||||||
|
{
|
||||||
|
char[] sourceBuffer = new char[source.Length];
|
||||||
|
fixed (char* pSourceBuffer = sourceBuffer)
|
||||||
|
{
|
||||||
|
ObjectiveC.bool_objc_msgSend(source,
|
||||||
|
sel_getCStringMaxLengthEncoding,
|
||||||
|
pSourceBuffer,
|
||||||
|
source.MaximumLengthOfBytes(NSStringEncoding.UTF16) + 1,
|
||||||
|
(ulong)NSStringEncoding.UTF16);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new string(sourceBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NSString ToNSString(this string source)
|
||||||
|
=> new(ObjectiveC.IntPtr_objc_msgSend(new ObjectiveCClass(nameof(NSString)), sel_stringWithUTF8String, source));
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -2,13 +2,10 @@ using Ryujinx.Common.Configuration;
|
|||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Metal.Effects;
|
using Ryujinx.Graphics.Metal.Effects;
|
||||||
using Ryujinx.Graphics.Metal.SharpMetalExtensions;
|
|
||||||
using SharpMetal.ObjectiveCCore;
|
using SharpMetal.ObjectiveCCore;
|
||||||
using SharpMetal.QuartzCore;
|
using SharpMetal.QuartzCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
using AntiAliasing = Ryujinx.Graphics.GAL.AntiAliasing;
|
|
||||||
using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Metal
|
namespace Ryujinx.Graphics.Metal
|
||||||
{
|
{
|
||||||
@ -18,20 +15,22 @@ namespace Ryujinx.Graphics.Metal
|
|||||||
public bool ScreenCaptureRequested { get; set; }
|
public bool ScreenCaptureRequested { get; set; }
|
||||||
|
|
||||||
private readonly MetalRenderer _renderer;
|
private readonly MetalRenderer _renderer;
|
||||||
private readonly CAMetalLayer _metalLayer;
|
private CAMetalLayer _metalLayer;
|
||||||
|
|
||||||
private int _width;
|
private int _width;
|
||||||
private int _height;
|
private int _height;
|
||||||
|
|
||||||
private int _requestedWidth;
|
private int _requestedWidth;
|
||||||
private int _requestedHeight;
|
private int _requestedHeight;
|
||||||
|
|
||||||
// private bool _vsyncEnabled;
|
|
||||||
private AntiAliasing _currentAntiAliasing;
|
private AntiAliasing _currentAntiAliasing;
|
||||||
private bool _updateEffect;
|
private bool _updateEffect;
|
||||||
private IPostProcessingEffect _effect;
|
private IPostProcessingEffect _effect;
|
||||||
private IScalingFilter _scalingFilter;
|
private IScalingFilter _scalingFilter;
|
||||||
private bool _isLinear;
|
private bool _isLinear;
|
||||||
|
|
||||||
|
public bool IsVSyncEnabled => _metalLayer.DisplaySyncEnabled;
|
||||||
|
|
||||||
// private float _scalingFilterLevel;
|
// private float _scalingFilterLevel;
|
||||||
private bool _updateScalingFilter;
|
private bool _updateScalingFilter;
|
||||||
private ScalingFilter _currentScalingFilter;
|
private ScalingFilter _currentScalingFilter;
|
||||||
@ -43,7 +42,7 @@ namespace Ryujinx.Graphics.Metal
|
|||||||
_metalLayer = metalLayer;
|
_metalLayer = metalLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void ResizeIfNeeded()
|
private void ResizeIfNeeded()
|
||||||
{
|
{
|
||||||
if (_requestedWidth != 0 && _requestedHeight != 0)
|
if (_requestedWidth != 0 && _requestedHeight != 0)
|
||||||
{
|
{
|
||||||
@ -57,7 +56,7 @@ namespace Ryujinx.Graphics.Metal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback)
|
public void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback)
|
||||||
{
|
{
|
||||||
if (_renderer.Pipeline is Pipeline pipeline && texture is Texture tex)
|
if (_renderer.Pipeline is Pipeline pipeline && texture is Texture tex)
|
||||||
{
|
{
|
||||||
@ -144,15 +143,7 @@ namespace Ryujinx.Graphics.Metal
|
|||||||
|
|
||||||
public void ChangeVSyncMode(VSyncMode vSyncMode)
|
public void ChangeVSyncMode(VSyncMode vSyncMode)
|
||||||
{
|
{
|
||||||
switch (vSyncMode)
|
_metalLayer.DisplaySyncEnabled = vSyncMode is VSyncMode.Switch;
|
||||||
{
|
|
||||||
case VSyncMode.Unbounded:
|
|
||||||
_metalLayer.SetDisplaySyncEnabled(false);
|
|
||||||
break;
|
|
||||||
case VSyncMode.Switch:
|
|
||||||
_metalLayer.SetDisplaySyncEnabled(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAntiAliasing(AntiAliasing effect)
|
public void SetAntiAliasing(AntiAliasing effect)
|
||||||
|
@ -2,8 +2,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
internal enum BitDepth
|
internal enum BitDepth
|
||||||
{
|
{
|
||||||
Bits8 = 8, /**< 8 bits */
|
Bits8 = 8, // < 8 bits
|
||||||
Bits10 = 10, /**< 10 bits */
|
Bits10 = 10, // < 10 bits
|
||||||
Bits12 = 12, /**< 12 bits */
|
Bits12 = 12, // < 12 bits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,6 @@ using Ryujinx.Graphics.OpenGL.Effects;
|
|||||||
using Ryujinx.Graphics.OpenGL.Effects.Smaa;
|
using Ryujinx.Graphics.OpenGL.Effects.Smaa;
|
||||||
using Ryujinx.Graphics.OpenGL.Image;
|
using Ryujinx.Graphics.OpenGL.Image;
|
||||||
using System;
|
using System;
|
||||||
using AntiAliasing = Ryujinx.Graphics.GAL.AntiAliasing;
|
|
||||||
using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Gommon;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
@ -890,7 +891,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private void PrintGpuInformation()
|
private void PrintGpuInformation()
|
||||||
{
|
{
|
||||||
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
|
string gpuInfoMessage = $"{GpuRenderer} ({GpuVersion})";
|
||||||
|
if (!GpuRenderer.StartsWithIgnoreCase(GpuVendor))
|
||||||
|
gpuInfoMessage = gpuInfoMessage.Prepend(GpuVendor);
|
||||||
|
|
||||||
|
Logger.Notice.Print(LogClass.Gpu, gpuInfoMessage);
|
||||||
|
|
||||||
Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB");
|
Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,8 +5,6 @@ using Silk.NET.Vulkan;
|
|||||||
using Silk.NET.Vulkan.Extensions.KHR;
|
using Silk.NET.Vulkan.Extensions.KHR;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AntiAliasing = Ryujinx.Graphics.GAL.AntiAliasing;
|
|
||||||
using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter;
|
|
||||||
using VkFormat = Silk.NET.Vulkan.Format;
|
using VkFormat = Silk.NET.Vulkan.Format;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using System;
|
using System;
|
||||||
using AntiAliasing = Ryujinx.Graphics.GAL.AntiAliasing;
|
|
||||||
using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
|
@ -188,6 +188,11 @@ namespace Ryujinx.HLE
|
|||||||
/// An action called when HLE force a refresh of output after docked mode changed.
|
/// An action called when HLE force a refresh of output after docked mode changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action RefreshInputConfig { internal get; set; }
|
public Action RefreshInputConfig { internal get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The desired hacky workarounds.
|
||||||
|
/// </summary>
|
||||||
|
public EnabledDirtyHack[] Hacks { internal get; set; }
|
||||||
|
|
||||||
public HLEConfiguration(VirtualFileSystem virtualFileSystem,
|
public HLEConfiguration(VirtualFileSystem virtualFileSystem,
|
||||||
LibHacHorizonManager libHacHorizonManager,
|
LibHacHorizonManager libHacHorizonManager,
|
||||||
@ -218,7 +223,8 @@ namespace Ryujinx.HLE
|
|||||||
bool multiplayerDisableP2p,
|
bool multiplayerDisableP2p,
|
||||||
string multiplayerLdnPassphrase,
|
string multiplayerLdnPassphrase,
|
||||||
string multiplayerLdnServer,
|
string multiplayerLdnServer,
|
||||||
int customVSyncInterval)
|
int customVSyncInterval,
|
||||||
|
EnabledDirtyHack[] dirtyHacks = null)
|
||||||
{
|
{
|
||||||
VirtualFileSystem = virtualFileSystem;
|
VirtualFileSystem = virtualFileSystem;
|
||||||
LibHacHorizonManager = libHacHorizonManager;
|
LibHacHorizonManager = libHacHorizonManager;
|
||||||
@ -250,6 +256,7 @@ namespace Ryujinx.HLE
|
|||||||
MultiplayerDisableP2p = multiplayerDisableP2p;
|
MultiplayerDisableP2p = multiplayerDisableP2p;
|
||||||
MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
|
MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
|
||||||
MultiplayerLdnServer = multiplayerLdnServer;
|
MultiplayerLdnServer = multiplayerLdnServer;
|
||||||
|
Hacks = dirtyHacks ?? [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Gommon;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
@ -6,12 +7,13 @@ using System;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||||
{
|
{
|
||||||
class AccountSaveDataManager
|
public class AccountSaveDataManager
|
||||||
{
|
{
|
||||||
private readonly string _profilesJsonPath = Path.Join(AppDataManager.BaseDirPath, "system", "Profiles.json");
|
private static readonly string _profilesJsonPath = Path.Join(AppDataManager.BaseDirPath, "system", "Profiles.json");
|
||||||
|
|
||||||
private static readonly ProfilesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly ProfilesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
@ -49,6 +51,16 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Optional<UserProfile> GetLastUsedUser()
|
||||||
|
{
|
||||||
|
ProfilesJson profilesJson = JsonHelper.DeserializeFromFile(_profilesJsonPath, _serializerContext.ProfilesJson);
|
||||||
|
|
||||||
|
return profilesJson.Profiles
|
||||||
|
.FindFirst(profile => profile.AccountState == AccountState.Open)
|
||||||
|
.Convert(profileJson => new UserProfile(new UserId(profileJson.UserId), profileJson.Name,
|
||||||
|
profileJson.Image, profileJson.LastModifiedTimestamp));
|
||||||
|
}
|
||||||
|
|
||||||
public void Save(ConcurrentDictionary<string, UserProfile> profiles)
|
public void Save(ConcurrentDictionary<string, UserProfile> profiles)
|
||||||
{
|
{
|
||||||
ProfilesJson profilesJson = new()
|
ProfilesJson profilesJson = new()
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
using LibHac;
|
using LibHac;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Sf;
|
using LibHac.Sf;
|
||||||
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
||||||
{
|
{
|
||||||
@ -13,6 +16,8 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
|||||||
_baseStorage = SharedRef<LibHac.FsSrv.Sf.IStorage>.CreateMove(ref baseStorage);
|
_baseStorage = SharedRef<LibHac.FsSrv.Sf.IStorage>.CreateMove(ref baseStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const string Xc2TitleId = "0100e95004038000";
|
||||||
|
|
||||||
[CommandCmif(0)]
|
[CommandCmif(0)]
|
||||||
// Read(u64 offset, u64 length) -> buffer<u8, 0x46, 0> buffer
|
// Read(u64 offset, u64 length) -> buffer<u8, 0x46, 0> buffer
|
||||||
public ResultCode Read(ServiceCtx context)
|
public ResultCode Read(ServiceCtx context)
|
||||||
@ -33,6 +38,13 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
|||||||
|
|
||||||
using var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true);
|
using var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true);
|
||||||
Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size);
|
Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size);
|
||||||
|
|
||||||
|
if (context.Device.DirtyHacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix) && TitleIDs.CurrentApplication.Value == Xc2TitleId)
|
||||||
|
{
|
||||||
|
// Add a load-bearing sleep to avoid XC2 softlock
|
||||||
|
// https://web.archive.org/web/20240728045136/https://github.com/Ryujinx/Ryujinx/issues/2357
|
||||||
|
Thread.Sleep(2);
|
||||||
|
}
|
||||||
|
|
||||||
return (ResultCode)result.Value;
|
return (ResultCode)result.Value;
|
||||||
}
|
}
|
||||||
|
@ -114,10 +114,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string usedCharacterStr = BitConverter.ToString(usedCharacter).Replace("-", "");
|
string usedCharacterStr = Convert.ToHexString(usedCharacter);
|
||||||
string variationStr = BitConverter.ToString(variation).Replace("-", "");
|
string variationStr = Convert.ToHexString(variation);
|
||||||
string amiiboIDStr = BitConverter.ToString(amiiboID).Replace("-", "");
|
string amiiboIDStr = Convert.ToHexString(amiiboID);
|
||||||
string setIDStr = BitConverter.ToString(setID).Replace("-", "");
|
string setIDStr = Convert.ToHexString(setID);
|
||||||
string head = usedCharacterStr + variationStr;
|
string head = usedCharacterStr + variationStr;
|
||||||
string tail = amiiboIDStr + setIDStr + "02";
|
string tail = amiiboIDStr + setIDStr + "02";
|
||||||
string finalID = head + tail;
|
string finalID = head + tail;
|
||||||
@ -289,8 +289,8 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
|
|||||||
|
|
||||||
private static void LogFinalData(byte[] titleId, byte[] appId, string head, string tail, string finalID, string nickName, DateTime initDateTime, DateTime writeDateTime, ushort settingsValue, ushort writeCounterValue, byte[] applicationAreas)
|
private static void LogFinalData(byte[] titleId, byte[] appId, string head, string tail, string finalID, string nickName, DateTime initDateTime, DateTime writeDateTime, ushort settingsValue, ushort writeCounterValue, byte[] applicationAreas)
|
||||||
{
|
{
|
||||||
Logger.Debug?.Print(LogClass.ServiceNfp, $"Title ID: 0x{BitConverter.ToString(titleId).Replace("-", "")}");
|
Logger.Debug?.Print(LogClass.ServiceNfp, $"Title ID: 0x{Convert.ToHexString(titleId)}");
|
||||||
Logger.Debug?.Print(LogClass.ServiceNfp, $"Application Program ID: 0x{BitConverter.ToString(appId).Replace("-", "")}");
|
Logger.Debug?.Print(LogClass.ServiceNfp, $"Application Program ID: 0x{Convert.ToHexString(appId)}");
|
||||||
Logger.Debug?.Print(LogClass.ServiceNfp, $"Head: {head}");
|
Logger.Debug?.Print(LogClass.ServiceNfp, $"Head: {head}");
|
||||||
Logger.Debug?.Print(LogClass.ServiceNfp, $"Tail: {tail}");
|
Logger.Debug?.Print(LogClass.ServiceNfp, $"Tail: {tail}");
|
||||||
Logger.Debug?.Print(LogClass.ServiceNfp, $"Final ID: {finalID}");
|
Logger.Debug?.Print(LogClass.ServiceNfp, $"Final ID: {finalID}");
|
||||||
|
@ -4,8 +4,10 @@ using LibHac.Fs.Fsa;
|
|||||||
using LibHac.Loader;
|
using LibHac.Loader;
|
||||||
using LibHac.Ns;
|
using LibHac.Ns;
|
||||||
using LibHac.Tools.FsSystem;
|
using LibHac.Tools.FsSystem;
|
||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.HLE.Loaders.Executables;
|
using Ryujinx.HLE.Loaders.Executables;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
@ -102,7 +104,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize GPU.
|
// Initialize GPU.
|
||||||
Graphics.Gpu.GraphicsConfig.TitleId = $"{programId:x16}";
|
GraphicsConfig.TitleId = programId.ToString("X16");
|
||||||
device.Gpu.HostInitalized.Set();
|
device.Gpu.HostInitalized.Set();
|
||||||
|
|
||||||
if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
|
if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
|
||||||
|
@ -6,7 +6,9 @@ using LibHac.Ns;
|
|||||||
using LibHac.Tools.Fs;
|
using LibHac.Tools.Fs;
|
||||||
using LibHac.Tools.FsSystem;
|
using LibHac.Tools.FsSystem;
|
||||||
using LibHac.Tools.FsSystem.NcaUtils;
|
using LibHac.Tools.FsSystem.NcaUtils;
|
||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.HLE.Loaders.Executables;
|
using Ryujinx.HLE.Loaders.Executables;
|
||||||
using Ryujinx.HLE.Loaders.Processes.Extensions;
|
using Ryujinx.HLE.Loaders.Processes.Extensions;
|
||||||
using System;
|
using System;
|
||||||
@ -59,6 +61,8 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||||||
{
|
{
|
||||||
_latestPid = processResult.ProcessId;
|
_latestPid = processResult.ProcessId;
|
||||||
|
|
||||||
|
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,6 +90,8 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||||||
{
|
{
|
||||||
_latestPid = processResult.ProcessId;
|
_latestPid = processResult.ProcessId;
|
||||||
|
|
||||||
|
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,6 +119,8 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||||||
if (processResult.ProgramId > 0x01000000000007FF)
|
if (processResult.ProgramId > 0x01000000000007FF)
|
||||||
{
|
{
|
||||||
_latestPid = processResult.ProcessId;
|
_latestPid = processResult.ProcessId;
|
||||||
|
|
||||||
|
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -132,6 +140,8 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||||||
{
|
{
|
||||||
_latestPid = processResult.ProcessId;
|
_latestPid = processResult.ProcessId;
|
||||||
|
|
||||||
|
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,14 +193,17 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||||||
if (nacpData.Value.PresenceGroupId != 0)
|
if (nacpData.Value.PresenceGroupId != 0)
|
||||||
{
|
{
|
||||||
programId = nacpData.Value.PresenceGroupId;
|
programId = nacpData.Value.PresenceGroupId;
|
||||||
|
TitleIDs.CurrentApplication.Value = programId.ToString("X16");
|
||||||
}
|
}
|
||||||
else if (nacpData.Value.SaveDataOwnerId != 0)
|
else if (nacpData.Value.SaveDataOwnerId != 0)
|
||||||
{
|
{
|
||||||
programId = nacpData.Value.SaveDataOwnerId;
|
programId = nacpData.Value.SaveDataOwnerId;
|
||||||
|
TitleIDs.CurrentApplication.Value = programId.ToString("X16");
|
||||||
}
|
}
|
||||||
else if (nacpData.Value.AddOnContentBaseId != 0)
|
else if (nacpData.Value.AddOnContentBaseId != 0)
|
||||||
{
|
{
|
||||||
programId = nacpData.Value.AddOnContentBaseId - 0x1000;
|
programId = nacpData.Value.AddOnContentBaseId - 0x1000;
|
||||||
|
TitleIDs.CurrentApplication.Value = programId.ToString("X16");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +217,7 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Explicitly null TitleId to disable the shader cache.
|
// Explicitly null TitleId to disable the shader cache.
|
||||||
Graphics.Gpu.GraphicsConfig.TitleId = null;
|
GraphicsConfig.TitleId = null;
|
||||||
_device.Gpu.HostInitalized.Set();
|
_device.Gpu.HostInitalized.Set();
|
||||||
|
|
||||||
ProcessResult processResult = ProcessLoaderHelper.LoadNsos(_device,
|
ProcessResult processResult = ProcessLoaderHelper.LoadNsos(_device,
|
||||||
|
@ -2,6 +2,7 @@ using LibHac.Common;
|
|||||||
using LibHac.Ns;
|
using LibHac.Ns;
|
||||||
using Ryujinx.Audio.Backends.CompatLayer;
|
using Ryujinx.Audio.Backends.CompatLayer;
|
||||||
using Ryujinx.Audio.Integration;
|
using Ryujinx.Audio.Integration;
|
||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Graphics.Gpu;
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
@ -17,6 +18,8 @@ namespace Ryujinx.HLE
|
|||||||
{
|
{
|
||||||
public class Switch : IDisposable
|
public class Switch : IDisposable
|
||||||
{
|
{
|
||||||
|
public static Switch Shared { get; private set; }
|
||||||
|
|
||||||
public HLEConfiguration Configuration { get; }
|
public HLEConfiguration Configuration { get; }
|
||||||
public IHardwareDeviceDriver AudioDeviceDriver { get; }
|
public IHardwareDeviceDriver AudioDeviceDriver { get; }
|
||||||
public MemoryBlock Memory { get; }
|
public MemoryBlock Memory { get; }
|
||||||
@ -37,6 +40,8 @@ namespace Ryujinx.HLE
|
|||||||
|
|
||||||
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
|
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
|
||||||
|
|
||||||
|
public DirtyHacks DirtyHacks { get; }
|
||||||
|
|
||||||
public Switch(HLEConfiguration configuration)
|
public Switch(HLEConfiguration configuration)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
|
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
|
||||||
@ -52,9 +57,10 @@ namespace Ryujinx.HLE
|
|||||||
: MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Mirrorable;
|
: MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Mirrorable;
|
||||||
|
|
||||||
#pragma warning disable IDE0055 // Disable formatting
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
|
DirtyHacks = new DirtyHacks(Configuration.Hacks);
|
||||||
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver);
|
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver);
|
||||||
Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags);
|
Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags);
|
||||||
Gpu = new GpuContext(Configuration.GpuRenderer);
|
Gpu = new GpuContext(Configuration.GpuRenderer, DirtyHacks);
|
||||||
System = new HOS.Horizon(this);
|
System = new HOS.Horizon(this);
|
||||||
Statistics = new PerformanceStatistics();
|
Statistics = new PerformanceStatistics();
|
||||||
Hid = new Hid(this, System.HidStorage);
|
Hid = new Hid(this, System.HidStorage);
|
||||||
@ -72,8 +78,11 @@ namespace Ryujinx.HLE
|
|||||||
System.EnablePtc = Configuration.EnablePtc;
|
System.EnablePtc = Configuration.EnablePtc;
|
||||||
System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel;
|
System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel;
|
||||||
System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode;
|
System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode;
|
||||||
|
|
||||||
UpdateVSyncInterval();
|
UpdateVSyncInterval();
|
||||||
#pragma warning restore IDE0055
|
#pragma warning restore IDE0055
|
||||||
|
|
||||||
|
Shared = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessFrame()
|
public void ProcessFrame()
|
||||||
@ -142,6 +151,9 @@ namespace Ryujinx.HLE
|
|||||||
AudioDeviceDriver.Dispose();
|
AudioDeviceDriver.Dispose();
|
||||||
FileSystem.Dispose();
|
FileSystem.Dispose();
|
||||||
Memory.Dispose();
|
Memory.Dispose();
|
||||||
|
|
||||||
|
TitleIDs.CurrentApplication.Value = null;
|
||||||
|
Shared = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<Version>1.0.0-dirty</Version>
|
|
||||||
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
|
|
||||||
<SigningCertificate Condition=" '$(SigningCertificate)' == '' ">-</SigningCertificate>
|
|
||||||
<TieredPGO>true</TieredPGO>
|
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="OpenTK.Core" />
|
|
||||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
|
|
||||||
<Exec Command="codesign --entitlements '$(ProjectDir)..\..\distribution\macos\entitlements.xml' -f -s $(SigningCertificate) '$(TargetDir)$(TargetName)'" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
|
|
||||||
<ProjectReference Include="..\Ryujinx.Input\Ryujinx.Input.csproj" />
|
|
||||||
<ProjectReference Include="..\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj" />
|
|
||||||
<ProjectReference Include="..\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj" />
|
|
||||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
|
||||||
<ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
|
|
||||||
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
|
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
|
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj" />
|
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="CommandLineParser" />
|
|
||||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="..\..\distribution\legal\THIRDPARTY.md">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
<TargetPath>THIRDPARTY.md</TargetPath>
|
|
||||||
</Content>
|
|
||||||
<Content Include="..\..\LICENSE.txt">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
<TargetPath>LICENSE.txt</TargetPath>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64' OR ('$(RuntimeIdentifier)' == '' AND $([MSBuild]::IsOSPlatform('Linux')))">
|
|
||||||
<Content Include="..\..\distribution\linux\Ryujinx.sh">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="Ryujinx.bmp" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!-- Due to .net core 3.1 embedded resource loading -->
|
|
||||||
<PropertyGroup>
|
|
||||||
<EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
|
|
||||||
<ApplicationIcon>..\Ryujinx\Ryujinx.ico</ApplicationIcon>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' != ''">
|
|
||||||
<PublishSingleFile>true</PublishSingleFile>
|
|
||||||
<PublishTrimmed>true</PublishTrimmed>
|
|
||||||
<TrimMode>partial</TrimMode>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
Before Width: | Height: | Size: 9.1 KiB |
@ -1,747 +0,0 @@
|
|||||||
using Ryujinx.Common.Configuration;
|
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
|
||||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using Ryujinx.HLE;
|
|
||||||
using Ryujinx.UI.Common.Configuration.System;
|
|
||||||
using Ryujinx.UI.Common.Configuration.UI;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Configuration
|
|
||||||
{
|
|
||||||
public partial class ConfigurationState
|
|
||||||
{
|
|
||||||
public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath)
|
|
||||||
{
|
|
||||||
bool configurationFileUpdated = false;
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version is < 0 or > ConfigurationFileFormat.CurrentVersion)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {configurationFileFormat.Version}, loading default.");
|
|
||||||
|
|
||||||
LoadDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 2)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2.");
|
|
||||||
|
|
||||||
configurationFileFormat.SystemRegion = Region.USA;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 3)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 3.");
|
|
||||||
|
|
||||||
configurationFileFormat.SystemTimeZone = "UTC";
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 4)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 4.");
|
|
||||||
|
|
||||||
configurationFileFormat.MaxAnisotropy = -1;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 5)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 5.");
|
|
||||||
|
|
||||||
configurationFileFormat.SystemTimeOffset = 0;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 8)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 8.");
|
|
||||||
|
|
||||||
configurationFileFormat.EnablePtc = true;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 9)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 9.");
|
|
||||||
|
|
||||||
configurationFileFormat.ColumnSort = new ColumnSort
|
|
||||||
{
|
|
||||||
SortColumnId = 0,
|
|
||||||
SortAscending = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
|
||||||
{
|
|
||||||
ToggleVSyncMode = Key.F1,
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 10)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 10.");
|
|
||||||
|
|
||||||
configurationFileFormat.AudioBackend = AudioBackend.OpenAl;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 11)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 11.");
|
|
||||||
|
|
||||||
configurationFileFormat.ResScale = 1;
|
|
||||||
configurationFileFormat.ResScaleCustom = 1.0f;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 12)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 12.");
|
|
||||||
|
|
||||||
configurationFileFormat.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// configurationFileFormat.Version == 13 -> LDN1
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 14)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 14.");
|
|
||||||
|
|
||||||
configurationFileFormat.CheckUpdatesOnStart = true;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 16)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 16.");
|
|
||||||
|
|
||||||
configurationFileFormat.EnableShaderCache = true;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 17)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 17.");
|
|
||||||
|
|
||||||
configurationFileFormat.StartFullscreen = false;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 18)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 18.");
|
|
||||||
|
|
||||||
configurationFileFormat.AspectRatio = AspectRatio.Fixed16x9;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// configurationFileFormat.Version == 19 -> LDN2
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 20)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 20.");
|
|
||||||
|
|
||||||
configurationFileFormat.ShowConfirmExit = true;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 21)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 21.");
|
|
||||||
|
|
||||||
// Initialize network config.
|
|
||||||
|
|
||||||
configurationFileFormat.MultiplayerMode = MultiplayerMode.Disabled;
|
|
||||||
configurationFileFormat.MultiplayerLanInterfaceId = "0";
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 22)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22.");
|
|
||||||
|
|
||||||
configurationFileFormat.HideCursor = HideCursorMode.Never;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 24)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 24.");
|
|
||||||
|
|
||||||
configurationFileFormat.InputConfig = new List<InputConfig>
|
|
||||||
{
|
|
||||||
new StandardKeyboardInputConfig
|
|
||||||
{
|
|
||||||
Version = InputConfig.CurrentVersion,
|
|
||||||
Backend = InputBackendType.WindowKeyboard,
|
|
||||||
Id = "0",
|
|
||||||
PlayerIndex = PlayerIndex.Player1,
|
|
||||||
ControllerType = ControllerType.ProController,
|
|
||||||
LeftJoycon = new LeftJoyconCommonConfig<Key>
|
|
||||||
{
|
|
||||||
DpadUp = Key.Up,
|
|
||||||
DpadDown = Key.Down,
|
|
||||||
DpadLeft = Key.Left,
|
|
||||||
DpadRight = Key.Right,
|
|
||||||
ButtonMinus = Key.Minus,
|
|
||||||
ButtonL = Key.E,
|
|
||||||
ButtonZl = Key.Q,
|
|
||||||
ButtonSl = Key.Unbound,
|
|
||||||
ButtonSr = Key.Unbound,
|
|
||||||
},
|
|
||||||
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
|
||||||
{
|
|
||||||
StickUp = Key.W,
|
|
||||||
StickDown = Key.S,
|
|
||||||
StickLeft = Key.A,
|
|
||||||
StickRight = Key.D,
|
|
||||||
StickButton = Key.F,
|
|
||||||
},
|
|
||||||
RightJoycon = new RightJoyconCommonConfig<Key>
|
|
||||||
{
|
|
||||||
ButtonA = Key.Z,
|
|
||||||
ButtonB = Key.X,
|
|
||||||
ButtonX = Key.C,
|
|
||||||
ButtonY = Key.V,
|
|
||||||
ButtonPlus = Key.Plus,
|
|
||||||
ButtonR = Key.U,
|
|
||||||
ButtonZr = Key.O,
|
|
||||||
ButtonSl = Key.Unbound,
|
|
||||||
ButtonSr = Key.Unbound,
|
|
||||||
},
|
|
||||||
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
|
||||||
{
|
|
||||||
StickUp = Key.I,
|
|
||||||
StickDown = Key.K,
|
|
||||||
StickLeft = Key.J,
|
|
||||||
StickRight = Key.L,
|
|
||||||
StickButton = Key.H,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 25)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 25.");
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 26)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 26.");
|
|
||||||
|
|
||||||
configurationFileFormat.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 27)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 27.");
|
|
||||||
|
|
||||||
configurationFileFormat.EnableMouse = false;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 28)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 28.");
|
|
||||||
|
|
||||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
|
||||||
{
|
|
||||||
ToggleVSyncMode = Key.F1,
|
|
||||||
Screenshot = Key.F8,
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 29)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 29.");
|
|
||||||
|
|
||||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
|
||||||
{
|
|
||||||
ToggleVSyncMode = Key.F1,
|
|
||||||
Screenshot = Key.F8,
|
|
||||||
ShowUI = Key.F4,
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 30)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 30.");
|
|
||||||
|
|
||||||
foreach (InputConfig config in configurationFileFormat.InputConfig)
|
|
||||||
{
|
|
||||||
if (config is StandardControllerInputConfig controllerConfig)
|
|
||||||
{
|
|
||||||
controllerConfig.Rumble = new RumbleConfigController
|
|
||||||
{
|
|
||||||
EnableRumble = false,
|
|
||||||
StrongRumble = 1f,
|
|
||||||
WeakRumble = 1f,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 31)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 31.");
|
|
||||||
|
|
||||||
configurationFileFormat.BackendThreading = BackendThreading.Auto;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 32)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 32.");
|
|
||||||
|
|
||||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
|
||||||
{
|
|
||||||
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
|
|
||||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
|
||||||
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
|
|
||||||
Pause = Key.F5,
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 33)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 33.");
|
|
||||||
|
|
||||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
|
||||||
{
|
|
||||||
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
|
|
||||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
|
||||||
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
|
|
||||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
|
||||||
ToggleMute = Key.F2,
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileFormat.AudioVolume = 1;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 34)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 34.");
|
|
||||||
|
|
||||||
configurationFileFormat.EnableInternetAccess = false;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 35)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 35.");
|
|
||||||
|
|
||||||
foreach (InputConfig config in configurationFileFormat.InputConfig)
|
|
||||||
{
|
|
||||||
if (config is StandardControllerInputConfig controllerConfig)
|
|
||||||
{
|
|
||||||
controllerConfig.RangeLeft = 1.0f;
|
|
||||||
controllerConfig.RangeRight = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 36)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 36.");
|
|
||||||
|
|
||||||
configurationFileFormat.LoggingEnableTrace = false;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 37)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 37.");
|
|
||||||
|
|
||||||
configurationFileFormat.ShowConsole = true;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 38)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 38.");
|
|
||||||
|
|
||||||
configurationFileFormat.BaseStyle = "Dark";
|
|
||||||
configurationFileFormat.GameListViewMode = 0;
|
|
||||||
configurationFileFormat.ShowNames = true;
|
|
||||||
configurationFileFormat.GridSize = 2;
|
|
||||||
configurationFileFormat.LanguageCode = "en_US";
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 39)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 39.");
|
|
||||||
|
|
||||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
|
||||||
{
|
|
||||||
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
|
|
||||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
|
||||||
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
|
|
||||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
|
||||||
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
|
|
||||||
ResScaleUp = Key.Unbound,
|
|
||||||
ResScaleDown = Key.Unbound,
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 40)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 40.");
|
|
||||||
|
|
||||||
configurationFileFormat.GraphicsBackend = GraphicsBackend.OpenGl;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 41)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 41.");
|
|
||||||
|
|
||||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
|
||||||
{
|
|
||||||
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
|
|
||||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
|
||||||
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
|
|
||||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
|
||||||
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
|
|
||||||
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
|
|
||||||
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
|
|
||||||
VolumeUp = Key.Unbound,
|
|
||||||
VolumeDown = Key.Unbound,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 42)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 42.");
|
|
||||||
|
|
||||||
configurationFileFormat.EnableMacroHLE = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 43)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 43.");
|
|
||||||
|
|
||||||
configurationFileFormat.UseHypervisor = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 44)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 44.");
|
|
||||||
|
|
||||||
configurationFileFormat.AntiAliasing = AntiAliasing.None;
|
|
||||||
configurationFileFormat.ScalingFilter = ScalingFilter.Bilinear;
|
|
||||||
configurationFileFormat.ScalingFilterLevel = 80;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 45)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 45.");
|
|
||||||
|
|
||||||
configurationFileFormat.ShownFileTypes = new ShownFileTypes
|
|
||||||
{
|
|
||||||
NSP = true,
|
|
||||||
PFS0 = true,
|
|
||||||
XCI = true,
|
|
||||||
NCA = true,
|
|
||||||
NRO = true,
|
|
||||||
NSO = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 46)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 46.");
|
|
||||||
|
|
||||||
configurationFileFormat.MultiplayerLanInterfaceId = "0";
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 47)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 47.");
|
|
||||||
|
|
||||||
configurationFileFormat.WindowStartup = new WindowStartup
|
|
||||||
{
|
|
||||||
WindowPositionX = 0,
|
|
||||||
WindowPositionY = 0,
|
|
||||||
WindowSizeHeight = 760,
|
|
||||||
WindowSizeWidth = 1280,
|
|
||||||
WindowMaximized = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 48)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 48.");
|
|
||||||
|
|
||||||
configurationFileFormat.EnableColorSpacePassthrough = false;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 49)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 49.");
|
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS())
|
|
||||||
{
|
|
||||||
AppDataManager.FixMacOSConfigurationFolders();
|
|
||||||
}
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 50)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 50.");
|
|
||||||
|
|
||||||
configurationFileFormat.EnableHardwareAcceleration = true;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 51)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 51.");
|
|
||||||
|
|
||||||
configurationFileFormat.RememberWindowState = true;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 52)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 52.");
|
|
||||||
|
|
||||||
configurationFileFormat.AutoloadDirs = [];
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 53)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 53.");
|
|
||||||
|
|
||||||
configurationFileFormat.EnableLowPowerPtc = false;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 54)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 54.");
|
|
||||||
|
|
||||||
configurationFileFormat.DramSize = MemoryConfiguration.MemoryConfiguration4GiB;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 55)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 55.");
|
|
||||||
|
|
||||||
configurationFileFormat.IgnoreApplet = false;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 56)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 56.");
|
|
||||||
|
|
||||||
configurationFileFormat.ShowTitleBar = !OperatingSystem.IsWindows();
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configurationFileFormat.Version < 57)
|
|
||||||
{
|
|
||||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 57.");
|
|
||||||
|
|
||||||
configurationFileFormat.VSyncMode = VSyncMode.Switch;
|
|
||||||
configurationFileFormat.EnableCustomVSyncInterval = false;
|
|
||||||
|
|
||||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
|
||||||
{
|
|
||||||
ToggleVSyncMode = Key.F1,
|
|
||||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
|
||||||
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
|
|
||||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
|
||||||
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
|
|
||||||
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
|
|
||||||
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
|
|
||||||
VolumeUp = configurationFileFormat.Hotkeys.VolumeUp,
|
|
||||||
VolumeDown = configurationFileFormat.Hotkeys.VolumeDown,
|
|
||||||
CustomVSyncIntervalIncrement = Key.Unbound,
|
|
||||||
CustomVSyncIntervalDecrement = Key.Unbound,
|
|
||||||
};
|
|
||||||
|
|
||||||
configurationFileFormat.CustomVSyncInterval = 120;
|
|
||||||
|
|
||||||
configurationFileUpdated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
|
|
||||||
Graphics.ResScale.Value = configurationFileFormat.ResScale;
|
|
||||||
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
|
|
||||||
Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy;
|
|
||||||
Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio;
|
|
||||||
Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath;
|
|
||||||
Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading;
|
|
||||||
Graphics.GraphicsBackend.Value = configurationFileFormat.GraphicsBackend;
|
|
||||||
Graphics.PreferredGpu.Value = configurationFileFormat.PreferredGpu;
|
|
||||||
Graphics.AntiAliasing.Value = configurationFileFormat.AntiAliasing;
|
|
||||||
Graphics.ScalingFilter.Value = configurationFileFormat.ScalingFilter;
|
|
||||||
Graphics.ScalingFilterLevel.Value = configurationFileFormat.ScalingFilterLevel;
|
|
||||||
Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug;
|
|
||||||
Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub;
|
|
||||||
Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo;
|
|
||||||
Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn;
|
|
||||||
Logger.EnableError.Value = configurationFileFormat.LoggingEnableError;
|
|
||||||
Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace;
|
|
||||||
Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest;
|
|
||||||
Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog;
|
|
||||||
Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses;
|
|
||||||
Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel;
|
|
||||||
System.Language.Value = configurationFileFormat.SystemLanguage;
|
|
||||||
System.Region.Value = configurationFileFormat.SystemRegion;
|
|
||||||
System.TimeZone.Value = configurationFileFormat.SystemTimeZone;
|
|
||||||
System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset;
|
|
||||||
System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
|
|
||||||
EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
|
|
||||||
CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart;
|
|
||||||
ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit;
|
|
||||||
IgnoreApplet.Value = configurationFileFormat.IgnoreApplet;
|
|
||||||
RememberWindowState.Value = configurationFileFormat.RememberWindowState;
|
|
||||||
ShowTitleBar.Value = configurationFileFormat.ShowTitleBar;
|
|
||||||
EnableHardwareAcceleration.Value = configurationFileFormat.EnableHardwareAcceleration;
|
|
||||||
HideCursor.Value = configurationFileFormat.HideCursor;
|
|
||||||
Graphics.VSyncMode.Value = configurationFileFormat.VSyncMode;
|
|
||||||
Graphics.EnableCustomVSyncInterval.Value = configurationFileFormat.EnableCustomVSyncInterval;
|
|
||||||
Graphics.CustomVSyncInterval.Value = configurationFileFormat.CustomVSyncInterval;
|
|
||||||
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
|
|
||||||
Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
|
|
||||||
Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE;
|
|
||||||
Graphics.EnableColorSpacePassthrough.Value = configurationFileFormat.EnableColorSpacePassthrough;
|
|
||||||
System.EnablePtc.Value = configurationFileFormat.EnablePtc;
|
|
||||||
System.EnableLowPowerPtc.Value = configurationFileFormat.EnableLowPowerPtc;
|
|
||||||
System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
|
|
||||||
System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
|
|
||||||
System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode;
|
|
||||||
System.AudioBackend.Value = configurationFileFormat.AudioBackend;
|
|
||||||
System.AudioVolume.Value = configurationFileFormat.AudioVolume;
|
|
||||||
System.MemoryManagerMode.Value = configurationFileFormat.MemoryManagerMode;
|
|
||||||
System.DramSize.Value = configurationFileFormat.DramSize;
|
|
||||||
System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices;
|
|
||||||
System.UseHypervisor.Value = configurationFileFormat.UseHypervisor;
|
|
||||||
UI.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn;
|
|
||||||
UI.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn;
|
|
||||||
UI.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn;
|
|
||||||
UI.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn;
|
|
||||||
UI.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn;
|
|
||||||
UI.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn;
|
|
||||||
UI.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn;
|
|
||||||
UI.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn;
|
|
||||||
UI.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn;
|
|
||||||
UI.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn;
|
|
||||||
UI.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId;
|
|
||||||
UI.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending;
|
|
||||||
UI.GameDirs.Value = configurationFileFormat.GameDirs;
|
|
||||||
UI.AutoloadDirs.Value = configurationFileFormat.AutoloadDirs ?? [];
|
|
||||||
UI.ShownFileTypes.NSP.Value = configurationFileFormat.ShownFileTypes.NSP;
|
|
||||||
UI.ShownFileTypes.PFS0.Value = configurationFileFormat.ShownFileTypes.PFS0;
|
|
||||||
UI.ShownFileTypes.XCI.Value = configurationFileFormat.ShownFileTypes.XCI;
|
|
||||||
UI.ShownFileTypes.NCA.Value = configurationFileFormat.ShownFileTypes.NCA;
|
|
||||||
UI.ShownFileTypes.NRO.Value = configurationFileFormat.ShownFileTypes.NRO;
|
|
||||||
UI.ShownFileTypes.NSO.Value = configurationFileFormat.ShownFileTypes.NSO;
|
|
||||||
UI.LanguageCode.Value = configurationFileFormat.LanguageCode;
|
|
||||||
UI.BaseStyle.Value = configurationFileFormat.BaseStyle;
|
|
||||||
UI.GameListViewMode.Value = configurationFileFormat.GameListViewMode;
|
|
||||||
UI.ShowNames.Value = configurationFileFormat.ShowNames;
|
|
||||||
UI.IsAscendingOrder.Value = configurationFileFormat.IsAscendingOrder;
|
|
||||||
UI.GridSize.Value = configurationFileFormat.GridSize;
|
|
||||||
UI.ApplicationSort.Value = configurationFileFormat.ApplicationSort;
|
|
||||||
UI.StartFullscreen.Value = configurationFileFormat.StartFullscreen;
|
|
||||||
UI.ShowConsole.Value = configurationFileFormat.ShowConsole;
|
|
||||||
UI.WindowStartup.WindowSizeWidth.Value = configurationFileFormat.WindowStartup.WindowSizeWidth;
|
|
||||||
UI.WindowStartup.WindowSizeHeight.Value = configurationFileFormat.WindowStartup.WindowSizeHeight;
|
|
||||||
UI.WindowStartup.WindowPositionX.Value = configurationFileFormat.WindowStartup.WindowPositionX;
|
|
||||||
UI.WindowStartup.WindowPositionY.Value = configurationFileFormat.WindowStartup.WindowPositionY;
|
|
||||||
UI.WindowStartup.WindowMaximized.Value = configurationFileFormat.WindowStartup.WindowMaximized;
|
|
||||||
Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard;
|
|
||||||
Hid.EnableMouse.Value = configurationFileFormat.EnableMouse;
|
|
||||||
Hid.Hotkeys.Value = configurationFileFormat.Hotkeys;
|
|
||||||
Hid.InputConfig.Value = configurationFileFormat.InputConfig ?? [];
|
|
||||||
|
|
||||||
Multiplayer.LanInterfaceId.Value = configurationFileFormat.MultiplayerLanInterfaceId;
|
|
||||||
Multiplayer.Mode.Value = configurationFileFormat.MultiplayerMode;
|
|
||||||
Multiplayer.DisableP2p.Value = configurationFileFormat.MultiplayerDisableP2p;
|
|
||||||
Multiplayer.LdnPassphrase.Value = configurationFileFormat.MultiplayerLdnPassphrase;
|
|
||||||
Multiplayer.LdnServer.Value = configurationFileFormat.LdnServer;
|
|
||||||
|
|
||||||
if (configurationFileUpdated)
|
|
||||||
{
|
|
||||||
ToFileFormat().SaveConfig(configurationFilePath);
|
|
||||||
|
|
||||||
Ryujinx.Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
namespace Ryujinx.UI.Common
|
|
||||||
{
|
|
||||||
public enum FileTypes
|
|
||||||
{
|
|
||||||
NSP,
|
|
||||||
PFS0,
|
|
||||||
XCI,
|
|
||||||
NCA,
|
|
||||||
NRO,
|
|
||||||
NSO
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
using LibHac.Common;
|
|
||||||
using LibHac.Ncm;
|
|
||||||
using LibHac.Ns;
|
|
||||||
using LibHac.Tools.FsSystem.NcaUtils;
|
|
||||||
using Ryujinx.HLE;
|
|
||||||
using Ryujinx.HLE.FileSystem;
|
|
||||||
using Ryujinx.UI.App.Common;
|
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Helper
|
|
||||||
{
|
|
||||||
public readonly struct AppletMetadata
|
|
||||||
{
|
|
||||||
private readonly ContentManager _contentManager;
|
|
||||||
|
|
||||||
public string Name { get; }
|
|
||||||
public ulong ProgramId { get; }
|
|
||||||
|
|
||||||
public string Version { get; }
|
|
||||||
|
|
||||||
public AppletMetadata(ContentManager contentManager, string name, ulong programId, string version = "1.0.0")
|
|
||||||
: this(name, programId, version)
|
|
||||||
{
|
|
||||||
_contentManager = contentManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AppletMetadata(string name, ulong programId, string version = "1.0.0")
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
ProgramId = programId;
|
|
||||||
Version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetContentPath(ContentManager contentManager)
|
|
||||||
=> (contentManager ?? _contentManager)
|
|
||||||
.GetInstalledContentPath(ProgramId, StorageId.BuiltInSystem, NcaContentType.Program);
|
|
||||||
|
|
||||||
public bool CanStart(ContentManager contentManager, out ApplicationData appData, out BlitStruct<ApplicationControlProperty> appControl)
|
|
||||||
{
|
|
||||||
contentManager ??= _contentManager;
|
|
||||||
if (contentManager == null)
|
|
||||||
{
|
|
||||||
appData = null;
|
|
||||||
appControl = new BlitStruct<ApplicationControlProperty>(0);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
appData = new()
|
|
||||||
{
|
|
||||||
Name = Name,
|
|
||||||
Id = ProgramId,
|
|
||||||
Path = GetContentPath(contentManager)
|
|
||||||
};
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(appData.Path))
|
|
||||||
{
|
|
||||||
appControl = new BlitStruct<ApplicationControlProperty>(0);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
appControl = StructHelpers.CreateCustomNacpData(Name, Version);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 81 KiB |
@ -1,132 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1050 1050.5"
|
|
||||||
style="enable-background:new 0 0 1050 1050.5;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#20221F;}
|
|
||||||
.st1{fill:#3B3B3B;}
|
|
||||||
.st2{fill:#121212;}
|
|
||||||
.st3{fill:#444542;}
|
|
||||||
.st4{fill:#FFFFFF;}
|
|
||||||
.st5{fill:#444542;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}
|
|
||||||
.st6{fill:#454644;}
|
|
||||||
.st7{fill:#454644;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}
|
|
||||||
.st8{fill:#3B3C3A;}
|
|
||||||
.st9{font-family:'Helvetica-Bold';}
|
|
||||||
.st10{font-size:40px;}
|
|
||||||
.st11{fill:#0D0D0A;}
|
|
||||||
</style>
|
|
||||||
<g id="Front">
|
|
||||||
<path id="Right_Grip_00000028282943321285403220000008369785803052272051_" class="st0" d="M766,850.5
|
|
||||||
c34,28.2,27.6,35.9,68.5,108.5c36.7,74.7,64.4,104.4,125.1,84.1v0c95.3-57.9,59.3-145.3,43.6-275.2c-10-60.6-35.6-190.3-35.6-190.3
|
|
||||||
L766,850.5z"/>
|
|
||||||
<path id="Left_Grip" class="st0" d="M82.3,577.6c0,0-25.6,129.7-35.6,190.3C31,897.8-5,985.1,90.3,1043v0
|
|
||||||
c60.8,20.3,88.4-9.4,125.1-84.1c40.9-72.7,34.5-80.3,68.5-108.5L82.3,577.6z"/>
|
|
||||||
<path id="Right_Bumper_00000006710349871522532470000011078040965381267594_" class="st1" d="M676.3,378.4
|
|
||||||
c10.1-4.3,39.7-22.5,58.7-19.7c59.5,0.9,166.7,17.7,172.6,81.2"/>
|
|
||||||
<path id="Left_Bumper_00000024680414077879639570000011759596763560342154_" class="st1" d="M142.4,439.9
|
|
||||||
c5.9-63.4,113-80.2,172.6-81.2c19-2.8,48.6,15.4,58.7,19.7"/>
|
|
||||||
<path id="Background_00000141418846164053065470000016150094984198570163_" class="st2" d="M766,850.5
|
|
||||||
c35.5-30.8,68.5-74.7,96-113.5c26.9-36.3,94.7-136.7,105.6-159.3c0-2.4-6.3-30.1-12.8-56.2C919.1,361.9,702.2,378.1,525,378.1
|
|
||||||
c-177.4,0-394.1-16.2-429.9,143.3c-6.5,26-12.8,53.8-12.8,56.2c10.9,22.6,78.8,123,105.6,159.3c27.5,38.8,60.5,82.8,96,113.5"/>
|
|
||||||
<g id="Directional_Pad">
|
|
||||||
<path id="Background_00000032628022449190479560000015279211462520783249_" class="st3" d="M466.2,683.5h-40c-2.8,0-5-2.2-5-5v-40
|
|
||||||
c0-2.8-2.2-5-5-5h-30c-2.8,0-5,2.2-5,5v40c0,2.8-2.2,5-5,5h-40c-2.8,0-5,2.2-5,5v30c0,2.8,2.2,5,5,5h40c2.8,0,5,2.2,5,5v40
|
|
||||||
c0,2.8,2.2,5,5,5h30c2.8,0,5-2.2,5-5v-40c0-2.8,2.2-5,5-5h40c2.8,0,5-2.2,5-5v-30C471.2,685.8,469,683.5,466.2,683.5z"/>
|
|
||||||
<g id="Arrows">
|
|
||||||
<g>
|
|
||||||
<polygon class="st4" points="393.7,746 408.7,746 401.2,761 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st4" points="358.7,696 358.7,711 343.7,703.5 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st4" points="408.7,661 393.7,661 401.2,646 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st4" points="443.7,711 443.7,696 458.7,703.5 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g id="R_Thumbstick_00000152226188525111835500000011838297421350334865_">
|
|
||||||
<circle id="Background_00000035532849542660068350000006517224202948159422_" class="st0" cx="650.6" cy="703.5" r="55"/>
|
|
||||||
<circle id="Stick" class="st5" cx="650.6" cy="703.5" r="45"/>
|
|
||||||
</g>
|
|
||||||
<g id="L_Thumbstick_00000047032468231999382210000005512347386782594484_">
|
|
||||||
<circle id="Background_00000182502673988292164000000007125719133096369561_" class="st0" cx="240.2" cy="564.8" r="55"/>
|
|
||||||
<circle id="Stick_00000075121990265259598900000000214370239054002365_" class="st5" cx="240.2" cy="564.8" r="45"/>
|
|
||||||
</g>
|
|
||||||
<g id="Minus_Button">
|
|
||||||
<circle id="_Background_00000120554951013892796430000015877571645746699662_" class="st6" cx="401" cy="489.3" r="22.5"/>
|
|
||||||
<polyline id="Plus_00000039131319101621183460000006196023733899658629_" class="st4" points="386.2,491.8 386.2,486.8
|
|
||||||
416.2,486.8 416.2,491.8 "/>
|
|
||||||
</g>
|
|
||||||
<g id="Plus_Button">
|
|
||||||
<circle id="_Background" class="st6" cx="650.4" cy="489.6" r="22.5"/>
|
|
||||||
<polygon id="Plus" class="st4" points="665.6,487.1 653.1,487.1 653.1,474.4 648.1,474.4 648.1,487.1 635.6,487.1 635.6,492.1
|
|
||||||
648.1,492.1 648.1,504.4 653.1,504.4 653.1,492.1 665.6,492.1 "/>
|
|
||||||
</g>
|
|
||||||
<g id="Home_Button_00000029758737660217614780000001403165237001195407_">
|
|
||||||
<circle id="_Background_00000132788487854287834010000009548421243227981499_" class="st6" cx="605.4" cy="564.8" r="22.5"/>
|
|
||||||
<path id="Home" class="st4" d="M605.4,549.8l-15,15h5v15h20v-15h5L605.4,549.8z M610.4,574.8h-10v-10h10V574.8z"/>
|
|
||||||
</g>
|
|
||||||
<g id="Capture_Button_00000105394663133565750060000017455731898661404072_">
|
|
||||||
<path class="st6" d="M468.6,586.5h-30c-2.8,0-5-2.2-5-5v-29.5c0-2.8,2.2-5,5-5h30c2.8,0,5,2.2,5,5v29.5
|
|
||||||
C473.6,584.2,471.4,586.5,468.6,586.5z"/>
|
|
||||||
<circle class="st7" cx="453.6" cy="566.7" r="15"/>
|
|
||||||
</g>
|
|
||||||
<g id="Buttons_00000023239109225132251950000005218343074279628213_">
|
|
||||||
<g id="A_Button">
|
|
||||||
<circle id="Background_00000006699118933065716380000004636085088820886913_" class="st8" cx="863.9" cy="564.8" r="35"/>
|
|
||||||
<text transform="matrix(1 0 0 1 849.4224 578.6607)" class="st4 st9 st10">A</text>
|
|
||||||
</g>
|
|
||||||
<g id="X_Button">
|
|
||||||
<circle id="Background_00000083074713085756701790000016893839312974798515_" class="st8" cx="793.9" cy="494.8" r="35"/>
|
|
||||||
<text transform="matrix(1 0 0 1 780.5266 508.6604)" class="st4 st9 st10">X</text>
|
|
||||||
</g>
|
|
||||||
<g id="Y_Button_00000100344340438574137780000014238704828967683973_">
|
|
||||||
<circle id="Background_00000137100455694543496620000011124722786613194377_" class="st8" cx="723.9" cy="564.8" r="35"/>
|
|
||||||
<text transform="matrix(1 0 0 1 710.5263 578.661)" class="st4 st9 st10">Y</text>
|
|
||||||
</g>
|
|
||||||
<g id="B_Button_00000041994261956088037220000013468634544777304733_">
|
|
||||||
<circle id="Background_00000096038108578846046800000001873940014252420514_" class="st8" cx="793.9" cy="634.8" r="35"/>
|
|
||||||
<text transform="matrix(1 0 0 1 780.9706 648.6605)" class="st4 st9 st10">B</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g id="Top_Down">
|
|
||||||
<path id="Left_Grip_00000026131988385328425370000016677941743356253314_" class="st0" d="M219.2,78.5
|
|
||||||
c-12.5-17.6-25.9-42.3-45.6-58.6C153.5,3.3,112.1-4.7,87.1,5.8c-13.9,5.8-33.4,33.1-42.7,52.8C33.9,80.9,30.4,109.9,32,141.4
|
|
||||||
c1.2,25.1,5.3,51.7,14.2,78.6c0,0,14.3,53.8,42.8,80.8c11.2,10.6,35,26.6,35,26.6l116-217.5C240,109.9,224.6,86.2,219.2,78.5z"/>
|
|
||||||
<path id="Right_Grip_00000016782759094708820330000002450847065936193693_" class="st0" d="M828.6,78.5
|
|
||||||
c12.5-17.6,25.9-42.3,45.6-58.6c20.1-16.6,61.4-24.5,86.5-14.1c13.9,5.8,33.4,33.1,42.7,52.8c10.5,22.3,13.9,51.3,12.4,82.8
|
|
||||||
c-1.2,25.1-5.3,51.7-14.2,78.6c0,0-14.3,53.8-42.8,80.8c-11.2,10.6-35,26.6-35,26.6l-116-217.5C807.8,109.9,823.2,86.2,828.6,78.5z
|
|
||||||
"/>
|
|
||||||
<path id="Background_00000169534857628063347190000007586592143875928969_" class="st11" d="M866,122.2
|
|
||||||
c66.3,18.7,85.1,128.8,69,186c-2.5,54.2-148.9,15.3-265.1,31.2c-41.1,1.7-91.8,2.4-145.9,2.3c-54.1,0-104.8-0.6-145.9-2.3
|
|
||||||
c-116.2-15.9-262.6,23.1-265.1-31.2c-16.1-57.1,2.6-167.3,69-186l60.5-18.8l38.9-1.9c40.2,0.1,142.8,0,242.7,0
|
|
||||||
c99.9,0,202.4,0.1,242.7,0l38.9,1.9L866,122.2z"/>
|
|
||||||
<g id="ZL_Trigger_00000005254517714433203260000014117442438696169895_">
|
|
||||||
<path id="Background_00000111870097528015387240000017384507710402295183_" class="st1" d="M145.9,239.2
|
|
||||||
c15.2-97.4,38.1-147.2,141.7-137c8.2,16.4,43.3,83,50.6,105.7C280.6,227.2,204.7,225.6,145.9,239.2z"/>
|
|
||||||
<text id="ZL_Trigger" transform="matrix(1.0139 0 0 1 218.3906 179.3992)" class="st4 st9 st10">ZL</text>
|
|
||||||
</g>
|
|
||||||
<g id="ZR_Trigger">
|
|
||||||
<path id="Background_00000133526766189752063450000016781240006605114763_" class="st1" d="M716.2,207.9
|
|
||||||
c7.4-22.7,42.5-89.3,50.6-105.7c103.7-10.2,126.5,39.6,141.7,137C849.8,225.6,773.8,227.2,716.2,207.9z"/>
|
|
||||||
|
|
||||||
<text id="ZL_Trigger_00000000206350378518266660000001315160307759857328_" transform="matrix(1.0139 0 0 1 784.2356 179.3992)" class="st4 st9 st10">ZR</text>
|
|
||||||
</g>
|
|
||||||
<g id="R_Trigger_00000085939413106284991650000014018840000393673094_">
|
|
||||||
<path id="Background" class="st1" d="M664,318.5c7-10.1,27.8-78.4,45.4-78.7C1040.8,243.7,897.1,334,664,318.5z"/>
|
|
||||||
<text id="R_Trigger" transform="matrix(1 0 0 1 769.6461 292.8947)" class="st4 st9 st10">R</text>
|
|
||||||
</g>
|
|
||||||
<g id="L_Trigger">
|
|
||||||
<path id="Background_00000043427985111927735300000011910735497762731703_" class="st1" d="M340.6,238.6
|
|
||||||
c17.6,0.3,38.4,68.6,45.4,78.7C152.9,332.8,9.2,242.6,340.6,238.6z"/>
|
|
||||||
|
|
||||||
<text id="R_Trigger_00000092444210070373642420000009814634285137007748_" transform="matrix(1 0 0 1 253.7327 291.7279)" class="st4 st9 st10">L</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 8.0 KiB |
@ -21,34 +21,6 @@
|
|||||||
<None Remove="Resources\Logo_Ryujinx.png" />
|
<None Remove="Resources\Logo_Ryujinx.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="Resources\Controller_JoyConLeft.svg" />
|
|
||||||
<EmbeddedResource Include="Resources\Controller_JoyConPair.svg" />
|
|
||||||
<EmbeddedResource Include="Resources\Controller_JoyConRight.svg" />
|
|
||||||
<EmbeddedResource Include="Resources\Controller_ProCon.svg" />
|
|
||||||
<EmbeddedResource Include="Resources\Icon_NCA.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Icon_NRO.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Icon_NSO.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Icon_NSP.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Icon_XCI.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Logo_Amiibo.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Logo_Ryujinx.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Logo_Ryujinx_AntiAlias.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Logo_Discord_Dark.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Logo_Discord_Light.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Logo_GitHub_Dark.png" />
|
|
||||||
<EmbeddedResource Include="Resources\Logo_GitHub_Light.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64' OR '$(RuntimeIdentifier)' == ''">
|
|
||||||
<EmbeddedResource Include="..\..\distribution\linux\shortcut-template.desktop" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64' OR '$(RuntimeIdentifier)' == ''">
|
|
||||||
<EmbeddedResource Include="..\..\distribution\macos\shortcut-template.plist" />
|
|
||||||
<EmbeddedResource Include="..\..\distribution\macos\shortcut-launch-script.sh" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DiscordRichPresence" />
|
<PackageReference Include="DiscordRichPresence" />
|
||||||
<PackageReference Include="DynamicData" />
|
<PackageReference Include="DynamicData" />
|
||||||
|
@ -20,11 +20,15 @@ using Ryujinx.Ava.UI.Models;
|
|||||||
using Ryujinx.Ava.UI.Renderer;
|
using Ryujinx.Ava.UI.Renderer;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
|
using Ryujinx.Ava.Utilities;
|
||||||
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Multiplayer;
|
using Ryujinx.Common.Configuration.Multiplayer;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.SystemInterop;
|
using Ryujinx.Common.SystemInterop;
|
||||||
|
using Ryujinx.Common.UI;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.GAL.Multithreading;
|
using Ryujinx.Graphics.GAL.Multithreading;
|
||||||
@ -39,10 +43,6 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
|
|||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
using Ryujinx.UI.App.Common;
|
|
||||||
using Ryujinx.UI.Common;
|
|
||||||
using Ryujinx.UI.Common.Configuration;
|
|
||||||
using Ryujinx.UI.Common.Helper;
|
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
using SPB.Graphics.Vulkan;
|
using SPB.Graphics.Vulkan;
|
||||||
@ -289,19 +289,19 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
private void UpdateScalingFilterLevel(object sender, ReactiveEventArgs<int> e)
|
private void UpdateScalingFilterLevel(object sender, ReactiveEventArgs<int> e)
|
||||||
{
|
{
|
||||||
_renderer.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
|
_renderer.Window?.SetScalingFilter(ConfigurationState.Instance.Graphics.ScalingFilter);
|
||||||
_renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
|
_renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateScalingFilter(object sender, ReactiveEventArgs<ScalingFilter> e)
|
private void UpdateScalingFilter(object sender, ReactiveEventArgs<ScalingFilter> e)
|
||||||
{
|
{
|
||||||
_renderer.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
|
_renderer.Window?.SetScalingFilter(ConfigurationState.Instance.Graphics.ScalingFilter);
|
||||||
_renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
|
_renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateColorSpacePassthrough(object sender, ReactiveEventArgs<bool> e)
|
private void UpdateColorSpacePassthrough(object sender, ReactiveEventArgs<bool> e)
|
||||||
{
|
{
|
||||||
_renderer.Window?.SetColorSpacePassthrough((bool)ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Value);
|
_renderer.Window?.SetColorSpacePassthrough(ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateVSyncMode(object sender, ReactiveEventArgs<VSyncMode> e)
|
public void UpdateVSyncMode(object sender, ReactiveEventArgs<VSyncMode> e)
|
||||||
@ -311,9 +311,10 @@ namespace Ryujinx.Ava
|
|||||||
Device.VSyncMode = e.NewValue;
|
Device.VSyncMode = e.NewValue;
|
||||||
Device.UpdateVSyncInterval();
|
Device.UpdateVSyncInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderer.Window?.ChangeVSyncMode(e.NewValue);
|
_renderer.Window?.ChangeVSyncMode(e.NewValue);
|
||||||
|
|
||||||
_viewModel.ShowCustomVSyncIntervalPicker = (e.NewValue == VSyncMode.Custom);
|
_viewModel.UpdateVSyncIntervalPicker();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void VSyncModeToggle()
|
public void VSyncModeToggle()
|
||||||
@ -526,7 +527,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
private void UpdateAntiAliasing(object sender, ReactiveEventArgs<AntiAliasing> e)
|
private void UpdateAntiAliasing(object sender, ReactiveEventArgs<AntiAliasing> e)
|
||||||
{
|
{
|
||||||
_renderer?.Window?.SetAntiAliasing((Graphics.GAL.AntiAliasing)e.NewValue);
|
_renderer?.Window?.SetAntiAliasing(e.NewValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateDockedModeState(object sender, ReactiveEventArgs<bool> e)
|
private void UpdateDockedModeState(object sender, ReactiveEventArgs<bool> e)
|
||||||
@ -577,7 +578,6 @@ namespace Ryujinx.Ava
|
|||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
_isActive = false;
|
_isActive = false;
|
||||||
DiscordIntegrationModule.SwitchToMainState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Exit()
|
private void Exit()
|
||||||
@ -861,13 +861,11 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationMetadata appMeta = ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
|
ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
|
||||||
appMetadata => appMetadata.UpdatePreGame()
|
appMetadata => appMetadata.UpdatePreGame()
|
||||||
);
|
);
|
||||||
|
|
||||||
DiscordIntegrationModule.SwitchToPlayingState(appMeta, Device.Processes.ActiveApplication);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -923,7 +921,7 @@ namespace Ryujinx.Ava
|
|||||||
// Initialize Configuration.
|
// Initialize Configuration.
|
||||||
var memoryConfiguration = ConfigurationState.Instance.System.DramSize.Value;
|
var memoryConfiguration = ConfigurationState.Instance.System.DramSize.Value;
|
||||||
|
|
||||||
Device = new HLE.Switch(new HLEConfiguration(
|
Device = new Switch(new HLEConfiguration(
|
||||||
VirtualFileSystem,
|
VirtualFileSystem,
|
||||||
_viewModel.LibHacHorizonManager,
|
_viewModel.LibHacHorizonManager,
|
||||||
ContentManager,
|
ContentManager,
|
||||||
@ -953,7 +951,8 @@ namespace Ryujinx.Ava
|
|||||||
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
||||||
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
||||||
ConfigurationState.Instance.Multiplayer.LdnServer,
|
ConfigurationState.Instance.Multiplayer.LdnServer,
|
||||||
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value));
|
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value,
|
||||||
|
ConfigurationState.Instance.Hacks.ShowDirtyHacks ? ConfigurationState.Instance.Hacks.EnabledHacks : null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IHardwareDeviceDriver InitializeAudio()
|
private static IHardwareDeviceDriver InitializeAudio()
|
||||||
@ -1057,10 +1056,10 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
Device.Gpu.Renderer.Initialize(_glLogLevel);
|
Device.Gpu.Renderer.Initialize(_glLogLevel);
|
||||||
|
|
||||||
_renderer?.Window?.SetAntiAliasing((Graphics.GAL.AntiAliasing)ConfigurationState.Instance.Graphics.AntiAliasing.Value);
|
_renderer?.Window?.SetAntiAliasing(ConfigurationState.Instance.Graphics.AntiAliasing);
|
||||||
_renderer?.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
|
_renderer?.Window?.SetScalingFilter(ConfigurationState.Instance.Graphics.ScalingFilter);
|
||||||
_renderer?.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
|
_renderer?.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel);
|
||||||
_renderer?.Window?.SetColorSpacePassthrough(ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Value);
|
_renderer?.Window?.SetColorSpacePassthrough(ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough);
|
||||||
|
|
||||||
Width = (int)RendererHost.Bounds.Width;
|
Width = (int)RendererHost.Bounds.Width;
|
||||||
Height = (int)RendererHost.Bounds.Height;
|
Height = (int)RendererHost.Bounds.Height;
|
||||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 253 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@ -15,12 +15,12 @@ using LibHac.Tools.FsSystem.NcaUtils;
|
|||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
using Ryujinx.Ava.UI.Controls;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
|
using Ryujinx.Common.Helper;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using Ryujinx.HLE.Loaders.Processes.Extensions;
|
using Ryujinx.HLE.Loaders.Processes.Extensions;
|
||||||
using Ryujinx.UI.Common.Configuration;
|
|
||||||
using Ryujinx.UI.Common.Helper;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.UI.Common.Configuration;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -2,7 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Models.Amiibo
|
namespace Ryujinx.Ava.Common.Models.Amiibo
|
||||||
{
|
{
|
||||||
public struct AmiiboApi : IEquatable<AmiiboApi>
|
public struct AmiiboApi : IEquatable<AmiiboApi>
|
||||||
{
|
{
|
@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Models.Amiibo
|
namespace Ryujinx.Ava.Common.Models.Amiibo
|
||||||
{
|
{
|
||||||
public class AmiiboApiGamesSwitch
|
public class AmiiboApiGamesSwitch
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Models.Amiibo
|
namespace Ryujinx.Ava.Common.Models.Amiibo
|
||||||
{
|
{
|
||||||
public class AmiiboApiUsage
|
public class AmiiboApiUsage
|
||||||
{
|
{
|
@ -2,7 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Models.Amiibo
|
namespace Ryujinx.Ava.Common.Models.Amiibo
|
||||||
{
|
{
|
||||||
public struct AmiiboJson
|
public struct AmiiboJson
|
||||||
{
|
{
|
@ -1,9 +1,7 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Models.Amiibo
|
namespace Ryujinx.Ava.Common.Models.Amiibo
|
||||||
{
|
{
|
||||||
[JsonSerializable(typeof(AmiiboJson))]
|
[JsonSerializable(typeof(AmiiboJson))]
|
||||||
public partial class AmiiboJsonSerializerContext : JsonSerializerContext
|
public partial class AmiiboJsonSerializerContext : JsonSerializerContext;
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
namespace Ryujinx.UI.Common.Models
|
namespace Ryujinx.Ava.Common.Models
|
||||||
{
|
{
|
||||||
// NOTE: most consuming code relies on this model being value-comparable
|
// NOTE: most consuming code relies on this model being value-comparable
|
||||||
public record DownloadableContentModel(ulong TitleId, string ContainerPath, string FullPath)
|
public record DownloadableContentModel(ulong TitleId, string ContainerPath, string FullPath)
|
@ -1,4 +1,4 @@
|
|||||||
namespace Ryujinx.UI.Common.Models.Github
|
namespace Ryujinx.Ava.Common.Models.Github
|
||||||
{
|
{
|
||||||
public class GithubReleaseAssetJsonResponse
|
public class GithubReleaseAssetJsonResponse
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Models.Github
|
namespace Ryujinx.Ava.Common.Models.Github
|
||||||
{
|
{
|
||||||
public class GithubReleasesJsonResponse
|
public class GithubReleasesJsonResponse
|
||||||
{
|
{
|
@ -1,9 +1,7 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Models.Github
|
namespace Ryujinx.Ava.Common.Models.Github
|
||||||
{
|
{
|
||||||
[JsonSerializable(typeof(GithubReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)]
|
[JsonSerializable(typeof(GithubReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||||
public partial class GithubReleasesJsonSerializerContext : JsonSerializerContext
|
public partial class GithubReleasesJsonSerializerContext : JsonSerializerContext;
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
namespace Ryujinx.UI.Common.Models
|
namespace Ryujinx.Ava.Common.Models
|
||||||
{
|
{
|
||||||
// NOTE: most consuming code relies on this model being value-comparable
|
// NOTE: most consuming code relies on this model being value-comparable
|
||||||
public record TitleUpdateModel(ulong TitleId, ulong Version, string DisplayVersion, string Path)
|
public record TitleUpdateModel(ulong TitleId, ulong Version, string DisplayVersion, string Path)
|
@ -1,8 +1,8 @@
|
|||||||
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.UI.App.Common;
|
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common.Models
|
namespace Ryujinx.Ava.Common.Models
|
||||||
{
|
{
|
||||||
public record XCITrimmerFileModel(
|
public record XCITrimmerFileModel(
|
||||||
string Name,
|
string Name,
|
@ -1,14 +1,14 @@
|
|||||||
using DiscordRPC;
|
using DiscordRPC;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
using Humanizer.Localisation;
|
using Humanizer.Localisation;
|
||||||
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.HLE;
|
||||||
using Ryujinx.HLE.Loaders.Processes;
|
using Ryujinx.HLE.Loaders.Processes;
|
||||||
using Ryujinx.UI.App.Common;
|
|
||||||
using Ryujinx.UI.Common.Configuration;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Common
|
namespace Ryujinx.Ava
|
||||||
{
|
{
|
||||||
public static class DiscordIntegrationModule
|
public static class DiscordIntegrationModule
|
||||||
{
|
{
|
||||||
@ -45,6 +45,16 @@ namespace Ryujinx.UI.Common
|
|||||||
};
|
};
|
||||||
|
|
||||||
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
|
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
|
||||||
|
TitleIDs.CurrentApplication.Event += (_, e) =>
|
||||||
|
{
|
||||||
|
if (e.NewValue)
|
||||||
|
SwitchToPlayingState(
|
||||||
|
ApplicationLibrary.LoadAndSaveMetaData(e.NewValue),
|
||||||
|
Switch.Shared.Processes.ActiveApplication
|
||||||
|
);
|
||||||
|
else
|
||||||
|
SwitchToMainState();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Update(object sender, ReactiveEventArgs<bool> evnt)
|
private static void Update(object sender, ReactiveEventArgs<bool> evnt)
|
||||||
@ -70,7 +80,7 @@ namespace Ryujinx.UI.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
|
private static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
|
||||||
{
|
{
|
||||||
_discordClient?.SetPresence(new RichPresence
|
_discordClient?.SetPresence(new RichPresence
|
||||||
{
|
{
|
||||||
@ -89,7 +99,7 @@ namespace Ryujinx.UI.Common
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SwitchToMainState() => _discordClient?.SetPresence(_discordPresenceMain);
|
private static void SwitchToMainState() => _discordClient?.SetPresence(_discordPresenceMain);
|
||||||
|
|
||||||
private static string TruncateToByteLength(string input)
|
private static string TruncateToByteLength(string input)
|
||||||
{
|
{
|
@ -2,7 +2,7 @@ using Ryujinx.HLE.UI;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2
|
namespace Ryujinx.Headless
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Headless text processing class, right now there is no way to forward the input to it.
|
/// Headless text processing class, right now there is no way to forward the input to it.
|
@ -1,6 +1,6 @@
|
|||||||
using Ryujinx.HLE.UI;
|
using Ryujinx.HLE.UI;
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2
|
namespace Ryujinx.Headless
|
||||||
{
|
{
|
||||||
internal class HeadlessHostUiTheme : IHostUITheme
|
internal class HeadlessHostUiTheme : IHostUITheme
|
||||||
{
|
{
|
366
src/Ryujinx/Headless/HeadlessRyujinx.Init.cs
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
using DiscordRPC;
|
||||||
|
using LibHac.Tools.FsSystem;
|
||||||
|
using Ryujinx.Audio.Backends.SDL2;
|
||||||
|
using Ryujinx.Ava;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Common.Utilities;
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.Graphics.GAL.Multithreading;
|
||||||
|
using Ryujinx.Graphics.Metal;
|
||||||
|
using Ryujinx.Graphics.OpenGL;
|
||||||
|
using Ryujinx.Graphics.Vulkan;
|
||||||
|
using Ryujinx.HLE;
|
||||||
|
using Ryujinx.Input;
|
||||||
|
using Silk.NET.Vulkan;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
||||||
|
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||||
|
using Key = Ryujinx.Common.Configuration.Hid.Key;
|
||||||
|
|
||||||
|
namespace Ryujinx.Headless
|
||||||
|
{
|
||||||
|
public partial class HeadlessRyujinx
|
||||||
|
{
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
// Ensure Discord presence timestamp begins at the absolute start of when Ryujinx is launched
|
||||||
|
DiscordIntegrationModule.StartedAt = Timestamps.Now;
|
||||||
|
|
||||||
|
// Delete backup files after updating.
|
||||||
|
Task.Run(Updater.CleanupUpdate);
|
||||||
|
|
||||||
|
// Hook unhandled exception and process exit events.
|
||||||
|
AppDomain.CurrentDomain.UnhandledException += (sender, e)
|
||||||
|
=> Program.ProcessUnhandledException(sender, e.ExceptionObject as Exception, e.IsTerminating);
|
||||||
|
AppDomain.CurrentDomain.ProcessExit += (_, _) => Program.Exit();
|
||||||
|
|
||||||
|
// Initialize the configuration.
|
||||||
|
ConfigurationState.Initialize();
|
||||||
|
|
||||||
|
// Initialize Discord integration.
|
||||||
|
DiscordIntegrationModule.Initialize();
|
||||||
|
|
||||||
|
// Logging system information.
|
||||||
|
Program.PrintSystemInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
||||||
|
{
|
||||||
|
if (inputId == null)
|
||||||
|
{
|
||||||
|
if (index == PlayerIndex.Player1)
|
||||||
|
{
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"{index} not configured, defaulting to default keyboard.");
|
||||||
|
|
||||||
|
// Default to keyboard
|
||||||
|
inputId = "0";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"{index} not configured");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(inputId);
|
||||||
|
|
||||||
|
bool isKeyboard = true;
|
||||||
|
|
||||||
|
if (gamepad == null)
|
||||||
|
{
|
||||||
|
gamepad = _inputManager.GamepadDriver.GetGamepad(inputId);
|
||||||
|
isKeyboard = false;
|
||||||
|
|
||||||
|
if (gamepad == null)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"{index} gamepad not found (\"{inputId}\")");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string gamepadName = gamepad.Name;
|
||||||
|
|
||||||
|
gamepad.Dispose();
|
||||||
|
|
||||||
|
InputConfig config;
|
||||||
|
|
||||||
|
if (inputProfileName == null || inputProfileName.Equals("default"))
|
||||||
|
{
|
||||||
|
if (isKeyboard)
|
||||||
|
{
|
||||||
|
config = new StandardKeyboardInputConfig
|
||||||
|
{
|
||||||
|
Version = InputConfig.CurrentVersion,
|
||||||
|
Backend = InputBackendType.WindowKeyboard,
|
||||||
|
Id = null,
|
||||||
|
ControllerType = ControllerType.JoyconPair,
|
||||||
|
LeftJoycon = new LeftJoyconCommonConfig<Key>
|
||||||
|
{
|
||||||
|
DpadUp = Key.Up,
|
||||||
|
DpadDown = Key.Down,
|
||||||
|
DpadLeft = Key.Left,
|
||||||
|
DpadRight = Key.Right,
|
||||||
|
ButtonMinus = Key.Minus,
|
||||||
|
ButtonL = Key.E,
|
||||||
|
ButtonZl = Key.Q,
|
||||||
|
ButtonSl = Key.Unbound,
|
||||||
|
ButtonSr = Key.Unbound,
|
||||||
|
},
|
||||||
|
|
||||||
|
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||||
|
{
|
||||||
|
StickUp = Key.W,
|
||||||
|
StickDown = Key.S,
|
||||||
|
StickLeft = Key.A,
|
||||||
|
StickRight = Key.D,
|
||||||
|
StickButton = Key.F,
|
||||||
|
},
|
||||||
|
|
||||||
|
RightJoycon = new RightJoyconCommonConfig<Key>
|
||||||
|
{
|
||||||
|
ButtonA = Key.Z,
|
||||||
|
ButtonB = Key.X,
|
||||||
|
ButtonX = Key.C,
|
||||||
|
ButtonY = Key.V,
|
||||||
|
ButtonPlus = Key.Plus,
|
||||||
|
ButtonR = Key.U,
|
||||||
|
ButtonZr = Key.O,
|
||||||
|
ButtonSl = Key.Unbound,
|
||||||
|
ButtonSr = Key.Unbound,
|
||||||
|
},
|
||||||
|
|
||||||
|
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||||
|
{
|
||||||
|
StickUp = Key.I,
|
||||||
|
StickDown = Key.K,
|
||||||
|
StickLeft = Key.J,
|
||||||
|
StickRight = Key.L,
|
||||||
|
StickButton = Key.H,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool isNintendoStyle = gamepadName.Contains("Nintendo");
|
||||||
|
|
||||||
|
config = new StandardControllerInputConfig
|
||||||
|
{
|
||||||
|
Version = InputConfig.CurrentVersion,
|
||||||
|
Backend = InputBackendType.GamepadSDL2,
|
||||||
|
Id = null,
|
||||||
|
ControllerType = ControllerType.JoyconPair,
|
||||||
|
DeadzoneLeft = 0.1f,
|
||||||
|
DeadzoneRight = 0.1f,
|
||||||
|
RangeLeft = 1.0f,
|
||||||
|
RangeRight = 1.0f,
|
||||||
|
TriggerThreshold = 0.5f,
|
||||||
|
LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
|
||||||
|
{
|
||||||
|
DpadUp = ConfigGamepadInputId.DpadUp,
|
||||||
|
DpadDown = ConfigGamepadInputId.DpadDown,
|
||||||
|
DpadLeft = ConfigGamepadInputId.DpadLeft,
|
||||||
|
DpadRight = ConfigGamepadInputId.DpadRight,
|
||||||
|
ButtonMinus = ConfigGamepadInputId.Minus,
|
||||||
|
ButtonL = ConfigGamepadInputId.LeftShoulder,
|
||||||
|
ButtonZl = ConfigGamepadInputId.LeftTrigger,
|
||||||
|
ButtonSl = ConfigGamepadInputId.Unbound,
|
||||||
|
ButtonSr = ConfigGamepadInputId.Unbound,
|
||||||
|
},
|
||||||
|
|
||||||
|
LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
||||||
|
{
|
||||||
|
Joystick = ConfigStickInputId.Left,
|
||||||
|
StickButton = ConfigGamepadInputId.LeftStick,
|
||||||
|
InvertStickX = false,
|
||||||
|
InvertStickY = false,
|
||||||
|
Rotate90CW = false,
|
||||||
|
},
|
||||||
|
|
||||||
|
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
|
||||||
|
{
|
||||||
|
ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
|
||||||
|
ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
|
||||||
|
ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
|
||||||
|
ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
|
||||||
|
ButtonPlus = ConfigGamepadInputId.Plus,
|
||||||
|
ButtonR = ConfigGamepadInputId.RightShoulder,
|
||||||
|
ButtonZr = ConfigGamepadInputId.RightTrigger,
|
||||||
|
ButtonSl = ConfigGamepadInputId.Unbound,
|
||||||
|
ButtonSr = ConfigGamepadInputId.Unbound,
|
||||||
|
},
|
||||||
|
|
||||||
|
RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
||||||
|
{
|
||||||
|
Joystick = ConfigStickInputId.Right,
|
||||||
|
StickButton = ConfigGamepadInputId.RightStick,
|
||||||
|
InvertStickX = false,
|
||||||
|
InvertStickY = false,
|
||||||
|
Rotate90CW = false,
|
||||||
|
},
|
||||||
|
|
||||||
|
Motion = new StandardMotionConfigController
|
||||||
|
{
|
||||||
|
MotionBackend = MotionInputBackendType.GamepadDriver,
|
||||||
|
EnableMotion = true,
|
||||||
|
Sensitivity = 100,
|
||||||
|
GyroDeadzone = 1,
|
||||||
|
},
|
||||||
|
Rumble = new RumbleConfigController
|
||||||
|
{
|
||||||
|
StrongRumble = 1f,
|
||||||
|
WeakRumble = 1f,
|
||||||
|
EnableRumble = false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string profileBasePath;
|
||||||
|
|
||||||
|
if (isKeyboard)
|
||||||
|
{
|
||||||
|
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "keyboard");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "controller");
|
||||||
|
}
|
||||||
|
|
||||||
|
string path = Path.Combine(profileBasePath, inputProfileName + ".json");
|
||||||
|
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" not found for \"{inputId}\"");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
|
||||||
|
}
|
||||||
|
catch (JsonException)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" parsing failed for \"{inputId}\"");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Id = inputId;
|
||||||
|
config.PlayerIndex = index;
|
||||||
|
|
||||||
|
string inputTypeName = isKeyboard ? "Keyboard" : "Gamepad";
|
||||||
|
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} configured with {inputTypeName} \"{config.Id}\"");
|
||||||
|
|
||||||
|
// If both stick ranges are 0 (usually indicative of an outdated profile load) then both sticks will be set to 1.0.
|
||||||
|
if (config is StandardControllerInputConfig controllerConfig)
|
||||||
|
{
|
||||||
|
if (controllerConfig.RangeLeft <= 0.0f && controllerConfig.RangeRight <= 0.0f)
|
||||||
|
{
|
||||||
|
controllerConfig.RangeLeft = 1.0f;
|
||||||
|
controllerConfig.RangeRight = 1.0f;
|
||||||
|
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} stick range reset. Save the profile now to update your configuration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IRenderer CreateRenderer(Options options, WindowBase window)
|
||||||
|
{
|
||||||
|
if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow)
|
||||||
|
{
|
||||||
|
string preferredGpuId = string.Empty;
|
||||||
|
Vk api = Vk.GetApi();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(options.PreferredGPUVendor))
|
||||||
|
{
|
||||||
|
string preferredGpuVendor = options.PreferredGPUVendor.ToLowerInvariant();
|
||||||
|
var devices = VulkanRenderer.GetPhysicalDevices(api);
|
||||||
|
|
||||||
|
foreach (var device in devices)
|
||||||
|
{
|
||||||
|
if (device.Vendor.ToLowerInvariant() == preferredGpuVendor)
|
||||||
|
{
|
||||||
|
preferredGpuId = device.Id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new VulkanRenderer(
|
||||||
|
api,
|
||||||
|
(instance, vk) => new SurfaceKHR((ulong)(vulkanWindow.CreateWindowSurface(instance.Handle))),
|
||||||
|
vulkanWindow.GetRequiredInstanceExtensions,
|
||||||
|
preferredGpuId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.GraphicsBackend == GraphicsBackend.Metal && window is MetalWindow metalWindow && OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
return new MetalRenderer(metalWindow.GetLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OpenGLRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)
|
||||||
|
{
|
||||||
|
BackendThreading threadingMode = options.BackendThreading;
|
||||||
|
|
||||||
|
bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
||||||
|
|
||||||
|
if (threadedGAL)
|
||||||
|
{
|
||||||
|
renderer = new ThreadedRenderer(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
HLEConfiguration configuration = new(_virtualFileSystem,
|
||||||
|
_libHacHorizonManager,
|
||||||
|
_contentManager,
|
||||||
|
_accountManager,
|
||||||
|
_userChannelPersistence,
|
||||||
|
renderer,
|
||||||
|
new SDL2HardwareDeviceDriver(),
|
||||||
|
options.DramSize,
|
||||||
|
window,
|
||||||
|
options.SystemLanguage,
|
||||||
|
options.SystemRegion,
|
||||||
|
options.VSyncMode,
|
||||||
|
!options.DisableDockedMode,
|
||||||
|
!options.DisablePTC,
|
||||||
|
options.EnableInternetAccess,
|
||||||
|
!options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
||||||
|
options.FsGlobalAccessLogMode,
|
||||||
|
options.SystemTimeOffset,
|
||||||
|
options.SystemTimeZone,
|
||||||
|
options.MemoryManagerMode,
|
||||||
|
options.IgnoreMissingServices,
|
||||||
|
options.AspectRatio,
|
||||||
|
options.AudioVolume,
|
||||||
|
options.UseHypervisor ?? true,
|
||||||
|
options.MultiplayerLanInterfaceId,
|
||||||
|
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
|
||||||
|
false,
|
||||||
|
string.Empty,
|
||||||
|
string.Empty,
|
||||||
|
options.CustomVSyncInterval);
|
||||||
|
|
||||||
|
return new Switch(configuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,10 @@
|
|||||||
using CommandLine;
|
using CommandLine;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using LibHac.Tools.FsSystem;
|
using Ryujinx.Ava;
|
||||||
using Ryujinx.Audio.Backends.SDL2;
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
|
||||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
|
||||||
using Ryujinx.Common.GraphicsDriver;
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Logging.Targets;
|
using Ryujinx.Common.Logging.Targets;
|
||||||
@ -15,16 +12,9 @@ using Ryujinx.Common.SystemInterop;
|
|||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.GAL.Multithreading;
|
|
||||||
using Ryujinx.Graphics.Gpu;
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.Graphics.Gpu.Shader;
|
using Ryujinx.Graphics.Gpu.Shader;
|
||||||
using Ryujinx.Graphics.Metal;
|
|
||||||
using Ryujinx.Graphics.OpenGL;
|
|
||||||
using Ryujinx.Graphics.Vulkan;
|
|
||||||
using Ryujinx.Graphics.Vulkan.MoltenVK;
|
using Ryujinx.Graphics.Vulkan.MoltenVK;
|
||||||
using Ryujinx.Headless.SDL2.Metal;
|
|
||||||
using Ryujinx.Headless.SDL2.OpenGL;
|
|
||||||
using Ryujinx.Headless.SDL2.Vulkan;
|
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
@ -33,22 +23,15 @@ using Ryujinx.Input;
|
|||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
using Ryujinx.Input.SDL2;
|
using Ryujinx.Input.SDL2;
|
||||||
using Ryujinx.SDL2.Common;
|
using Ryujinx.SDL2.Common;
|
||||||
using Silk.NET.Vulkan;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
|
||||||
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
|
||||||
using Key = Ryujinx.Common.Configuration.Hid.Key;
|
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2
|
namespace Ryujinx.Headless
|
||||||
{
|
{
|
||||||
class Program
|
public partial class HeadlessRyujinx
|
||||||
{
|
{
|
||||||
public static string Version { get; private set; }
|
|
||||||
|
|
||||||
private static VirtualFileSystem _virtualFileSystem;
|
private static VirtualFileSystem _virtualFileSystem;
|
||||||
private static ContentManager _contentManager;
|
private static ContentManager _contentManager;
|
||||||
private static AccountManager _accountManager;
|
private static AccountManager _accountManager;
|
||||||
@ -58,20 +41,18 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
private static Switch _emulationContext;
|
private static Switch _emulationContext;
|
||||||
private static WindowBase _window;
|
private static WindowBase _window;
|
||||||
private static WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
|
private static WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
|
||||||
private static List<InputConfig> _inputConfiguration;
|
private static List<InputConfig> _inputConfiguration = [];
|
||||||
private static bool _enableKeyboard;
|
private static bool _enableKeyboard;
|
||||||
private static bool _enableMouse;
|
private static bool _enableMouse;
|
||||||
|
|
||||||
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
static void Main(string[] args)
|
public static void Entrypoint(string[] args)
|
||||||
{
|
{
|
||||||
Version = ReleaseInformation.Version;
|
|
||||||
|
|
||||||
// Make process DPI aware for proper window sizing on high-res screens.
|
// Make process DPI aware for proper window sizing on high-res screens.
|
||||||
ForceDpiAware.Windows();
|
ForceDpiAware.Windows();
|
||||||
|
|
||||||
Console.Title = $"Ryujinx Console {Version} (Headless SDL2)";
|
Console.Title = $"Ryujinx Console {Program.Version} (Headless)";
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
|
if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
|
||||||
{
|
{
|
||||||
@ -99,7 +80,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
}
|
}
|
||||||
|
|
||||||
Parser.Default.ParseArguments<Options>(args)
|
Parser.Default.ParseArguments<Options>(args)
|
||||||
.WithParsed(Load)
|
.WithParsed(options => Load(args, options))
|
||||||
.WithNotParsed(errors =>
|
.WithNotParsed(errors =>
|
||||||
{
|
{
|
||||||
Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:");
|
Logger.Error?.PrintMsg(LogClass.Application, "Error parsing command-line arguments:");
|
||||||
@ -107,239 +88,81 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
errors.ForEach(err => Logger.Error?.PrintMsg(LogClass.Application, $" - {err.Tag}"));
|
errors.ForEach(err => Logger.Error?.PrintMsg(LogClass.Application, $" - {err.Tag}"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
public static void ReloadConfig(string customConfigPath = null)
|
||||||
{
|
{
|
||||||
if (inputId == null)
|
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
||||||
|
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
||||||
|
|
||||||
|
string configurationPath = null;
|
||||||
|
|
||||||
|
// Now load the configuration as the other subsystems are now registered
|
||||||
|
if (customConfigPath != null && File.Exists(customConfigPath))
|
||||||
{
|
{
|
||||||
if (index == PlayerIndex.Player1)
|
configurationPath = customConfigPath;
|
||||||
{
|
}
|
||||||
Logger.Info?.Print(LogClass.Application, $"{index} not configured, defaulting to default keyboard.");
|
else if (File.Exists(localConfigurationPath))
|
||||||
|
{
|
||||||
// Default to keyboard
|
configurationPath = localConfigurationPath;
|
||||||
inputId = "0";
|
}
|
||||||
}
|
else if (File.Exists(appDataConfigurationPath))
|
||||||
else
|
{
|
||||||
{
|
configurationPath = appDataConfigurationPath;
|
||||||
Logger.Info?.Print(LogClass.Application, $"{index} not configured");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(inputId);
|
if (configurationPath == null)
|
||||||
|
|
||||||
bool isKeyboard = true;
|
|
||||||
|
|
||||||
if (gamepad == null)
|
|
||||||
{
|
{
|
||||||
gamepad = _inputManager.GamepadDriver.GetGamepad(inputId);
|
// No configuration, we load the default values and save it to disk
|
||||||
isKeyboard = false;
|
configurationPath = appDataConfigurationPath;
|
||||||
|
Logger.Notice.Print(LogClass.Application, $"No configuration file found. Saving default configuration to: {configurationPath}");
|
||||||
|
|
||||||
if (gamepad == null)
|
ConfigurationState.Instance.LoadDefault();
|
||||||
{
|
ConfigurationState.Instance.ToFileFormat().SaveConfig(configurationPath);
|
||||||
Logger.Error?.Print(LogClass.Application, $"{index} gamepad not found (\"{inputId}\")");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string gamepadName = gamepad.Name;
|
|
||||||
|
|
||||||
gamepad.Dispose();
|
|
||||||
|
|
||||||
InputConfig config;
|
|
||||||
|
|
||||||
if (inputProfileName == null || inputProfileName.Equals("default"))
|
|
||||||
{
|
|
||||||
if (isKeyboard)
|
|
||||||
{
|
|
||||||
config = new StandardKeyboardInputConfig
|
|
||||||
{
|
|
||||||
Version = InputConfig.CurrentVersion,
|
|
||||||
Backend = InputBackendType.WindowKeyboard,
|
|
||||||
Id = null,
|
|
||||||
ControllerType = ControllerType.JoyconPair,
|
|
||||||
LeftJoycon = new LeftJoyconCommonConfig<Key>
|
|
||||||
{
|
|
||||||
DpadUp = Key.Up,
|
|
||||||
DpadDown = Key.Down,
|
|
||||||
DpadLeft = Key.Left,
|
|
||||||
DpadRight = Key.Right,
|
|
||||||
ButtonMinus = Key.Minus,
|
|
||||||
ButtonL = Key.E,
|
|
||||||
ButtonZl = Key.Q,
|
|
||||||
ButtonSl = Key.Unbound,
|
|
||||||
ButtonSr = Key.Unbound,
|
|
||||||
},
|
|
||||||
|
|
||||||
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
|
||||||
{
|
|
||||||
StickUp = Key.W,
|
|
||||||
StickDown = Key.S,
|
|
||||||
StickLeft = Key.A,
|
|
||||||
StickRight = Key.D,
|
|
||||||
StickButton = Key.F,
|
|
||||||
},
|
|
||||||
|
|
||||||
RightJoycon = new RightJoyconCommonConfig<Key>
|
|
||||||
{
|
|
||||||
ButtonA = Key.Z,
|
|
||||||
ButtonB = Key.X,
|
|
||||||
ButtonX = Key.C,
|
|
||||||
ButtonY = Key.V,
|
|
||||||
ButtonPlus = Key.Plus,
|
|
||||||
ButtonR = Key.U,
|
|
||||||
ButtonZr = Key.O,
|
|
||||||
ButtonSl = Key.Unbound,
|
|
||||||
ButtonSr = Key.Unbound,
|
|
||||||
},
|
|
||||||
|
|
||||||
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
|
||||||
{
|
|
||||||
StickUp = Key.I,
|
|
||||||
StickDown = Key.K,
|
|
||||||
StickLeft = Key.J,
|
|
||||||
StickRight = Key.L,
|
|
||||||
StickButton = Key.H,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool isNintendoStyle = gamepadName.Contains("Nintendo");
|
|
||||||
|
|
||||||
config = new StandardControllerInputConfig
|
|
||||||
{
|
|
||||||
Version = InputConfig.CurrentVersion,
|
|
||||||
Backend = InputBackendType.GamepadSDL2,
|
|
||||||
Id = null,
|
|
||||||
ControllerType = ControllerType.JoyconPair,
|
|
||||||
DeadzoneLeft = 0.1f,
|
|
||||||
DeadzoneRight = 0.1f,
|
|
||||||
RangeLeft = 1.0f,
|
|
||||||
RangeRight = 1.0f,
|
|
||||||
TriggerThreshold = 0.5f,
|
|
||||||
LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
|
|
||||||
{
|
|
||||||
DpadUp = ConfigGamepadInputId.DpadUp,
|
|
||||||
DpadDown = ConfigGamepadInputId.DpadDown,
|
|
||||||
DpadLeft = ConfigGamepadInputId.DpadLeft,
|
|
||||||
DpadRight = ConfigGamepadInputId.DpadRight,
|
|
||||||
ButtonMinus = ConfigGamepadInputId.Minus,
|
|
||||||
ButtonL = ConfigGamepadInputId.LeftShoulder,
|
|
||||||
ButtonZl = ConfigGamepadInputId.LeftTrigger,
|
|
||||||
ButtonSl = ConfigGamepadInputId.Unbound,
|
|
||||||
ButtonSr = ConfigGamepadInputId.Unbound,
|
|
||||||
},
|
|
||||||
|
|
||||||
LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
|
||||||
{
|
|
||||||
Joystick = ConfigStickInputId.Left,
|
|
||||||
StickButton = ConfigGamepadInputId.LeftStick,
|
|
||||||
InvertStickX = false,
|
|
||||||
InvertStickY = false,
|
|
||||||
Rotate90CW = false,
|
|
||||||
},
|
|
||||||
|
|
||||||
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
|
|
||||||
{
|
|
||||||
ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
|
|
||||||
ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
|
|
||||||
ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
|
|
||||||
ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
|
|
||||||
ButtonPlus = ConfigGamepadInputId.Plus,
|
|
||||||
ButtonR = ConfigGamepadInputId.RightShoulder,
|
|
||||||
ButtonZr = ConfigGamepadInputId.RightTrigger,
|
|
||||||
ButtonSl = ConfigGamepadInputId.Unbound,
|
|
||||||
ButtonSr = ConfigGamepadInputId.Unbound,
|
|
||||||
},
|
|
||||||
|
|
||||||
RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
|
||||||
{
|
|
||||||
Joystick = ConfigStickInputId.Right,
|
|
||||||
StickButton = ConfigGamepadInputId.RightStick,
|
|
||||||
InvertStickX = false,
|
|
||||||
InvertStickY = false,
|
|
||||||
Rotate90CW = false,
|
|
||||||
},
|
|
||||||
|
|
||||||
Motion = new StandardMotionConfigController
|
|
||||||
{
|
|
||||||
MotionBackend = MotionInputBackendType.GamepadDriver,
|
|
||||||
EnableMotion = true,
|
|
||||||
Sensitivity = 100,
|
|
||||||
GyroDeadzone = 1,
|
|
||||||
},
|
|
||||||
Rumble = new RumbleConfigController
|
|
||||||
{
|
|
||||||
StrongRumble = 1f,
|
|
||||||
WeakRumble = 1f,
|
|
||||||
EnableRumble = false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string profileBasePath;
|
Logger.Notice.Print(LogClass.Application, $"Loading configuration from: {configurationPath}");
|
||||||
|
|
||||||
if (isKeyboard)
|
if (ConfigurationFileFormat.TryLoad(configurationPath, out ConfigurationFileFormat configurationFileFormat))
|
||||||
{
|
{
|
||||||
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "keyboard");
|
ConfigurationState.Instance.Load(configurationFileFormat, configurationPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "controller");
|
Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location: {configurationPath}");
|
||||||
}
|
|
||||||
|
|
||||||
string path = Path.Combine(profileBasePath, inputProfileName + ".json");
|
ConfigurationState.Instance.LoadDefault();
|
||||||
|
|
||||||
if (!File.Exists(path))
|
|
||||||
{
|
|
||||||
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" not found for \"{inputId}\"");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
|
|
||||||
}
|
|
||||||
catch (JsonException)
|
|
||||||
{
|
|
||||||
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" parsing failed for \"{inputId}\"");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Id = inputId;
|
|
||||||
config.PlayerIndex = index;
|
|
||||||
|
|
||||||
string inputTypeName = isKeyboard ? "Keyboard" : "Gamepad";
|
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} configured with {inputTypeName} \"{config.Id}\"");
|
|
||||||
|
|
||||||
// If both stick ranges are 0 (usually indicative of an outdated profile load) then both sticks will be set to 1.0.
|
|
||||||
if (config is StandardControllerInputConfig controllerConfig)
|
|
||||||
{
|
|
||||||
if (controllerConfig.RangeLeft <= 0.0f && controllerConfig.RangeRight <= 0.0f)
|
|
||||||
{
|
|
||||||
controllerConfig.RangeLeft = 1.0f;
|
|
||||||
controllerConfig.RangeRight = 1.0f;
|
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} stick range reset. Save the profile now to update your configuration");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Load(Options option)
|
static void Load(string[] originalArgs, Options option)
|
||||||
{
|
{
|
||||||
AppDataManager.Initialize(option.BaseDataDir);
|
Initialize();
|
||||||
|
|
||||||
|
bool useLastUsedProfile = false;
|
||||||
|
|
||||||
|
if (option.InheritConfig)
|
||||||
|
{
|
||||||
|
option.InheritMainConfig(originalArgs, ConfigurationState.Instance, out useLastUsedProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppDataManager.Initialize(option.BaseDataDir);
|
||||||
|
|
||||||
|
if (useLastUsedProfile && AccountSaveDataManager.GetLastUsedUser().TryGet(out var profile))
|
||||||
|
option.UserProfile = profile.Name;
|
||||||
|
|
||||||
|
// Check if keys exists.
|
||||||
|
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
|
||||||
|
{
|
||||||
|
if (!(AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && File.Exists(Path.Combine(AppDataManager.KeysDirPathUser, "prod.keys"))))
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, "Keys not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReloadConfig();
|
||||||
|
|
||||||
_virtualFileSystem = VirtualFileSystem.CreateInstance();
|
_virtualFileSystem = VirtualFileSystem.CreateInstance();
|
||||||
_libHacHorizonManager = new LibHacHorizonManager();
|
_libHacHorizonManager = new LibHacHorizonManager();
|
||||||
|
|
||||||
@ -354,7 +177,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
|
|
||||||
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
|
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
|
||||||
|
|
||||||
GraphicsConfig.EnableShaderCache = true;
|
GraphicsConfig.EnableShaderCache = !option.DisableShaderCache;
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS())
|
if (OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
@ -365,15 +188,13 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IGamepad gamepad;
|
|
||||||
|
|
||||||
if (option.ListInputIds)
|
if (option.ListInputIds)
|
||||||
{
|
{
|
||||||
Logger.Info?.Print(LogClass.Application, "Input Ids:");
|
Logger.Info?.Print(LogClass.Application, "Input Ids:");
|
||||||
|
|
||||||
foreach (string id in _inputManager.KeyboardDriver.GamepadsIds)
|
foreach (string id in _inputManager.KeyboardDriver.GamepadsIds)
|
||||||
{
|
{
|
||||||
gamepad = _inputManager.KeyboardDriver.GetGamepad(id);
|
IGamepad gamepad = _inputManager.KeyboardDriver.GetGamepad(id);
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
||||||
|
|
||||||
@ -382,7 +203,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
|
|
||||||
foreach (string id in _inputManager.GamepadDriver.GamepadsIds)
|
foreach (string id in _inputManager.GamepadDriver.GamepadsIds)
|
||||||
{
|
{
|
||||||
gamepad = _inputManager.GamepadDriver.GetGamepad(id);
|
IGamepad gamepad = _inputManager.GamepadDriver.GetGamepad(id);
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
||||||
|
|
||||||
@ -399,7 +220,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_inputConfiguration = new List<InputConfig>();
|
_inputConfiguration ??= [];
|
||||||
_enableKeyboard = option.EnableKeyboard;
|
_enableKeyboard = option.EnableKeyboard;
|
||||||
_enableMouse = option.EnableMouse;
|
_enableMouse = option.EnableMouse;
|
||||||
|
|
||||||
@ -412,9 +233,9 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
_inputConfiguration.Add(inputConfig);
|
_inputConfiguration.Add(inputConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
||||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||||
LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3);
|
LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3);
|
||||||
LoadPlayerConfiguration(option.InputProfile4Name, option.InputId4, PlayerIndex.Player4);
|
LoadPlayerConfiguration(option.InputProfile4Name, option.InputId4, PlayerIndex.Player4);
|
||||||
LoadPlayerConfiguration(option.InputProfile5Name, option.InputId5, PlayerIndex.Player5);
|
LoadPlayerConfiguration(option.InputProfile5Name, option.InputId5, PlayerIndex.Player5);
|
||||||
@ -422,6 +243,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
LoadPlayerConfiguration(option.InputProfile7Name, option.InputId7, PlayerIndex.Player7);
|
LoadPlayerConfiguration(option.InputProfile7Name, option.InputId7, PlayerIndex.Player7);
|
||||||
LoadPlayerConfiguration(option.InputProfile8Name, option.InputId8, PlayerIndex.Player8);
|
LoadPlayerConfiguration(option.InputProfile8Name, option.InputId8, PlayerIndex.Player8);
|
||||||
LoadPlayerConfiguration(option.InputProfileHandheldName, option.InputIdHandheld, PlayerIndex.Handheld);
|
LoadPlayerConfiguration(option.InputProfileHandheldName, option.InputIdHandheld, PlayerIndex.Handheld);
|
||||||
|
|
||||||
|
|
||||||
if (_inputConfiguration.Count == 0)
|
if (_inputConfiguration.Count == 0)
|
||||||
{
|
{
|
||||||
@ -433,7 +255,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
Logger.SetEnable(LogLevel.Stub, !option.LoggingDisableStub);
|
Logger.SetEnable(LogLevel.Stub, !option.LoggingDisableStub);
|
||||||
Logger.SetEnable(LogLevel.Info, !option.LoggingDisableInfo);
|
Logger.SetEnable(LogLevel.Info, !option.LoggingDisableInfo);
|
||||||
Logger.SetEnable(LogLevel.Warning, !option.LoggingDisableWarning);
|
Logger.SetEnable(LogLevel.Warning, !option.LoggingDisableWarning);
|
||||||
Logger.SetEnable(LogLevel.Error, option.LoggingEnableError);
|
Logger.SetEnable(LogLevel.Error, !option.LoggingDisableError);
|
||||||
Logger.SetEnable(LogLevel.Trace, option.LoggingEnableTrace);
|
Logger.SetEnable(LogLevel.Trace, option.LoggingEnableTrace);
|
||||||
Logger.SetEnable(LogLevel.Guest, !option.LoggingDisableGuest);
|
Logger.SetEnable(LogLevel.Guest, !option.LoggingDisableGuest);
|
||||||
Logger.SetEnable(LogLevel.AccessLog, option.LoggingEnableFsAccessLog);
|
Logger.SetEnable(LogLevel.AccessLog, option.LoggingEnableFsAccessLog);
|
||||||
@ -522,88 +344,6 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IRenderer CreateRenderer(Options options, WindowBase window)
|
|
||||||
{
|
|
||||||
if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow)
|
|
||||||
{
|
|
||||||
string preferredGpuId = string.Empty;
|
|
||||||
Vk api = Vk.GetApi();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(options.PreferredGPUVendor))
|
|
||||||
{
|
|
||||||
string preferredGpuVendor = options.PreferredGPUVendor.ToLowerInvariant();
|
|
||||||
var devices = VulkanRenderer.GetPhysicalDevices(api);
|
|
||||||
|
|
||||||
foreach (var device in devices)
|
|
||||||
{
|
|
||||||
if (device.Vendor.ToLowerInvariant() == preferredGpuVendor)
|
|
||||||
{
|
|
||||||
preferredGpuId = device.Id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new VulkanRenderer(
|
|
||||||
api,
|
|
||||||
(instance, vk) => new SurfaceKHR((ulong)(vulkanWindow.CreateWindowSurface(instance.Handle))),
|
|
||||||
vulkanWindow.GetRequiredInstanceExtensions,
|
|
||||||
preferredGpuId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.GraphicsBackend == GraphicsBackend.Metal && window is MetalWindow metalWindow && OperatingSystem.IsMacOS())
|
|
||||||
{
|
|
||||||
return new MetalRenderer(metalWindow.GetLayer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new OpenGLRenderer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)
|
|
||||||
{
|
|
||||||
BackendThreading threadingMode = options.BackendThreading;
|
|
||||||
|
|
||||||
bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
|
||||||
|
|
||||||
if (threadedGAL)
|
|
||||||
{
|
|
||||||
renderer = new ThreadedRenderer(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
HLEConfiguration configuration = new(_virtualFileSystem,
|
|
||||||
_libHacHorizonManager,
|
|
||||||
_contentManager,
|
|
||||||
_accountManager,
|
|
||||||
_userChannelPersistence,
|
|
||||||
renderer,
|
|
||||||
new SDL2HardwareDeviceDriver(),
|
|
||||||
options.DramSize,
|
|
||||||
window,
|
|
||||||
options.SystemLanguage,
|
|
||||||
options.SystemRegion,
|
|
||||||
options.VSyncMode,
|
|
||||||
!options.DisableDockedMode,
|
|
||||||
!options.DisablePTC,
|
|
||||||
options.EnableInternetAccess,
|
|
||||||
!options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
|
||||||
options.FsGlobalAccessLogMode,
|
|
||||||
options.SystemTimeOffset,
|
|
||||||
options.SystemTimeZone,
|
|
||||||
options.MemoryManagerMode,
|
|
||||||
options.IgnoreMissingServices,
|
|
||||||
options.AspectRatio,
|
|
||||||
options.AudioVolume,
|
|
||||||
options.UseHypervisor ?? true,
|
|
||||||
options.MultiplayerLanInterfaceId,
|
|
||||||
Common.Configuration.Multiplayer.MultiplayerMode.Disabled,
|
|
||||||
false,
|
|
||||||
string.Empty,
|
|
||||||
string.Empty,
|
|
||||||
options.CustomVSyncInterval);
|
|
||||||
|
|
||||||
return new Switch(configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ExecutionEntrypoint()
|
private static void ExecutionEntrypoint()
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
@ -5,7 +5,7 @@ using SharpMetal.QuartzCore;
|
|||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
using static SDL2.SDL;
|
using static SDL2.SDL;
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2.Metal
|
namespace Ryujinx.Headless
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("macos")]
|
[SupportedOSPlatform("macos")]
|
||||||
class MetalWindow : WindowBase
|
class MetalWindow : WindowBase
|
@ -7,7 +7,7 @@ using Ryujinx.Input.HLE;
|
|||||||
using System;
|
using System;
|
||||||
using static SDL2.SDL;
|
using static SDL2.SDL;
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2.OpenGL
|
namespace Ryujinx.Headless
|
||||||
{
|
{
|
||||||
class OpenGLWindow : WindowBase
|
class OpenGLWindow : WindowBase
|
||||||
{
|
{
|
@ -1,13 +1,168 @@
|
|||||||
using CommandLine;
|
using CommandLine;
|
||||||
|
using Gommon;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2
|
namespace Ryujinx.Headless
|
||||||
{
|
{
|
||||||
public class Options
|
public class Options
|
||||||
{
|
{
|
||||||
|
public void InheritMainConfig(string[] originalArgs, ConfigurationState configurationState, out bool needsProfileSet)
|
||||||
|
{
|
||||||
|
needsProfileSet = NeedsOverride(nameof(UserProfile));
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(IsFullscreen)))
|
||||||
|
IsFullscreen = configurationState.UI.StartFullscreen;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(EnableKeyboard)))
|
||||||
|
EnableKeyboard = configurationState.Hid.EnableKeyboard;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(EnableMouse)))
|
||||||
|
EnableMouse = configurationState.Hid.EnableMouse;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(HideCursorMode)))
|
||||||
|
HideCursorMode = configurationState.HideCursor;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(DisablePTC)))
|
||||||
|
DisablePTC = !configurationState.System.EnablePtc;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(EnableInternetAccess)))
|
||||||
|
EnableInternetAccess = configurationState.System.EnableInternetAccess;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(DisableFsIntegrityChecks)))
|
||||||
|
DisableFsIntegrityChecks = configurationState.System.EnableFsIntegrityChecks;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(FsGlobalAccessLogMode)))
|
||||||
|
FsGlobalAccessLogMode = configurationState.System.FsGlobalAccessLogMode;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(VSyncMode)))
|
||||||
|
VSyncMode = configurationState.Graphics.VSyncMode;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(CustomVSyncInterval)))
|
||||||
|
CustomVSyncInterval = configurationState.Graphics.CustomVSyncInterval;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(DisableShaderCache)))
|
||||||
|
DisableShaderCache = !configurationState.Graphics.EnableShaderCache;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(EnableTextureRecompression)))
|
||||||
|
EnableTextureRecompression = configurationState.Graphics.EnableTextureRecompression;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(DisableDockedMode)))
|
||||||
|
DisableDockedMode = !configurationState.System.EnableDockedMode;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(SystemLanguage)))
|
||||||
|
SystemLanguage = (SystemLanguage)(int)configurationState.System.Language.Value;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(SystemRegion)))
|
||||||
|
SystemRegion = (RegionCode)(int)configurationState.System.Region.Value;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(SystemTimeZone)))
|
||||||
|
SystemTimeZone = configurationState.System.TimeZone;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(SystemTimeOffset)))
|
||||||
|
SystemTimeOffset = configurationState.System.SystemTimeOffset;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(MemoryManagerMode)))
|
||||||
|
MemoryManagerMode = configurationState.System.MemoryManagerMode;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(AudioVolume)))
|
||||||
|
AudioVolume = configurationState.System.AudioVolume;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(UseHypervisor)) && OperatingSystem.IsMacOS())
|
||||||
|
UseHypervisor = configurationState.System.UseHypervisor;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(MultiplayerLanInterfaceId)))
|
||||||
|
MultiplayerLanInterfaceId = configurationState.Multiplayer.LanInterfaceId;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(DisableFileLog)))
|
||||||
|
DisableFileLog = !configurationState.Logger.EnableFileLog;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(LoggingEnableDebug)))
|
||||||
|
LoggingEnableDebug = configurationState.Logger.EnableDebug;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(LoggingDisableStub)))
|
||||||
|
LoggingDisableStub = !configurationState.Logger.EnableStub;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(LoggingDisableInfo)))
|
||||||
|
LoggingDisableInfo = !configurationState.Logger.EnableInfo;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(LoggingDisableWarning)))
|
||||||
|
LoggingDisableWarning = !configurationState.Logger.EnableWarn;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(LoggingDisableError)))
|
||||||
|
LoggingDisableError = !configurationState.Logger.EnableError;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(LoggingEnableTrace)))
|
||||||
|
LoggingEnableTrace = configurationState.Logger.EnableTrace;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(LoggingDisableGuest)))
|
||||||
|
LoggingDisableGuest = !configurationState.Logger.EnableGuest;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(LoggingEnableFsAccessLog)))
|
||||||
|
LoggingEnableFsAccessLog = configurationState.Logger.EnableFsAccessLog;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(LoggingGraphicsDebugLevel)))
|
||||||
|
LoggingGraphicsDebugLevel = configurationState.Logger.GraphicsDebugLevel;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(ResScale)))
|
||||||
|
ResScale = configurationState.Graphics.ResScale;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(MaxAnisotropy)))
|
||||||
|
MaxAnisotropy = configurationState.Graphics.MaxAnisotropy;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(AspectRatio)))
|
||||||
|
AspectRatio = configurationState.Graphics.AspectRatio;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(BackendThreading)))
|
||||||
|
BackendThreading = configurationState.Graphics.BackendThreading;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(DisableMacroHLE)))
|
||||||
|
DisableMacroHLE = !configurationState.Graphics.EnableMacroHLE;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(GraphicsShadersDumpPath)))
|
||||||
|
GraphicsShadersDumpPath = configurationState.Graphics.ShadersDumpPath;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(GraphicsBackend)))
|
||||||
|
GraphicsBackend = configurationState.Graphics.GraphicsBackend;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(AntiAliasing)))
|
||||||
|
AntiAliasing = configurationState.Graphics.AntiAliasing;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(ScalingFilter)))
|
||||||
|
ScalingFilter = configurationState.Graphics.ScalingFilter;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(ScalingFilterLevel)))
|
||||||
|
ScalingFilterLevel = configurationState.Graphics.ScalingFilterLevel;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(DramSize)))
|
||||||
|
DramSize = configurationState.System.DramSize;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(IgnoreMissingServices)))
|
||||||
|
IgnoreMissingServices = configurationState.System.IgnoreMissingServices;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(IgnoreControllerApplet)))
|
||||||
|
IgnoreControllerApplet = configurationState.IgnoreApplet;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
|
||||||
|
|
||||||
|
string OptionName(string propertyName) =>
|
||||||
|
typeof(Options)!.GetProperty(propertyName)!.GetCustomAttribute<OptionAttribute>()!.LongName;
|
||||||
|
}
|
||||||
|
|
||||||
// General
|
// General
|
||||||
|
|
||||||
|
[Option("use-main-config", Required = false, Default = false, HelpText = "Use the settings from what was configured via the UI.")]
|
||||||
|
public bool InheritConfig { get; set; }
|
||||||
|
|
||||||
[Option("root-data-dir", Required = false, HelpText = "Set the custom folder path for Ryujinx data.")]
|
[Option("root-data-dir", Required = false, HelpText = "Set the custom folder path for Ryujinx data.")]
|
||||||
public string BaseDataDir { get; set; }
|
public string BaseDataDir { get; set; }
|
||||||
@ -95,10 +250,10 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
[Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")]
|
[Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")]
|
||||||
public HideCursorMode HideCursorMode { get; set; }
|
public HideCursorMode HideCursorMode { get; set; }
|
||||||
|
|
||||||
[Option("list-input-profiles", Required = false, HelpText = "List inputs profiles.")]
|
[Option("list-input-profiles", Required = false, HelpText = "List input profiles.")]
|
||||||
public bool ListInputProfiles { get; set; }
|
public bool ListInputProfiles { get; set; }
|
||||||
|
|
||||||
[Option("list-inputs-ids", Required = false, HelpText = "List inputs ids.")]
|
[Option("list-input-ids", Required = false, HelpText = "List input IDs.")]
|
||||||
public bool ListInputIds { get; set; }
|
public bool ListInputIds { get; set; }
|
||||||
|
|
||||||
// System
|
// System
|
||||||
@ -172,7 +327,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
public bool LoggingDisableWarning { get; set; }
|
public bool LoggingDisableWarning { get; set; }
|
||||||
|
|
||||||
[Option("disable-error-logs", Required = false, HelpText = "Disables printing error log messages.")]
|
[Option("disable-error-logs", Required = false, HelpText = "Disables printing error log messages.")]
|
||||||
public bool LoggingEnableError { get; set; }
|
public bool LoggingDisableError { get; set; }
|
||||||
|
|
||||||
[Option("enable-trace-logs", Required = false, Default = false, HelpText = "Enables printing trace log messages.")]
|
[Option("enable-trace-logs", Required = false, Default = false, HelpText = "Enables printing trace log messages.")]
|
||||||
public bool LoggingEnableTrace { get; set; }
|
public bool LoggingEnableTrace { get; set; }
|
||||||
@ -215,7 +370,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
[Option("anti-aliasing", Required = false, Default = AntiAliasing.None, HelpText = "Set the type of anti aliasing being used. [None|Fxaa|SmaaLow|SmaaMedium|SmaaHigh|SmaaUltra]")]
|
[Option("anti-aliasing", Required = false, Default = AntiAliasing.None, HelpText = "Set the type of anti aliasing being used. [None|Fxaa|SmaaLow|SmaaMedium|SmaaHigh|SmaaUltra]")]
|
||||||
public AntiAliasing AntiAliasing { get; set; }
|
public AntiAliasing AntiAliasing { get; set; }
|
||||||
|
|
||||||
[Option("scaling-filter", Required = false, Default = ScalingFilter.Bilinear, HelpText = "Set the scaling filter. [Bilinear|Nearest|Fsr]")]
|
[Option("scaling-filter", Required = false, Default = ScalingFilter.Bilinear, HelpText = "Set the scaling filter. [Bilinear|Nearest|Fsr|Area]")]
|
||||||
public ScalingFilter ScalingFilter { get; set; }
|
public ScalingFilter ScalingFilter { get; set; }
|
||||||
|
|
||||||
[Option("scaling-filter-level", Required = false, Default = 0, HelpText = "Set the scaling filter intensity (currently only applies to FSR). [0-100]")]
|
[Option("scaling-filter-level", Required = false, Default = 0, HelpText = "Set the scaling filter intensity (currently only applies to FSR). [0-100]")]
|
BIN
src/Ryujinx/Headless/Ryujinx.bmp
Normal file
After Width: | Height: | Size: 3.9 KiB |
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2
|
namespace Ryujinx.Headless
|
||||||
{
|
{
|
||||||
class StatusUpdatedEventArgs(
|
class StatusUpdatedEventArgs(
|
||||||
string vSyncMode,
|
string vSyncMode,
|
@ -6,7 +6,7 @@ using System;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using static SDL2.SDL;
|
using static SDL2.SDL;
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2.Vulkan
|
namespace Ryujinx.Headless
|
||||||
{
|
{
|
||||||
class VulkanWindow : WindowBase
|
class VulkanWindow : WindowBase
|
||||||
{
|
{
|
@ -1,5 +1,6 @@
|
|||||||
using Humanizer;
|
using Humanizer;
|
||||||
using LibHac.Tools.Fs;
|
using LibHac.Tools.Fs;
|
||||||
|
using Ryujinx.Ava;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
@ -26,7 +27,7 @@ using AntiAliasing = Ryujinx.Common.Configuration.AntiAliasing;
|
|||||||
using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter;
|
using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter;
|
||||||
using Switch = Ryujinx.HLE.Switch;
|
using Switch = Ryujinx.HLE.Switch;
|
||||||
|
|
||||||
namespace Ryujinx.Headless.SDL2
|
namespace Ryujinx.Headless
|
||||||
{
|
{
|
||||||
abstract partial class WindowBase : IHostUIHandler, IDisposable
|
abstract partial class WindowBase : IHostUIHandler, IDisposable
|
||||||
{
|
{
|
||||||
@ -136,7 +137,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
|
|
||||||
private void SetWindowIcon()
|
private void SetWindowIcon()
|
||||||
{
|
{
|
||||||
Stream iconStream = typeof(WindowBase).Assembly.GetManifestResourceStream("Ryujinx.Headless.SDL2.Ryujinx.bmp");
|
Stream iconStream = typeof(Program).Assembly.GetManifestResourceStream("HeadlessLogo");
|
||||||
byte[] iconBytes = new byte[iconStream!.Length];
|
byte[] iconBytes = new byte[iconStream!.Length];
|
||||||
|
|
||||||
if (iconStream.Read(iconBytes, 0, iconBytes.Length) != iconBytes.Length)
|
if (iconStream.Read(iconBytes, 0, iconBytes.Length) != iconBytes.Length)
|
||||||
@ -254,12 +255,12 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
|
|
||||||
private void SetAntiAliasing()
|
private void SetAntiAliasing()
|
||||||
{
|
{
|
||||||
Renderer?.Window.SetAntiAliasing((Graphics.GAL.AntiAliasing)AntiAliasing);
|
Renderer?.Window.SetAntiAliasing(AntiAliasing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetScalingFilter()
|
private void SetScalingFilter()
|
||||||
{
|
{
|
||||||
Renderer?.Window.SetScalingFilter((Graphics.GAL.ScalingFilter)ScalingFilter);
|
Renderer?.Window.SetScalingFilter(ScalingFilter);
|
||||||
Renderer?.Window.SetScalingFilterLevel(ScalingFilterLevel);
|
Renderer?.Window.SetScalingFilterLevel(ScalingFilterLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +319,7 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
Device.VSyncMode.ToString(),
|
Device.VSyncMode.ToString(),
|
||||||
dockedMode,
|
dockedMode,
|
||||||
Device.Configuration.AspectRatio.ToText(),
|
Device.Configuration.AspectRatio.ToText(),
|
||||||
$"Game: {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
|
$"{Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
|
||||||
$"FIFO: {Device.Statistics.GetFifoPercent():0.00} %",
|
$"FIFO: {Device.Statistics.GetFifoPercent():0.00} %",
|
||||||
$"GPU: {_gpuDriverName}"));
|
$"GPU: {_gpuDriverName}"));
|
||||||
|
|