Compare commits

..

No commits in common. "master" and "Canary-1.3.89" have entirely different histories.

85 changed files with 2241 additions and 4720 deletions

View File

@ -106,47 +106,45 @@ jobs:
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz" gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz"
shell: bash shell: bash
# If anyone wants to look into why appimagetool randomly errors with exit code 8, that would be cool - name: Build AppImage (Linux)
if: matrix.platform.os == 'ubuntu-latest'
run: |
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
PLATFORM_NAME="${{ matrix.platform.name }}"
# - name: Build AppImage (Linux) sudo apt install -y zsync desktop-file-utils appstream
# if: matrix.platform.os == 'ubuntu-latest'
# run: | mkdir -p tools
# BUILD_VERSION="${{ steps.version_info.outputs.build_version }}" export PATH="$PATH:$(readlink -f tools)"
# PLATFORM_NAME="${{ matrix.platform.name }}"
# # Setup appimagetool
# sudo apt install -y zsync desktop-file-utils appstream wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
# chmod +x tools/appimagetool
# mkdir -p tools chmod +x distribution/linux/appimage/build-appimage.sh
# export PATH="$PATH:$(readlink -f tools)"
# # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
# # Setup appimagetool if [ "$PLATFORM_NAME" = "linux-x64" ]; then
# wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" ARCH_NAME=x64
# chmod +x tools/appimagetool export ARCH=x86_64
# chmod +x distribution/linux/appimage/build-appimage.sh elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
# ARCH_NAME=arm64
# # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name) export ARCH=aarch64
# if [ "$PLATFORM_NAME" = "linux-x64" ]; then else
# ARCH_NAME=x64 echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
# export ARCH=x86_64 exit 1
# elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then fi
# ARCH_NAME=arm64
# export ARCH=aarch64 export UFLAG="gh-releases-zsync|${{ secrets.RC_OWNER }}${{ secrets.RC_CANARY_NAME }}|latest|*-$ARCH_NAME.AppImage.zsync"
# else BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
# echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
# exit 1 pushd publish_appimage
# fi mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
# mv Ryujinx.AppImage.zsync ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
# export UFLAG="gh-releases-zsync|${{ secrets.RC_OWNER }}${{ secrets.RC_CANARY_NAME }}|latest|*-$ARCH_NAME.AppImage.zsync" popd
# BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage"
# pushd publish_appimage gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
# mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage shell: bash
# mv Ryujinx.AppImage.zsync ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
# popd
#
# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage"
# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
# shell: bash
macos_release: macos_release:
name: Release MacOS universal name: Release MacOS universal

View File

@ -97,47 +97,45 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# If anyone wants to look into why appimagetool randomly errors with exit code 8, that would be cool - name: Build AppImage (Linux)
if: matrix.platform.os == 'ubuntu-latest'
run: |
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
PLATFORM_NAME="${{ matrix.platform.name }}"
# - name: Build AppImage (Linux) sudo apt install -y zsync desktop-file-utils appstream
# if: matrix.platform.os == 'ubuntu-latest'
# run: | mkdir -p tools
# BUILD_VERSION="${{ steps.version_info.outputs.build_version }}" export PATH="$PATH:$(readlink -f tools)"
# PLATFORM_NAME="${{ matrix.platform.name }}"
# # Setup appimagetool
# sudo apt install -y zsync desktop-file-utils appstream wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
# chmod +x tools/appimagetool
# mkdir -p tools chmod +x distribution/linux/appimage/build-appimage.sh
# export PATH="$PATH:$(readlink -f tools)"
# # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
# # Setup appimagetool if [ "$PLATFORM_NAME" = "linux-x64" ]; then
# wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" ARCH_NAME=x64
# chmod +x tools/appimagetool export ARCH=x86_64
# chmod +x distribution/linux/appimage/build-appimage.sh elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
# ARCH_NAME=arm64
# # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name) export ARCH=aarch64
# if [ "$PLATFORM_NAME" = "linux-x64" ]; then else
# ARCH_NAME=x64 echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
# export ARCH=x86_64 exit 1
# elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then fi
# ARCH_NAME=arm64
# export ARCH=aarch64 export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync"
# else BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
# echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
# exit 1 pushd publish_appimage
# fi mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
# mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
# export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync" popd
# BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage"
# pushd publish_appimage gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
# mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage shell: bash
# mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
# popd
#
# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage"
# gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
# shell: bash
macos_release: macos_release:
name: Release MacOS universal name: Release MacOS universal

View File

@ -40,10 +40,8 @@
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" /> <PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" /> <PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.116" /> <PackageVersion Include="Ryujinx.LibHac" Version="0.20.0" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" /> <PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.29" />
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.29" />
<PackageVersion Include="Gommon" Version="2.7.1.1" /> <PackageVersion Include="Gommon" Version="2.7.1.1" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="Sep" Version="0.6.0" /> <PackageVersion Include="Sep" Version="0.6.0" />

View File

@ -7,8 +7,8 @@
# Ryujinx # Ryujinx
[![Latest release](https://img.shields.io/gitlab/v/release/ryubing%2Fryujinx?gitlab_url=https%3A%2F%2Fgit.ryujinx.app&label=stable&color=32cd32)](https://update.ryujinx.app/latest/stable) [![Latest release](https://img.shields.io/gitlab/v/release/ryubing%2Fryujinx?gitlab_url=https%3A%2F%2Fgit.ryujinx.app&label=stable&color=32cd32)](https://git.ryujinx.app/ryubing/ryujinx/-/releases)
[![Latest canary release](https://img.shields.io/gitlab/v/release/ryubing%2Fcanary?gitlab_url=https%3A%2F%2Fgit.ryujinx.app&label=canary&color=FF4500)](https://update.ryujinx.app/latest/canary) [![Latest canary release](https://img.shields.io/gitlab/v/release/ryubing%2Fcanary?gitlab_url=https%3A%2F%2Fgit.ryujinx.app&label=canary&color=FF4500)](https://git.ryujinx.app/ryubing/canary/-/releases)
<br> <br>
<a href="https://discord.gg/PEuzjrFXUA"> <a href="https://discord.gg/PEuzjrFXUA">
<img src="https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Ryubing&logo=discord&logoColor=white" alt="Discord"> <img src="https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Ryubing&logo=discord&logoColor=white" alt="Discord">

View File

@ -77,8 +77,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Gene
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig .editorconfig = .editorconfig
@ -86,9 +84,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.github\workflows\canary.yml = .github\workflows\canary.yml .github\workflows\canary.yml = .github\workflows\canary.yml
Directory.Packages.props = Directory.Packages.props Directory.Packages.props = Directory.Packages.props
.github\workflows\release.yml = .github\workflows\release.yml .github\workflows\release.yml = .github\workflows\release.yml
nuget.config = nuget.config
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU

File diff suppressed because it is too large Load Diff

View File

@ -188,8 +188,6 @@
01003DD00BFEE000,"Airheart - Tales of broken Wings",,playable,2021-02-26 15:20:27 01003DD00BFEE000,"Airheart - Tales of broken Wings",,playable,2021-02-26 15:20:27
01007F100DE52000,"Akane",nvdec,playable,2022-07-21 00:12:18 01007F100DE52000,"Akane",nvdec,playable,2022-07-21 00:12:18
01009A800F0C8000,"Akash: Path of the Five",gpu;nvdec,ingame,2020-12-14 22:33:12 01009A800F0C8000,"Akash: Path of the Five",gpu;nvdec,ingame,2020-12-14 22:33:12
01009E8012976000,"AKIBA'S TRIP: Hellbound & Debriefed",,playable,2025-07-30 23:22:47
0100D74019A0E000,"AKIBA'S TRIP: Undead & Undressed Director's Cut",,playable,2025-07-31 13:58:42
010053100B0EA000,"Akihabara - Feel the Rhythm Remixed",,playable,2021-02-22 14:39:35 010053100B0EA000,"Akihabara - Feel the Rhythm Remixed",,playable,2021-02-22 14:39:35
0100D4C00EE0C000,"Akuarium",slow,playable,2020-12-12 23:43:36 0100D4C00EE0C000,"Akuarium",slow,playable,2020-12-12 23:43:36
010026E00FEBE000,"Akuto: Showdown",,playable,2020-08-04 19:43:27 010026E00FEBE000,"Akuto: Showdown",,playable,2020-08-04 19:43:27
@ -1097,7 +1095,6 @@
0100F9600E746000,"ESP Ra.De. Psi",audio;slow,ingame,2024-03-07 15:05:08 0100F9600E746000,"ESP Ra.De. Psi",audio;slow,ingame,2024-03-07 15:05:08
010073000FE18000,"Esports powerful pro yakyuu 2020",gpu;crash;Needs More Attention,ingame,2024-04-29 05:34:14 010073000FE18000,"Esports powerful pro yakyuu 2020",gpu;crash;Needs More Attention,ingame,2024-04-29 05:34:14
01004F9012FD8000,"Estranged: The Departure",nvdec;UE4,playable,2022-10-24 10:37:58 01004F9012FD8000,"Estranged: The Departure",nvdec;UE4,playable,2022-10-24 10:37:58
010018f01e0a0000,"Eternights",,playable,2025-07-30 12:10:24
0100CB900B498000,"Eternum Ex",,playable,2021-01-13 20:28:32 0100CB900B498000,"Eternum Ex",,playable,2021-01-13 20:28:32
010092501EB2C000,"Europa (Demo)",gpu;crash;UE4,ingame,2024-04-23 10:47:12 010092501EB2C000,"Europa (Demo)",gpu;crash;UE4,ingame,2024-04-23 10:47:12
01007BE0160D6000,"EVE ghost enemies",gpu,ingame,2023-01-14 03:13:30 01007BE0160D6000,"EVE ghost enemies",gpu,ingame,2023-01-14 03:13:30
@ -1243,8 +1240,6 @@
010003F00BD48000,"Friday the 13th: Killer Puzzle",,playable,2021-01-28 01:33:38 010003F00BD48000,"Friday the 13th: Killer Puzzle",,playable,2021-01-28 01:33:38
010092A00C4B6000,"Friday the 13th: The Game Ultimate Slasher Edition",nvdec;online-broken;UE4,playable,2022-09-06 17:33:27 010092A00C4B6000,"Friday the 13th: The Game Ultimate Slasher Edition",nvdec;online-broken;UE4,playable,2022-09-06 17:33:27
0100F200178F4000,"FRONT MISSION 1st: Remake",,playable,2023-06-09 07:44:24 0100F200178F4000,"FRONT MISSION 1st: Remake",,playable,2023-06-09 07:44:24
0100c4e018a24000,"FRONT MISSION 2: Remake",,playable,2025-07-30 12:11:23
01007E6019872000,"FRONT MISSION 3: Remake",,playable,2025-07-30 12:12:02
0100861012474000,"Frontline Zed",,playable,2020-10-03 12:55:59 0100861012474000,"Frontline Zed",,playable,2020-10-03 12:55:59
0100B5300B49A000,"Frost",,playable,2022-07-27 12:00:36 0100B5300B49A000,"Frost",,playable,2022-07-27 12:00:36
010038A007AA4000,"FruitFall Crush",,playable,2020-10-20 11:33:33 010038A007AA4000,"FruitFall Crush",,playable,2020-10-20 11:33:33
@ -1523,7 +1518,6 @@
010095C016C14000,"Iridium",,playable,2022-08-05 23:19:53 010095C016C14000,"Iridium",,playable,2022-08-05 23:19:53
0100AD300B786000,"Iris School of Wizardry -Vinculum Hearts-",,playable,2022-12-05 13:11:15 0100AD300B786000,"Iris School of Wizardry -Vinculum Hearts-",,playable,2022-12-05 13:11:15
0100945012168000,"Iris.Fall",nvdec,playable,2022-10-18 13:40:22 0100945012168000,"Iris.Fall",nvdec,playable,2022-10-18 13:40:22
010059801B736000,"IronFall: Invasion",,playable,2025-07-30 11:42:30
01005270118D6000,"Iron Wings",slow,ingame,2022-08-07 08:32:57 01005270118D6000,"Iron Wings",slow,ingame,2022-08-07 08:32:57
01004DB003E6A000,"IRONCAST",,playable,2021-01-13 13:54:29 01004DB003E6A000,"IRONCAST",,playable,2021-01-13 13:54:29
0100E5700CD56000,"Irony Curtain: From Matryoshka with Love",,playable,2021-06-04 20:12:37 0100E5700CD56000,"Irony Curtain: From Matryoshka with Love",,playable,2021-06-04 20:12:37
@ -2263,7 +2257,6 @@
010086F0064CE000,"Poi: Explorer Edition",nvdec,playable,2021-01-21 19:32:00 010086F0064CE000,"Poi: Explorer Edition",nvdec,playable,2021-01-21 19:32:00
0100EB6012FD2000,"Poison Control",,playable,2021-05-16 14:01:54 0100EB6012FD2000,"Poison Control",,playable,2021-05-16 14:01:54
010072400E04A000,"Pokémon Café ReMix",,playable,2021-08-17 20:00:04 010072400E04A000,"Pokémon Café ReMix",,playable,2021-08-17 20:00:04
010008c01e742000,"Pokémon Friends",crash;services,menus,2025-07-24 13:32:00
01003D200BAA2000,"Pokémon Mystery Dungeon™: Rescue Team DX",mac-bug,playable,2024-01-21 00:16:32 01003D200BAA2000,"Pokémon Mystery Dungeon™: Rescue Team DX",mac-bug,playable,2024-01-21 00:16:32
01008DB008C2C000,"Pokémon Shield + Pokémon Shield Expansion Pass",deadlock;crash;online-broken;ldn-works;LAN,ingame,2024-08-12 07:20:22 01008DB008C2C000,"Pokémon Shield + Pokémon Shield Expansion Pass",deadlock;crash;online-broken;ldn-works;LAN,ingame,2024-08-12 07:20:22
0100ABF008968000,"Pokémon Sword + Pokémon Sword Expansion Pass",deadlock;crash;online-broken;ldn-works;LAN,ingame,2024-08-26 15:40:37 0100ABF008968000,"Pokémon Sword + Pokémon Sword Expansion Pass",deadlock;crash;online-broken;ldn-works;LAN,ingame,2024-08-26 15:40:37
@ -2312,7 +2305,6 @@
010077B00BDD8000,"Professional Farmer: Nintendo Switch™ Edition",slow,playable,2020-12-16 13:38:19 010077B00BDD8000,"Professional Farmer: Nintendo Switch™ Edition",slow,playable,2020-12-16 13:38:19
010018300C83A000,"Professor Lupo and his Horrible Pets",,playable,2020-06-12 00:08:45 010018300C83A000,"Professor Lupo and his Horrible Pets",,playable,2020-06-12 00:08:45
0100D1F0132F6000,"Professor Lupo: Ocean",,playable,2021-04-14 16:33:33 0100D1F0132F6000,"Professor Lupo: Ocean",,playable,2021-04-14 16:33:33
0100c3a017834000,"Prodeus",,playable,2025-07-30 12:07:52
0100BBD00976C000,"Project Highrise: Architect's Edition",,playable,2022-08-10 17:19:12 0100BBD00976C000,"Project Highrise: Architect's Edition",,playable,2022-08-10 17:19:12
0100ACE00DAB6000,"Project Nimbus: Complete Edition",nvdec;UE4;vulkan-backend-bug,playable,2022-08-10 17:35:43 0100ACE00DAB6000,"Project Nimbus: Complete Edition",nvdec;UE4;vulkan-backend-bug,playable,2022-08-10 17:35:43
01002980140F6000,"Project TRIANGLE STRATEGY™ Debut Demo",UE4;demo,playable,2022-10-24 21:40:27 01002980140F6000,"Project TRIANGLE STRATEGY™ Debut Demo",UE4;demo,playable,2022-10-24 21:40:27
@ -2444,7 +2436,6 @@
0100E9C010EA8000,"Rise of Insanity",,playable,2020-08-30 15:42:14 0100E9C010EA8000,"Rise of Insanity",,playable,2020-08-30 15:42:14
01006BA00E652000,"Rise: Race The Future",,playable,2021-02-27 13:29:06 01006BA00E652000,"Rise: Race The Future",,playable,2021-02-27 13:29:06
010020C012F48000,"Rising Hell",,playable,2022-10-31 13:54:02 010020C012F48000,"Rising Hell",,playable,2022-10-31 13:54:02
0100D1801A0F4000,"Risk of Rain Returns",,playable,2025-06-28 04:24:04
010076D00E4BA000,"Risk of Rain 2",online-broken,playable,2024-03-04 17:01:05 010076D00E4BA000,"Risk of Rain 2",online-broken,playable,2024-03-04 17:01:05
0100E8300A67A000,"RISK® Global Domination",nvdec;online-broken,playable,2022-08-01 18:53:28 0100E8300A67A000,"RISK® Global Domination",nvdec;online-broken,playable,2022-08-01 18:53:28
010042500FABA000,"Ritual: Crown of Horns",,playable,2021-01-26 16:01:47 010042500FABA000,"Ritual: Crown of Horns",,playable,2021-01-26 16:01:47
@ -2755,7 +2746,6 @@
01005D701264A000,"SpyHack",,playable,2021-04-15 10:53:51 01005D701264A000,"SpyHack",,playable,2021-04-15 10:53:51
010077B00E046000,"Spyro™ Reignited Trilogy",nvdec;UE4,playable,2022-09-11 18:38:33 010077B00E046000,"Spyro™ Reignited Trilogy",nvdec;UE4,playable,2022-09-11 18:38:33
0100085012A0E000,"Squeakers",,playable,2020-12-13 12:13:05 0100085012A0E000,"Squeakers",,playable,2020-12-13 12:13:05
0100E1D01EB2E000,"Squeakross: Home Squeak Home",,playable,2025-06-16 02:02:00
010009300D31C000,"Squidgies Takeover",,playable,2020-07-20 22:28:08 010009300D31C000,"Squidgies Takeover",,playable,2020-07-20 22:28:08
0100FCD0102EC000,"Squidlit",,playable,2020-08-06 12:38:32 0100FCD0102EC000,"Squidlit",,playable,2020-08-06 12:38:32
0100EBF00E702000,"STAR OCEAN First Departure R",nvdec,playable,2021-07-05 19:29:16 0100EBF00E702000,"STAR OCEAN First Departure R",nvdec,playable,2021-07-05 19:29:16
@ -2775,7 +2765,7 @@
0100E6B0115FC000,"Star99",online,menus,2021-11-26 14:18:51 0100E6B0115FC000,"Star99",online,menus,2021-11-26 14:18:51
01002100137BA000,"Stardash",,playable,2021-01-21 16:31:19 01002100137BA000,"Stardash",,playable,2021-01-21 16:31:19
0100E65002BB8000,"Stardew Valley",online-broken;ldn-untested,playable,2024-02-14 03:11:19 0100E65002BB8000,"Stardew Valley",online-broken;ldn-untested,playable,2024-02-14 03:11:19
01002CC003FE6000,"Starlink: Battle for Atlas™ Digital Edition",,playable,2025-07-30 12:09:37 01002CC003FE6000,"Starlink: Battle for Atlas™ Digital Edition",services-horizon;crash;Needs Update,nothing,2024-05-05 17:25:11
010098E010FDA000,"Starlit Adventures Golden Stars",,playable,2020-11-21 12:14:43 010098E010FDA000,"Starlit Adventures Golden Stars",,playable,2020-11-21 12:14:43
01001BB00AC26000,"STARSHIP AVENGER Operation: Take Back Earth",,playable,2021-01-12 15:52:55 01001BB00AC26000,"STARSHIP AVENGER Operation: Take Back Earth",,playable,2021-01-12 15:52:55
010000700A572000,"State of Anarchy: Master of Mayhem",nvdec,playable,2021-01-12 19:00:05 010000700A572000,"State of Anarchy: Master of Mayhem",nvdec,playable,2021-01-12 19:00:05
@ -2983,7 +2973,6 @@
0100C2E0129A6000,"The Executioner",nvdec,playable,2021-01-23 00:31:28 0100C2E0129A6000,"The Executioner",nvdec,playable,2021-01-23 00:31:28
01006050114D4000,"The Experiment: Escape Room",gpu,ingame,2022-09-30 13:20:35 01006050114D4000,"The Experiment: Escape Room",gpu,ingame,2022-09-30 13:20:35
0100B5900DFB2000,"The Eyes of Ara",,playable,2022-09-16 14:44:06 0100B5900DFB2000,"The Eyes of Ara",,playable,2022-09-16 14:44:06
0100BA5013E52000,"The Falconeer: Warrior Edition",,playable,2025-07-30 12:04:50
01002DD00AF9E000,"The Fall",gpu,ingame,2020-05-31 23:31:16 01002DD00AF9E000,"The Fall",gpu,ingame,2020-05-31 23:31:16
01003E5002320000,"The Fall Part 2: Unbound",,playable,2021-11-06 02:18:08 01003E5002320000,"The Fall Part 2: Unbound",,playable,2021-11-06 02:18:08
0100CDC00789E000,"The Final Station",nvdec,playable,2022-08-22 15:54:39 0100CDC00789E000,"The Final Station",nvdec,playable,2022-08-22 15:54:39
@ -3027,7 +3016,6 @@
01009B101044C000,"The Legend of Heroes: Trails of Cold Steel III Demo",demo;nvdec,playable,2021-04-23 01:07:32 01009B101044C000,"The Legend of Heroes: Trails of Cold Steel III Demo",demo;nvdec,playable,2021-04-23 01:07:32
0100D3C010DE8000,"The Legend of Heroes: Trails of Cold Steel IV",nvdec,playable,2021-04-23 14:01:05 0100D3C010DE8000,"The Legend of Heroes: Trails of Cold Steel IV",nvdec,playable,2021-04-23 14:01:05
01005E5013862000,"THE LEGEND OF HEROES: ZERO NO KISEKI KAI [英雄傳說 零之軌跡:改]",crash,nothing,2021-09-30 14:41:07 01005E5013862000,"THE LEGEND OF HEROES: ZERO NO KISEKI KAI [英雄傳說 零之軌跡:改]",crash,nothing,2021-09-30 14:41:07
01009C901ACEE000,"The Legend of Nayuta: Boundless Trails",,ingame,2025-06-12 15:47
01008CF01BAAC000,"The Legend of Zelda Echoes of Wisdom",nvdec;ASTC;intel-vendor-bug,playable,2024-10-01 14:11:01 01008CF01BAAC000,"The Legend of Zelda Echoes of Wisdom",nvdec;ASTC;intel-vendor-bug,playable,2024-10-01 14:11:01
0100509005AF2000,"The Legend of Zelda: Breath of the Wild Demo",demo,ingame,2022-12-24 05:02:58 0100509005AF2000,"The Legend of Zelda: Breath of the Wild Demo",demo,ingame,2022-12-24 05:02:58
01007EF00011E000,"The Legend of Zelda™: Breath of the Wild",gpu;amd-vendor-bug;mac-bug,ingame,2024-09-23 19:35:46 01007EF00011E000,"The Legend of Zelda™: Breath of the Wild",gpu;amd-vendor-bug;mac-bug,ingame,2024-09-23 19:35:46
@ -3206,7 +3194,6 @@
010000400F582000,"TT Isle of Man Ride on the Edge 2",gpu;nvdec;online-broken,ingame,2022-09-30 22:13:05 010000400F582000,"TT Isle of Man Ride on the Edge 2",gpu;nvdec;online-broken,ingame,2022-09-30 22:13:05
0100752011628000,"TTV2",,playable,2020-11-27 13:21:36 0100752011628000,"TTV2",,playable,2020-11-27 13:21:36
0100AFE00452E000,"Tumblestone",,playable,2021-01-07 17:49:20 0100AFE00452E000,"Tumblestone",,playable,2021-01-07 17:49:20
0100D1A01D7BA000,"Turbo Overkill",,playable,2025-07-30 12:08:57
010085500D5F6000,"Turok",gpu,ingame,2021-06-04 13:16:24 010085500D5F6000,"Turok",gpu,ingame,2021-06-04 13:16:24
0100CDC00D8D6000,"Turok 2: Seeds of Evil",gpu;vulkan,ingame,2022-09-12 17:50:05 0100CDC00D8D6000,"Turok 2: Seeds of Evil",gpu;vulkan,ingame,2022-09-12 17:50:05
010004B0130C8000,"Turrican Flashback",audout,playable,2021-08-30 10:07:56 010004B0130C8000,"Turrican Flashback",audout,playable,2021-08-30 10:07:56
@ -3230,8 +3217,6 @@
0100592005164000,"UNBOX: Newbie's Adventure",UE4,playable,2022-08-29 13:12:56 0100592005164000,"UNBOX: Newbie's Adventure",UE4,playable,2022-08-29 13:12:56
01002D900C5E4000,"Uncanny Valley",nvdec,playable,2021-06-04 13:28:45 01002D900C5E4000,"Uncanny Valley",nvdec,playable,2021-06-04 13:28:45
010076F011F54000,"Undead & Beyond",nvdec,playable,2022-10-04 09:11:18 010076F011F54000,"Undead & Beyond",nvdec,playable,2022-10-04 09:11:18
01009B700D0B8000,"Undead Horde",,playable,2025-07-30 12:05:05
0100FC301A878000,"Undead Horde 2: Necropolis",,playable,2025-07-30 12:06:07
01008F3013E4E000,"Under Leaves",,playable,2021-05-22 18:13:58 01008F3013E4E000,"Under Leaves",,playable,2021-05-22 18:13:58
010080B00AD66000,"Undertale",,playable,2022-08-31 17:31:46 010080B00AD66000,"Undertale",,playable,2022-08-31 17:31:46
01008F80049C6000,"Unepic",,playable,2024-01-15 17:03:00 01008F80049C6000,"Unepic",,playable,2024-01-15 17:03:00

1 title_id game_name labels status last_updated
188 01003DD00BFEE000 Airheart - Tales of broken Wings playable 2021-02-26 15:20:27
189 01007F100DE52000 Akane nvdec playable 2022-07-21 00:12:18
190 01009A800F0C8000 Akash: Path of the Five gpu;nvdec ingame 2020-12-14 22:33:12
01009E8012976000 AKIBA'S TRIP: Hellbound & Debriefed playable 2025-07-30 23:22:47
0100D74019A0E000 AKIBA'S TRIP: Undead & Undressed Director's Cut playable 2025-07-31 13:58:42
191 010053100B0EA000 Akihabara - Feel the Rhythm Remixed playable 2021-02-22 14:39:35
192 0100D4C00EE0C000 Akuarium slow playable 2020-12-12 23:43:36
193 010026E00FEBE000 Akuto: Showdown playable 2020-08-04 19:43:27
1095 0100F9600E746000 ESP Ra.De. Psi audio;slow ingame 2024-03-07 15:05:08
1096 010073000FE18000 Esports powerful pro yakyuu 2020 gpu;crash;Needs More Attention ingame 2024-04-29 05:34:14
1097 01004F9012FD8000 Estranged: The Departure nvdec;UE4 playable 2022-10-24 10:37:58
010018f01e0a0000 Eternights playable 2025-07-30 12:10:24
1098 0100CB900B498000 Eternum Ex playable 2021-01-13 20:28:32
1099 010092501EB2C000 Europa (Demo) gpu;crash;UE4 ingame 2024-04-23 10:47:12
1100 01007BE0160D6000 EVE ghost enemies gpu ingame 2023-01-14 03:13:30
1240 010003F00BD48000 Friday the 13th: Killer Puzzle playable 2021-01-28 01:33:38
1241 010092A00C4B6000 Friday the 13th: The Game Ultimate Slasher Edition nvdec;online-broken;UE4 playable 2022-09-06 17:33:27
1242 0100F200178F4000 FRONT MISSION 1st: Remake playable 2023-06-09 07:44:24
0100c4e018a24000 FRONT MISSION 2: Remake playable 2025-07-30 12:11:23
01007E6019872000 FRONT MISSION 3: Remake playable 2025-07-30 12:12:02
1243 0100861012474000 Frontline Zed playable 2020-10-03 12:55:59
1244 0100B5300B49A000 Frost playable 2022-07-27 12:00:36
1245 010038A007AA4000 FruitFall Crush playable 2020-10-20 11:33:33
1518 010095C016C14000 Iridium playable 2022-08-05 23:19:53
1519 0100AD300B786000 Iris School of Wizardry -Vinculum Hearts- playable 2022-12-05 13:11:15
1520 0100945012168000 Iris.Fall nvdec playable 2022-10-18 13:40:22
010059801B736000 IronFall: Invasion playable 2025-07-30 11:42:30
1521 01005270118D6000 Iron Wings slow ingame 2022-08-07 08:32:57
1522 01004DB003E6A000 IRONCAST playable 2021-01-13 13:54:29
1523 0100E5700CD56000 Irony Curtain: From Matryoshka with Love playable 2021-06-04 20:12:37
2257 010086F0064CE000 Poi: Explorer Edition nvdec playable 2021-01-21 19:32:00
2258 0100EB6012FD2000 Poison Control playable 2021-05-16 14:01:54
2259 010072400E04A000 Pokémon Café ReMix playable 2021-08-17 20:00:04
010008c01e742000 Pokémon Friends crash;services menus 2025-07-24 13:32:00
2260 01003D200BAA2000 Pokémon Mystery Dungeon™: Rescue Team DX mac-bug playable 2024-01-21 00:16:32
2261 01008DB008C2C000 Pokémon Shield + Pokémon Shield Expansion Pass deadlock;crash;online-broken;ldn-works;LAN ingame 2024-08-12 07:20:22
2262 0100ABF008968000 Pokémon Sword + Pokémon Sword Expansion Pass deadlock;crash;online-broken;ldn-works;LAN ingame 2024-08-26 15:40:37
2305 010077B00BDD8000 Professional Farmer: Nintendo Switch™ Edition slow playable 2020-12-16 13:38:19
2306 010018300C83A000 Professor Lupo and his Horrible Pets playable 2020-06-12 00:08:45
2307 0100D1F0132F6000 Professor Lupo: Ocean playable 2021-04-14 16:33:33
0100c3a017834000 Prodeus playable 2025-07-30 12:07:52
2308 0100BBD00976C000 Project Highrise: Architect's Edition playable 2022-08-10 17:19:12
2309 0100ACE00DAB6000 Project Nimbus: Complete Edition nvdec;UE4;vulkan-backend-bug playable 2022-08-10 17:35:43
2310 01002980140F6000 Project TRIANGLE STRATEGY™ Debut Demo UE4;demo playable 2022-10-24 21:40:27
2436 0100E9C010EA8000 Rise of Insanity playable 2020-08-30 15:42:14
2437 01006BA00E652000 Rise: Race The Future playable 2021-02-27 13:29:06
2438 010020C012F48000 Rising Hell playable 2022-10-31 13:54:02
0100D1801A0F4000 Risk of Rain Returns playable 2025-06-28 04:24:04
2439 010076D00E4BA000 Risk of Rain 2 online-broken playable 2024-03-04 17:01:05
2440 0100E8300A67A000 RISK® Global Domination nvdec;online-broken playable 2022-08-01 18:53:28
2441 010042500FABA000 Ritual: Crown of Horns playable 2021-01-26 16:01:47
2746 01005D701264A000 SpyHack playable 2021-04-15 10:53:51
2747 010077B00E046000 Spyro™ Reignited Trilogy nvdec;UE4 playable 2022-09-11 18:38:33
2748 0100085012A0E000 Squeakers playable 2020-12-13 12:13:05
0100E1D01EB2E000 Squeakross: Home Squeak Home playable 2025-06-16 02:02:00
2749 010009300D31C000 Squidgies Takeover playable 2020-07-20 22:28:08
2750 0100FCD0102EC000 Squidlit playable 2020-08-06 12:38:32
2751 0100EBF00E702000 STAR OCEAN First Departure R nvdec playable 2021-07-05 19:29:16
2765 0100E6B0115FC000 Star99 online menus 2021-11-26 14:18:51
2766 01002100137BA000 Stardash playable 2021-01-21 16:31:19
2767 0100E65002BB8000 Stardew Valley online-broken;ldn-untested playable 2024-02-14 03:11:19
2768 01002CC003FE6000 Starlink: Battle for Atlas™ Digital Edition services-horizon;crash;Needs Update playable nothing 2025-07-30 12:09:37 2024-05-05 17:25:11
2769 010098E010FDA000 Starlit Adventures Golden Stars playable 2020-11-21 12:14:43
2770 01001BB00AC26000 STARSHIP AVENGER Operation: Take Back Earth playable 2021-01-12 15:52:55
2771 010000700A572000 State of Anarchy: Master of Mayhem nvdec playable 2021-01-12 19:00:05
2973 0100C2E0129A6000 The Executioner nvdec playable 2021-01-23 00:31:28
2974 01006050114D4000 The Experiment: Escape Room gpu ingame 2022-09-30 13:20:35
2975 0100B5900DFB2000 The Eyes of Ara playable 2022-09-16 14:44:06
0100BA5013E52000 The Falconeer: Warrior Edition playable 2025-07-30 12:04:50
2976 01002DD00AF9E000 The Fall gpu ingame 2020-05-31 23:31:16
2977 01003E5002320000 The Fall Part 2: Unbound playable 2021-11-06 02:18:08
2978 0100CDC00789E000 The Final Station nvdec playable 2022-08-22 15:54:39
3016 01009B101044C000 The Legend of Heroes: Trails of Cold Steel III Demo demo;nvdec playable 2021-04-23 01:07:32
3017 0100D3C010DE8000 The Legend of Heroes: Trails of Cold Steel IV nvdec playable 2021-04-23 14:01:05
3018 01005E5013862000 THE LEGEND OF HEROES: ZERO NO KISEKI KAI [英雄傳說 零之軌跡:改] crash nothing 2021-09-30 14:41:07
01009C901ACEE000 The Legend of Nayuta: Boundless Trails ingame 2025-06-12 15:47
3019 01008CF01BAAC000 The Legend of Zelda Echoes of Wisdom nvdec;ASTC;intel-vendor-bug playable 2024-10-01 14:11:01
3020 0100509005AF2000 The Legend of Zelda: Breath of the Wild Demo demo ingame 2022-12-24 05:02:58
3021 01007EF00011E000 The Legend of Zelda™: Breath of the Wild gpu;amd-vendor-bug;mac-bug ingame 2024-09-23 19:35:46
3194 010000400F582000 TT Isle of Man Ride on the Edge 2 gpu;nvdec;online-broken ingame 2022-09-30 22:13:05
3195 0100752011628000 TTV2 playable 2020-11-27 13:21:36
3196 0100AFE00452E000 Tumblestone playable 2021-01-07 17:49:20
0100D1A01D7BA000 Turbo Overkill playable 2025-07-30 12:08:57
3197 010085500D5F6000 Turok gpu ingame 2021-06-04 13:16:24
3198 0100CDC00D8D6000 Turok 2: Seeds of Evil gpu;vulkan ingame 2022-09-12 17:50:05
3199 010004B0130C8000 Turrican Flashback audout playable 2021-08-30 10:07:56
3217 0100592005164000 UNBOX: Newbie's Adventure UE4 playable 2022-08-29 13:12:56
3218 01002D900C5E4000 Uncanny Valley nvdec playable 2021-06-04 13:28:45
3219 010076F011F54000 Undead & Beyond nvdec playable 2022-10-04 09:11:18
01009B700D0B8000 Undead Horde playable 2025-07-30 12:05:05
0100FC301A878000 Undead Horde 2: Necropolis playable 2025-07-30 12:06:07
3220 01008F3013E4E000 Under Leaves playable 2021-05-22 18:13:58
3221 010080B00AD66000 Undertale playable 2022-08-31 17:31:46
3222 01008F80049C6000 Unepic playable 2024-01-15 17:03:00

View File

@ -5,21 +5,7 @@
<clear /> <clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<!-- Only needed when using pre-release versions of Ryujinx.LibHac. --> <!-- Only needed when using pre-release versions of Ryujinx.LibHac. -->
<add key="LibHacAlpha" value="https://git.ryujinx.app/api/v4/projects/17/packages/nuget/index.json" /> <!--<add key="LibHacAlpha" value="https://git.ryujinx.app/api/v4/projects/17/packages/nuget/index.json" />-->
<add key="Ryujinx.UpdateClient" value="https://git.ryujinx.app/api/v4/projects/71/packages/nuget/index.json" /> <add key="Ryujinx.UpdateClient" value="https://git.ryujinx.app/api/v4/projects/71/packages/nuget/index.json" />
</packageSources> </packageSources>
<packageSourceMapping>
<!-- key value for <packageSource> should match key values from <packageSources> element -->
<!-- These are defined and .NET still yells about multiple package sources with no mappings. Not sure what to do, this is in the docs lol -->
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="Ryujinx.UpdateClient">
<package pattern="Ryujinx.UpdateClient" />
<package pattern="Ryujinx.Systems.Update.Common" />
</packageSource>
<packageSource key="LibHacAlpha">
<package pattern="Ryujinx.LibHac" />
</packageSource>
</packageSourceMapping>
</configuration> </configuration>

View File

@ -3,7 +3,6 @@ using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using ExecutionContext = ARMeilleure.State.ExecutionContext;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
@ -201,11 +200,7 @@ namespace ARMeilleure.Instructions
ExecutionContext context = GetContext(); ExecutionContext context = GetContext();
// If debugging, we'll handle interrupts outside context.CheckInterrupt();
if (!Optimizations.EnableDebugging)
{
context.CheckInterrupt();
}
Statistics.ResumeTimer(); Statistics.ResumeTimer();

View File

@ -12,7 +12,6 @@ namespace ARMeilleure
public static bool AllowLcqInFunctionTable { get; set; } = true; public static bool AllowLcqInFunctionTable { get; set; } = true;
public static bool UseUnmanagedDispatchLoop { get; set; } = true; public static bool UseUnmanagedDispatchLoop { get; set; } = true;
public static bool EnableDebugging { get; set; } = false;
public static bool UseAdvSimdIfAvailable { get; set; } = true; public static bool UseAdvSimdIfAvailable { get; set; } = true;
public static bool UseArm64AesIfAvailable { get; set; } = true; public static bool UseArm64AesIfAvailable { get; set; } = true;

View File

@ -1,5 +1,4 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using System.Threading;
namespace ARMeilleure.State namespace ARMeilleure.State
{ {
@ -11,7 +10,7 @@ namespace ARMeilleure.State
internal nint NativeContextPtr => _nativeContext.BasePtr; internal nint NativeContextPtr => _nativeContext.BasePtr;
internal bool Interrupted { get; private set; } private bool _interrupted;
private readonly ICounter _counter; private readonly ICounter _counter;
@ -66,8 +65,6 @@ namespace ARMeilleure.State
public bool IsAarch32 { get; set; } public bool IsAarch32 { get; set; }
public ulong ThreadUid { get; set; }
internal ExecutionMode ExecutionMode internal ExecutionMode ExecutionMode
{ {
get get
@ -93,19 +90,14 @@ namespace ARMeilleure.State
private readonly ExceptionCallbackNoArgs _interruptCallback; private readonly ExceptionCallbackNoArgs _interruptCallback;
private readonly ExceptionCallback _breakCallback; private readonly ExceptionCallback _breakCallback;
private readonly ExceptionCallbackNoArgs _stepCallback;
private readonly ExceptionCallback _supervisorCallback; private readonly ExceptionCallback _supervisorCallback;
private readonly ExceptionCallback _undefinedCallback; private readonly ExceptionCallback _undefinedCallback;
internal int ShouldStep;
public ulong DebugPc { get; set; }
public ExecutionContext( public ExecutionContext(
IJitMemoryAllocator allocator, IJitMemoryAllocator allocator,
ICounter counter, ICounter counter,
ExceptionCallbackNoArgs interruptCallback = null, ExceptionCallbackNoArgs interruptCallback = null,
ExceptionCallback breakCallback = null, ExceptionCallback breakCallback = null,
ExceptionCallbackNoArgs stepCallback = null,
ExceptionCallback supervisorCallback = null, ExceptionCallback supervisorCallback = null,
ExceptionCallback undefinedCallback = null) ExceptionCallback undefinedCallback = null)
{ {
@ -113,7 +105,6 @@ namespace ARMeilleure.State
_counter = counter; _counter = counter;
_interruptCallback = interruptCallback; _interruptCallback = interruptCallback;
_breakCallback = breakCallback; _breakCallback = breakCallback;
_stepCallback = stepCallback;
_supervisorCallback = supervisorCallback; _supervisorCallback = supervisorCallback;
_undefinedCallback = undefinedCallback; _undefinedCallback = undefinedCallback;
@ -136,9 +127,9 @@ namespace ARMeilleure.State
internal void CheckInterrupt() internal void CheckInterrupt()
{ {
if (Interrupted) if (_interrupted)
{ {
Interrupted = false; _interrupted = false;
_interruptCallback?.Invoke(this); _interruptCallback?.Invoke(this);
} }
@ -148,37 +139,16 @@ namespace ARMeilleure.State
public void RequestInterrupt() public void RequestInterrupt()
{ {
Interrupted = true; _interrupted = true;
}
public void StepHandler()
{
_stepCallback?.Invoke(this);
}
public void RequestDebugStep()
{
Interlocked.Exchange(ref ShouldStep, 1);
RequestInterrupt();
} }
internal void OnBreak(ulong address, int imm) internal void OnBreak(ulong address, int imm)
{ {
if (Optimizations.EnableDebugging)
{
DebugPc = Pc;
}
_breakCallback?.Invoke(this, address, imm); _breakCallback?.Invoke(this, address, imm);
} }
internal void OnSupervisorCall(ulong address, int imm) internal void OnSupervisorCall(ulong address, int imm)
{ {
if (Optimizations.EnableDebugging)
{
DebugPc = Pc;
}
_supervisorCallback?.Invoke(this, address, imm); _supervisorCallback?.Invoke(this, address, imm);
} }

View File

@ -22,12 +22,6 @@ namespace ARMeilleure.State
public ulong ExclusiveValueHigh; public ulong ExclusiveValueHigh;
public int Running; public int Running;
public long Tpidr2El0; public long Tpidr2El0;
/// <summary>
/// Precise PC value used for debugging.
/// This will only be set when Optimizations.EnableDebugging is true.
/// </summary>
public ulong DebugPrecisePc;
} }
private static NativeCtxStorage _dummyStorage = new(); private static NativeCtxStorage _dummyStorage = new();
@ -45,11 +39,6 @@ namespace ARMeilleure.State
public ulong GetPc() public ulong GetPc()
{ {
if (Optimizations.EnableDebugging)
{
return GetStorage().DebugPrecisePc;
}
// TODO: More precise tracking of PC value. // TODO: More precise tracking of PC value.
return GetStorage().DispatchAddress; return GetStorage().DispatchAddress;
} }
@ -279,11 +268,6 @@ namespace ARMeilleure.State
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running); return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running);
} }
public static int GetDebugPrecisePcOffset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.DebugPrecisePc);
}
private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target) private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
{ {
return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target); return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);

View File

@ -33,7 +33,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 7009; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 7008; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";
@ -303,13 +303,6 @@ namespace ARMeilleure.Translation.PTC
return false; return false;
} }
if (outerHeader.DebuggerMode != Optimizations.EnableDebugging)
{
InvalidateCompressedStream(compressedStream);
return false;
}
nint intPtr = nint.Zero; nint intPtr = nint.Zero;
try try
@ -486,7 +479,6 @@ namespace ARMeilleure.Translation.PTC
MemoryManagerMode = GetMemoryManagerMode(), MemoryManagerMode = GetMemoryManagerMode(),
OSPlatform = GetOSPlatform(), OSPlatform = GetOSPlatform(),
Architecture = (uint)RuntimeInformation.ProcessArchitecture, Architecture = (uint)RuntimeInformation.ProcessArchitecture,
DebuggerMode = Optimizations.EnableDebugging,
UncompressedStreamSize = UncompressedStreamSize =
(long)Unsafe.SizeOf<InnerHeader>() + (long)Unsafe.SizeOf<InnerHeader>() +
@ -1076,7 +1068,7 @@ namespace ARMeilleure.Translation.PTC
return osPlatform; return osPlatform;
} }
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 87*/)] [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 86*/)]
private struct OuterHeader private struct OuterHeader
{ {
public ulong Magic; public ulong Magic;
@ -1088,7 +1080,6 @@ namespace ARMeilleure.Translation.PTC
public byte MemoryManagerMode; public byte MemoryManagerMode;
public uint OSPlatform; public uint OSPlatform;
public uint Architecture; public uint Architecture;
public bool DebuggerMode;
public long UncompressedStreamSize; public long UncompressedStreamSize;

View File

@ -119,25 +119,7 @@ namespace ARMeilleure.Translation
NativeInterface.RegisterThread(context, Memory, this); NativeInterface.RegisterThread(context, Memory, this);
if (Optimizations.EnableDebugging) if (Optimizations.UseUnmanagedDispatchLoop)
{
context.DebugPc = address;
do
{
if (Interlocked.CompareExchange(ref context.ShouldStep, 0, 1) == 1)
{
context.DebugPc = Step(context, context.DebugPc);
context.StepHandler();
}
else
{
context.DebugPc = ExecuteSingle(context, context.DebugPc);
}
context.CheckInterrupt();
}
while (context.Running && context.DebugPc != 0);
}
else if (Optimizations.UseUnmanagedDispatchLoop)
{ {
Stubs.DispatchLoop(context.NativeContextPtr, address); Stubs.DispatchLoop(context.NativeContextPtr, address);
} }
@ -193,24 +175,8 @@ namespace ARMeilleure.Translation
return nextAddr; return nextAddr;
} }
private ulong Step(State.ExecutionContext context, ulong address) public ulong Step(State.ExecutionContext context, ulong address)
{ {
try
{
OpCode opCode = Decoder.DecodeOpCode(Memory, address, context.ExecutionMode);
// For branch instructions during single-stepping, we handle them manually
// func.Execute() will sometimes execute the entire function call, which is not what we want
if (opCode.Instruction.Name is InstName.Bl or InstName.Blr or InstName.Blx or InstName.Br)
{
return ExecuteBranchInstructionForStepping(context, address, opCode);
}
}
catch
{
// ignore
}
TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true); TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true);
address = func.Execute(Stubs.ContextWrapper, context); address = func.Execute(Stubs.ContextWrapper, context);
@ -220,94 +186,6 @@ namespace ARMeilleure.Translation
return address; return address;
} }
private static ulong ExecuteBranchInstructionForStepping(State.ExecutionContext context, ulong address, OpCode opCode)
{
switch (opCode.Instruction.Name)
{
case InstName.Bl:
if (opCode is IOpCodeBImm opBImm)
{
// Set link register
if (context.ExecutionMode == ExecutionMode.Aarch64)
{
context.SetX(30, address + (ulong)opCode.OpCodeSizeInBytes); // LR = X30
}
else
{
// For ARM32, need to set the appropriate return address
uint returnAddr = opCode is OpCode32 op32 && op32.IsThumb
? (uint)address + (uint)opCode.OpCodeSizeInBytes | 1u // Thumb bit set
: (uint)address + (uint)opCode.OpCodeSizeInBytes;
context.SetX(14, returnAddr); // LR = R14
}
return (ulong)opBImm.Immediate;
}
break;
case InstName.Blr:
if (opCode is OpCodeBReg opBReg)
{
// Set link register
if (context.ExecutionMode == ExecutionMode.Aarch64)
{
context.SetX(30, address + (ulong)opCode.OpCodeSizeInBytes); // LR = X30
}
else
{
uint returnAddr = opCode is OpCode32 op32 && op32.IsThumb
? (uint)address + (uint)opCode.OpCodeSizeInBytes | 1u // Thumb bit set
: (uint)address + (uint)opCode.OpCodeSizeInBytes;
context.SetX(14, returnAddr); // LR = R14
}
return context.GetX(opBReg.Rn);
}
break;
case InstName.Blx:
if (opCode is IOpCodeBImm opBlxImm)
{
// Handle mode switching for BLX
if (opCode is OpCode32 op32)
{
uint returnAddr = op32.IsThumb
? (uint)address + (uint)opCode.OpCodeSizeInBytes | 1u
: (uint)address + (uint)opCode.OpCodeSizeInBytes;
context.SetX(14, returnAddr);
// BLX switches between ARM and Thumb modes
context.SetPstateFlag(PState.TFlag, !op32.IsThumb);
}
return (ulong)opBlxImm.Immediate;
}
else if (opCode is IOpCode32BReg opBlxReg)
{
if (opCode is OpCode32 op32)
{
uint returnAddr = op32.IsThumb
? (uint)address + (uint)opCode.OpCodeSizeInBytes | 1u
: (uint)address + (uint)opCode.OpCodeSizeInBytes;
context.SetX(14, returnAddr);
// For BLX register, the target address determines the mode
ulong targetAddr = context.GetX(opBlxReg.Rm);
context.SetPstateFlag(PState.TFlag, (targetAddr & 1) != 0);
return targetAddr & ~1UL; // Clear the Thumb bit for the actual address
}
}
break;
case InstName.Br:
if (opCode is OpCodeBReg opBr)
{
// BR doesn't set link register, just branches to the target
return context.GetX(opBr.Rn);
}
break;
}
throw new InvalidOperationException($"Unhandled branch instruction: {opCode.Instruction.Name}");
}
internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode) internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
{ {
if (!Functions.TryGetValue(address, out TranslatedFunction func)) if (!Functions.TryGetValue(address, out TranslatedFunction func))
@ -489,13 +367,9 @@ namespace ARMeilleure.Translation
if (block.Exit) if (block.Exit)
{ {
// Return to managed rather than tail call. // Left option here as it may be useful if we need to return to managed rather than tail call in
bool useReturns = Optimizations.EnableDebugging; // future. (eg. for debug)
bool useReturns = false;
if (Optimizations.EnableDebugging)
{
EmitDebugPrecisePcUpdate(context, block.Address);
}
InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns); InstEmitFlowHelper.EmitVirtualJump(context, Const(block.Address), isReturn: useReturns);
} }
@ -519,11 +393,6 @@ namespace ARMeilleure.Translation
} }
} }
if (Optimizations.EnableDebugging)
{
EmitDebugPrecisePcUpdate(context, opCode.Address);
}
Operand lblPredicateSkip = default; Operand lblPredicateSkip = default;
if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al) if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al)
@ -620,14 +489,6 @@ namespace ARMeilleure.Translation
context.MarkLabel(lblExit); context.MarkLabel(lblExit);
} }
internal static void EmitDebugPrecisePcUpdate(EmitterContext context, ulong address)
{
long debugPrecisePcOffs = NativeContext.GetDebugPrecisePcOffset();
Operand debugPrecisePcAddr = context.Add(context.LoadArgument(OperandType.I64, 0), Const(debugPrecisePcOffs));
context.Store(debugPrecisePcAddr, Const(address));
}
public void InvalidateJitCacheRegion(ulong address, ulong size) public void InvalidateJitCacheRegion(ulong address, ulong size)
{ {
ulong[] overlapAddresses = []; ulong[] overlapAddresses = [];

View File

@ -33,7 +33,7 @@ namespace Ryujinx.BuildValidationTasks
LocalesJson json; LocalesJson json;
if (isGitRunner && data.Contains("\r\n")) if (isGitRunner && data.Contains("\r\n"))
throw new FormatException("locales.json is using CRLF line endings! It should be using LF line endings, rebuild locally to fix..."); throw new FormatException("locales.json is using CRLF line endings! It should be using LF line endings, build locally to fix...");
try try
{ {
@ -86,7 +86,7 @@ namespace Ryujinx.BuildValidationTasks
} }
if (isGitRunner && encounteredIssue) if (isGitRunner && encounteredIssue)
throw new JsonException("1 or more locales are invalid! Rebuild locally to fix..."); throw new JsonException("1 or more locales are invalid!");
string jsonString = JsonSerializer.Serialize(json, _jsonOptions); string jsonString = JsonSerializer.Serialize(json, _jsonOptions);
@ -102,7 +102,6 @@ namespace Ryujinx.BuildValidationTasks
struct LocalesJson struct LocalesJson
{ {
public Dictionary<string, string> Info { get; set; }
public List<string> Languages { get; set; } public List<string> Languages { get; set; }
public List<LocalesEntry> Locales { get; set; } public List<LocalesEntry> Locales { get; set; }
} }

View File

@ -11,17 +11,7 @@
Command="dotnet Ryujinx.BuildValidationTasks.dll &quot;$(ProjectDir)..\..\\&quot;" Command="dotnet Ryujinx.BuildValidationTasks.dll &quot;$(ProjectDir)..\..\\&quot;"
ConsoleToMsBuild="true" ConsoleToMsBuild="true"
Condition="'$(RuntimeIdentifier)' == ''" Condition="'$(RuntimeIdentifier)' == ''"
IgnoreExitCode="true"> />
<Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
<Output TaskParameter="ExitCode" PropertyName="BuildExitCode"/>
</Exec>
<PropertyGroup Condition=" '$(OutputOfExec.IndexOf(Unhandled exception))' != '-1'">
<ErrorOutput>$(OutputOfExec.Substring($(OutputOfExec.IndexOf("Unhandled exception"))))</ErrorOutput>
<ErrorOutput>$(ErrorOutput.Substring(0, $(ErrorOutput.IndexOf(';'))))</ErrorOutput>
</PropertyGroup>
<Error Text="$(ErrorOutput)" Condition=" '$(BuildExitCode)' != '0'"/>
</Target> </Target>
</Project> </Project>

View File

@ -13,7 +13,6 @@ namespace Ryujinx.Common.Logging
Cpu, Cpu,
Emulation, Emulation,
FFmpeg, FFmpeg,
GdbStub,
Font, Font,
Gpu, Gpu,
Hid, Hid,

View File

@ -93,7 +93,6 @@ namespace Ryujinx.Common
//The Pokémon Franchise //The Pokémon Franchise
"0100f4300bf2c000", // New Pokémon Snap "0100f4300bf2c000", // New Pokémon Snap
"0100000011d90000", // Pokémon Brilliant Diamond "0100000011d90000", // Pokémon Brilliant Diamond
"010008c01e742000", // Pokémon Friends
"01001f5010dfa000", // Pokémon Legends: Arceus "01001f5010dfa000", // Pokémon Legends: Arceus
"01003d200baa2000", // Pokémon Mystery Dungeon - Rescue Team DX "01003d200baa2000", // Pokémon Mystery Dungeon - Rescue Team DX
"0100a3d008c5c000", // Pokémon Scarlet "0100a3d008c5c000", // Pokémon Scarlet
@ -196,7 +195,6 @@ namespace Ryujinx.Common
"01008d100d43e000", // Saints Row IV "01008d100d43e000", // Saints Row IV
"0100de600beee000", // Saints Row: The Third - The Full Package "0100de600beee000", // Saints Row: The Third - The Full Package
"01001180021fa000", // Shovel Knight: Specter of Torment "01001180021fa000", // Shovel Knight: Specter of Torment
"0100e1D01eb2e000", // Squeakross: Home Squeak Home
"0100e65002bb8000", // Stardew Valley "0100e65002bb8000", // Stardew Valley
"0100d7a01b7a2000", // Star Wars: Bounty Hunter "0100d7a01b7a2000", // Star Wars: Bounty Hunter
"0100800015926000", // Suika Game "0100800015926000", // Suika Game

View File

@ -1,10 +0,0 @@
namespace Ryujinx.Cpu.AppleHv.Arm
{
enum ExceptionLevel : uint
{
PstateMask = 0xfffffff0,
EL1h = 0b0101,
El1t = 0b0100,
EL0 = 0b0000,
}
}

View File

@ -11,18 +11,7 @@ namespace Ryujinx.Cpu.AppleHv
class HvExecutionContext : IExecutionContext class HvExecutionContext : IExecutionContext
{ {
/// <inheritdoc/> /// <inheritdoc/>
public ulong Pc public ulong Pc => _impl.ElrEl1;
{
get
{
uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
if (currentEl == (uint)ExceptionLevel.EL1h)
{
return _impl.ElrEl1;
}
return _impl.Pc;
}
}
/// <inheritdoc/> /// <inheritdoc/>
public long TpidrEl0 public long TpidrEl0
@ -59,9 +48,6 @@ namespace Ryujinx.Cpu.AppleHv
set => _impl.Fpsr = value; set => _impl.Fpsr = value;
} }
/// <inheritdoc/>
public ulong ThreadUid { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public bool IsAarch32 public bool IsAarch32
{ {
@ -81,7 +67,6 @@ namespace Ryujinx.Cpu.AppleHv
private readonly ICounter _counter; private readonly ICounter _counter;
private readonly IHvExecutionContext _shadowContext; private readonly IHvExecutionContext _shadowContext;
private IHvExecutionContext _impl; private IHvExecutionContext _impl;
private int _shouldStep;
private readonly ExceptionCallbacks _exceptionCallbacks; private readonly ExceptionCallbacks _exceptionCallbacks;
@ -118,11 +103,6 @@ namespace Ryujinx.Cpu.AppleHv
_exceptionCallbacks.BreakCallback?.Invoke(this, address, imm); _exceptionCallbacks.BreakCallback?.Invoke(this, address, imm);
} }
private void StepHandler()
{
_exceptionCallbacks.StepCallback?.Invoke(this);
}
private void SupervisorCallHandler(ulong address, int imm) private void SupervisorCallHandler(ulong address, int imm)
{ {
_exceptionCallbacks.SupervisorCallback?.Invoke(this, address, imm); _exceptionCallbacks.SupervisorCallback?.Invoke(this, address, imm);
@ -147,30 +127,6 @@ namespace Ryujinx.Cpu.AppleHv
return Interlocked.Exchange(ref _interruptRequested, 0) != 0; return Interlocked.Exchange(ref _interruptRequested, 0) != 0;
} }
/// <inheritdoc/>
public void RequestDebugStep()
{
Interlocked.Exchange(ref _shouldStep, 1);
}
/// <inheritdoc/>
public ulong DebugPc
{
get => Pc;
set
{
uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
if (currentEl == (uint)ExceptionLevel.EL1h)
{
_impl.ElrEl1 = value;
}
else
{
_impl.Pc = value;
}
}
}
/// <inheritdoc/> /// <inheritdoc/>
public void StopRunning() public void StopRunning()
{ {
@ -186,22 +142,6 @@ namespace Ryujinx.Cpu.AppleHv
while (Running) while (Running)
{ {
if (Interlocked.CompareExchange(ref _shouldStep, 0, 1) == 1)
{
uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
if (currentEl == (uint)ExceptionLevel.EL1h)
{
HvApi.hv_vcpu_get_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, out ulong spsr).ThrowOnError();
spsr |= (1 << 21);
HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, spsr);
}
else
{
Pstate |= (1 << 21);
}
HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.MDSCR_EL1, 1);
}
HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError(); HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError();
HvExitReason reason = vcpu.ExitInfo->Reason; HvExitReason reason = vcpu.ExitInfo->Reason;
@ -269,20 +209,6 @@ namespace Ryujinx.Cpu.AppleHv
SupervisorCallHandler(elr - 4UL, id); SupervisorCallHandler(elr - 4UL, id);
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu); vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
break; break;
case ExceptionClass.SoftwareStepLowerEl:
HvApi.hv_vcpu_get_sys_reg(vcpuHandle, HvSysReg.SPSR_EL1, out ulong spsr).ThrowOnError();
spsr &= ~((ulong)(1 << 21));
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.SPSR_EL1, spsr).ThrowOnError();
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.MDSCR_EL1, 0);
ReturnToPool(vcpu);
StepHandler();
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
break;
case ExceptionClass.BrkAarch64:
ReturnToPool(vcpu);
BreakHandler(elr, (ushort)esr);
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
break;
default: default:
throw new Exception($"Unhandled guest exception {ec}."); throw new Exception($"Unhandled guest exception {ec}.");
} }
@ -293,7 +219,10 @@ namespace Ryujinx.Cpu.AppleHv
// TODO: Invalidate only the range that was modified? // TODO: Invalidate only the range that was modified?
return HvAddressSpace.KernelRegionTlbiEretAddress; return HvAddressSpace.KernelRegionTlbiEretAddress;
} }
return HvAddressSpace.KernelRegionEretAddress; else
{
return HvAddressSpace.KernelRegionEretAddress;
}
} }
private static void DataAbort(MemoryTracking tracking, ulong vcpu, uint esr) private static void DataAbort(MemoryTracking tracking, ulong vcpu, uint esr)

View File

@ -18,8 +18,6 @@ namespace Ryujinx.Cpu.AppleHv
public bool IsAarch32 { get; set; } public bool IsAarch32 { get; set; }
public ulong ThreadUid { get; set; }
private readonly ulong[] _x; private readonly ulong[] _x;
private readonly V128[] _v; private readonly V128[] _v;
@ -48,14 +46,5 @@ namespace Ryujinx.Cpu.AppleHv
{ {
_v[index] = value; _v[index] = value;
} }
public void RequestInterrupt()
{
}
public bool GetAndClearInterruptRequested()
{
return false;
}
} }
} }

View File

@ -2,7 +2,6 @@ using ARMeilleure.State;
using Ryujinx.Memory; using Ryujinx.Memory;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading;
namespace Ryujinx.Cpu.AppleHv namespace Ryujinx.Cpu.AppleHv
{ {
@ -14,8 +13,6 @@ namespace Ryujinx.Cpu.AppleHv
private static readonly SetSimdFpReg _setSimdFpReg; private static readonly SetSimdFpReg _setSimdFpReg;
private static readonly nint _setSimdFpRegNativePtr; private static readonly nint _setSimdFpRegNativePtr;
public ulong ThreadUid { get; set; }
static HvExecutionContextVcpu() static HvExecutionContextVcpu()
{ {
// .NET does not support passing vectors by value, so we need to pass a pointer and use a native // .NET does not support passing vectors by value, so we need to pass a pointer and use a native
@ -138,7 +135,6 @@ namespace Ryujinx.Cpu.AppleHv
} }
private readonly ulong _vcpu; private readonly ulong _vcpu;
private int _interruptRequested;
public HvExecutionContextVcpu(ulong vcpu) public HvExecutionContextVcpu(ulong vcpu)
{ {
@ -184,16 +180,8 @@ namespace Ryujinx.Cpu.AppleHv
public void RequestInterrupt() public void RequestInterrupt()
{ {
if (Interlocked.Exchange(ref _interruptRequested, 1) == 0) ulong vcpu = _vcpu;
{ HvApi.hv_vcpus_exit(ref vcpu, 1);
ulong vcpu = _vcpu;
HvApi.hv_vcpus_exit(ref vcpu, 1);
}
}
public bool GetAndClearInterruptRequested()
{
return Interlocked.Exchange(ref _interruptRequested, 0) != 0;
} }
} }
} }

View File

@ -15,7 +15,6 @@ namespace Ryujinx.Cpu.AppleHv
uint Fpcr { get; set; } uint Fpcr { get; set; }
uint Fpsr { get; set; } uint Fpsr { get; set; }
ulong ThreadUid { get; set; }
ulong GetX(int index); ulong GetX(int index);
void SetX(int index, ulong value); void SetX(int index, ulong value);
@ -40,8 +39,5 @@ namespace Ryujinx.Cpu.AppleHv
SetV(i, context.GetV(i)); SetV(i, context.GetV(i));
} }
} }
void RequestInterrupt();
bool GetAndClearInterruptRequested();
} }
} }

View File

@ -29,11 +29,6 @@ namespace Ryujinx.Cpu
/// </summary> /// </summary>
public readonly ExceptionCallback BreakCallback; public readonly ExceptionCallback BreakCallback;
/// <summary>
/// Handler for CPU software interrupts caused by single-stepping.
/// </summary>
public readonly ExceptionCallbackNoArgs StepCallback;
/// <summary> /// <summary>
/// Handler for CPU software interrupts caused by the Arm SVC instruction. /// Handler for CPU software interrupts caused by the Arm SVC instruction.
/// </summary> /// </summary>
@ -52,19 +47,16 @@ namespace Ryujinx.Cpu
/// </remarks> /// </remarks>
/// <param name="interruptCallback">Handler for CPU interrupts triggered using <see cref="IExecutionContext.RequestInterrupt"/></param> /// <param name="interruptCallback">Handler for CPU interrupts triggered using <see cref="IExecutionContext.RequestInterrupt"/></param>
/// <param name="breakCallback">Handler for CPU software interrupts caused by the Arm BRK instruction</param> /// <param name="breakCallback">Handler for CPU software interrupts caused by the Arm BRK instruction</param>
/// <param name="stepCallback">Handler for CPU software interrupts caused by single-stepping</param>
/// <param name="supervisorCallback">Handler for CPU software interrupts caused by the Arm SVC instruction</param> /// <param name="supervisorCallback">Handler for CPU software interrupts caused by the Arm SVC instruction</param>
/// <param name="undefinedCallback">Handler for CPU software interrupts caused by any undefined Arm instruction</param> /// <param name="undefinedCallback">Handler for CPU software interrupts caused by any undefined Arm instruction</param>
public ExceptionCallbacks( public ExceptionCallbacks(
ExceptionCallbackNoArgs interruptCallback = null, ExceptionCallbackNoArgs interruptCallback = null,
ExceptionCallback breakCallback = null, ExceptionCallback breakCallback = null,
ExceptionCallbackNoArgs stepCallback = null,
ExceptionCallback supervisorCallback = null, ExceptionCallback supervisorCallback = null,
ExceptionCallback undefinedCallback = null) ExceptionCallback undefinedCallback = null)
{ {
InterruptCallback = interruptCallback; InterruptCallback = interruptCallback;
BreakCallback = breakCallback; BreakCallback = breakCallback;
StepCallback = stepCallback;
SupervisorCallback = supervisorCallback; SupervisorCallback = supervisorCallback;
UndefinedCallback = undefinedCallback; UndefinedCallback = undefinedCallback;
} }

View File

@ -1,6 +1,5 @@
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Threading;
namespace Ryujinx.Cpu namespace Ryujinx.Cpu
{ {
@ -47,11 +46,6 @@ namespace Ryujinx.Cpu
/// </summary> /// </summary>
bool IsAarch32 { get; set; } bool IsAarch32 { get; set; }
/// <summary>
/// Thread UID.
/// </summary>
public ulong ThreadUid { get; set; }
/// <summary> /// <summary>
/// Indicates whenever the CPU is still running code. /// Indicates whenever the CPU is still running code.
/// </summary> /// </summary>
@ -114,23 +108,5 @@ namespace Ryujinx.Cpu
/// If you only need to pause the thread temporarily, use <see cref="RequestInterrupt"/> instead. /// If you only need to pause the thread temporarily, use <see cref="RequestInterrupt"/> instead.
/// </remarks> /// </remarks>
void StopRunning(); void StopRunning();
/// <summary>
/// Requests the thread to stop running temporarily and call <see cref="ExceptionCallbacks.InterruptCallback"/>.
/// </summary>
/// <remarks>
/// The thread might not pause immediately.
/// One must not assume that guest code is no longer being executed by the thread after calling this function.
/// After single stepping, the thread should call call <see cref="ExceptionCallbacks.StepCallback"/>.
/// </remarks>
void RequestDebugStep();
/// <summary>
/// Current Program Counter (for debugging).
/// </summary>
/// <remarks>
/// PC register for the debugger. Must not be accessed while the thread isn't stopped for debugging.
/// </remarks>
ulong DebugPc { get; set; }
} }
} }

View File

@ -1,6 +1,5 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using ExecutionContext = ARMeilleure.State.ExecutionContext;
namespace Ryujinx.Cpu.Jit namespace Ryujinx.Cpu.Jit
{ {
@ -54,13 +53,6 @@ namespace Ryujinx.Cpu.Jit
set => _impl.IsAarch32 = value; set => _impl.IsAarch32 = value;
} }
/// <inheritdoc/>
public ulong ThreadUid
{
get => _impl.ThreadUid;
set => _impl.ThreadUid = value;
}
/// <inheritdoc/> /// <inheritdoc/>
public bool Running => _impl.Running; public bool Running => _impl.Running;
@ -73,7 +65,6 @@ namespace Ryujinx.Cpu.Jit
counter, counter,
InterruptHandler, InterruptHandler,
BreakHandler, BreakHandler,
StepHandler,
SupervisorCallHandler, SupervisorCallHandler,
UndefinedHandler); UndefinedHandler);
@ -102,11 +93,6 @@ namespace Ryujinx.Cpu.Jit
_exceptionCallbacks.BreakCallback?.Invoke(this, address, imm); _exceptionCallbacks.BreakCallback?.Invoke(this, address, imm);
} }
private void StepHandler(ExecutionContext context)
{
_exceptionCallbacks.StepCallback?.Invoke(this);
}
private void SupervisorCallHandler(ExecutionContext context, ulong address, int imm) private void SupervisorCallHandler(ExecutionContext context, ulong address, int imm)
{ {
_exceptionCallbacks.SupervisorCallback?.Invoke(this, address, imm); _exceptionCallbacks.SupervisorCallback?.Invoke(this, address, imm);
@ -123,16 +109,6 @@ namespace Ryujinx.Cpu.Jit
_impl.RequestInterrupt(); _impl.RequestInterrupt();
} }
/// <inheritdoc/>
public void RequestDebugStep() => _impl.RequestDebugStep();
/// <inheritdoc/>
public ulong DebugPc
{
get => _impl.DebugPc;
set => _impl.DebugPc = value;
}
/// <inheritdoc/> /// <inheritdoc/>
public void StopRunning() public void StopRunning()
{ {

View File

@ -1,8 +1,6 @@
using ARMeilleure;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Threading;
namespace Ryujinx.Cpu.LightningJit.State namespace Ryujinx.Cpu.LightningJit.State
{ {
@ -54,8 +52,6 @@ namespace Ryujinx.Cpu.LightningJit.State
public bool IsAarch32 { get; set; } public bool IsAarch32 { get; set; }
public ulong ThreadUid { get; set; }
internal ExecutionMode ExecutionMode internal ExecutionMode ExecutionMode
{ {
get get
@ -81,20 +77,15 @@ namespace Ryujinx.Cpu.LightningJit.State
private readonly ExceptionCallbackNoArgs _interruptCallback; private readonly ExceptionCallbackNoArgs _interruptCallback;
private readonly ExceptionCallback _breakCallback; private readonly ExceptionCallback _breakCallback;
private readonly ExceptionCallbackNoArgs _stepCallback;
private readonly ExceptionCallback _supervisorCallback; private readonly ExceptionCallback _supervisorCallback;
private readonly ExceptionCallback _undefinedCallback; private readonly ExceptionCallback _undefinedCallback;
internal int ShouldStep;
public ulong DebugPc { get; set; }
public ExecutionContext(IJitMemoryAllocator allocator, ICounter counter, ExceptionCallbacks exceptionCallbacks) public ExecutionContext(IJitMemoryAllocator allocator, ICounter counter, ExceptionCallbacks exceptionCallbacks)
{ {
_nativeContext = new NativeContext(allocator); _nativeContext = new NativeContext(allocator);
_counter = counter; _counter = counter;
_interruptCallback = exceptionCallbacks.InterruptCallback; _interruptCallback = exceptionCallbacks.InterruptCallback;
_breakCallback = exceptionCallbacks.BreakCallback; _breakCallback = exceptionCallbacks.BreakCallback;
_stepCallback = exceptionCallbacks.StepCallback;
_supervisorCallback = exceptionCallbacks.SupervisorCallback; _supervisorCallback = exceptionCallbacks.SupervisorCallback;
_undefinedCallback = exceptionCallbacks.UndefinedCallback; _undefinedCallback = exceptionCallbacks.UndefinedCallback;
@ -126,17 +117,6 @@ namespace Ryujinx.Cpu.LightningJit.State
_interrupted = true; _interrupted = true;
} }
public void StepHandler()
{
_stepCallback?.Invoke(this);
}
public void RequestDebugStep()
{
Interlocked.Exchange(ref ShouldStep, 1);
RequestInterrupt();
}
internal void OnBreak(ulong address, int imm) internal void OnBreak(ulong address, int imm)
{ {
_breakCallback?.Invoke(this, address, imm); _breakCallback?.Invoke(this, address, imm);

View File

@ -1,203 +0,0 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Memory;
using System.Collections.Concurrent;
using System.Linq;
namespace Ryujinx.HLE.Debugger
{
internal class Breakpoint
{
public byte[] OriginalData { get; }
public bool IsStep { get; }
public Breakpoint(byte[] originalData, bool isStep)
{
OriginalData = originalData;
IsStep = isStep;
}
}
/// <summary>
/// Manages software breakpoints for the debugger.
/// </summary>
public class BreakpointManager
{
private readonly Debugger _debugger;
private readonly ConcurrentDictionary<ulong, Breakpoint> _breakpoints = new();
private static readonly byte[] _aarch64BreakInstruction = { 0x00, 0x00, 0x20, 0xD4 }; // BRK #0
private static readonly byte[] _aarch32BreakInstruction = { 0xFE, 0xDE, 0xFF, 0xE7 }; // TRAP
private static readonly byte[] _aarch32ThumbBreakInstruction = { 0x80, 0xB6 };
public BreakpointManager(Debugger debugger)
{
_debugger = debugger;
}
/// <summary>
/// Sets a software breakpoint at a specified address.
/// </summary>
/// <param name="address">The memory address to set the breakpoint at.</param>
/// <param name="length">The length of the instruction to replace.</param>
/// <param name="isStep">Indicates if this is a single-step breakpoint.</param>
/// <returns>True if the breakpoint was set successfully; otherwise, false.</returns>
public bool SetBreakPoint(ulong address, ulong length, bool isStep = false)
{
if (_breakpoints.ContainsKey(address))
{
return false;
}
byte[] breakInstruction = GetBreakInstruction(length);
if (breakInstruction == null)
{
Logger.Error?.Print(LogClass.GdbStub, $"Unsupported instruction length for breakpoint: {length}");
return false;
}
var originalInstruction = new byte[length];
if (!ReadMemory(address, originalInstruction))
{
Logger.Error?.Print(LogClass.GdbStub, $"Failed to read memory at 0x{address:X16} to set breakpoint.");
return false;
}
if (!WriteMemory(address, breakInstruction))
{
Logger.Error?.Print(LogClass.GdbStub, $"Failed to write breakpoint at 0x{address:X16}.");
return false;
}
var breakpoint = new Breakpoint(originalInstruction, isStep);
if (_breakpoints.TryAdd(address, breakpoint))
{
Logger.Debug?.Print(LogClass.GdbStub, $"Breakpoint set at 0x{address:X16}");
return true;
}
Logger.Error?.Print(LogClass.GdbStub, $"Failed to add breakpoint at 0x{address:X16}.");
return false;
}
/// <summary>
/// Clears a software breakpoint at a specified address.
/// </summary>
/// <param name="address">The memory address of the breakpoint to clear.</param>
/// <param name="length">The length of the instruction (unused).</param>
/// <returns>True if the breakpoint was cleared successfully; otherwise, false.</returns>
public bool ClearBreakPoint(ulong address, ulong length)
{
if (_breakpoints.TryGetValue(address, out Breakpoint breakpoint))
{
if (!WriteMemory(address, breakpoint.OriginalData))
{
Logger.Error?.Print(LogClass.GdbStub, $"Failed to restore original instruction at 0x{address:X16} to clear breakpoint.");
return false;
}
_breakpoints.TryRemove(address, out _);
Logger.Debug?.Print(LogClass.GdbStub, $"Breakpoint cleared at 0x{address:X16}");
return true;
}
Logger.Warning?.Print(LogClass.GdbStub, $"No breakpoint found at address 0x{address:X16}");
return false;
}
/// <summary>
/// Clears all currently set software breakpoints.
/// </summary>
public void ClearAll()
{
foreach (var bp in _breakpoints)
{
if (!WriteMemory(bp.Key, bp.Value.OriginalData))
{
Logger.Error?.Print(LogClass.GdbStub, $"Failed to restore original instruction at 0x{bp.Key:X16} while clearing all breakpoints.");
}
}
_breakpoints.Clear();
Logger.Debug?.Print(LogClass.GdbStub, "All breakpoints cleared.");
}
/// <summary>
/// Clears all currently set single-step software breakpoints.
/// </summary>
public void ClearAllStepBreakpoints()
{
var stepBreakpoints = _breakpoints.Where(p => p.Value.IsStep).ToList();
if (stepBreakpoints.Count == 0)
{
return;
}
foreach (var bp in stepBreakpoints)
{
if (_breakpoints.TryRemove(bp.Key, out Breakpoint removedBreakpoint))
{
WriteMemory(bp.Key, removedBreakpoint.OriginalData);
}
}
Logger.Debug?.Print(LogClass.GdbStub, "All step breakpoints cleared.");
}
private byte[] GetBreakInstruction(ulong length)
{
if (_debugger.IsProcessAarch32)
{
if (length == 2)
{
return _aarch32ThumbBreakInstruction;
}
if (length == 4)
{
return _aarch32BreakInstruction;
}
}
else
{
if (length == 4)
{
return _aarch64BreakInstruction;
}
}
return null;
}
private bool ReadMemory(ulong address, byte[] data)
{
try
{
_debugger.DebugProcess.CpuMemory.Read(address, data);
return true;
}
catch (InvalidMemoryRegionException)
{
return false;
}
}
private bool WriteMemory(ulong address, byte[] data)
{
try
{
_debugger.DebugProcess.CpuMemory.Write(address, data);
_debugger.DebugProcess.InvalidateCacheRegion(address, (ulong)data.Length);
return true;
}
catch (InvalidMemoryRegionException)
{
return false;
}
}
}
}

View File

@ -1,9 +0,0 @@
namespace Ryujinx.HLE.Debugger
{
public enum DebugState
{
Running,
Stopping,
Stopped,
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +0,0 @@
namespace Ryujinx.HLE.Debugger
{
enum GdbSignal
{
Zero = 0,
Int = 2,
Quit = 3,
Trap = 5,
Abort = 6,
Alarm = 14,
IO = 23,
XCPU = 24,
Unknown = 143
}
}

View File

@ -1,93 +0,0 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2009-2022 Free Software Foundation, Inc.
Contributed by ARM Ltd.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.aarch64.core">
<reg name="x0" bitsize="64"/>
<reg name="x1" bitsize="64"/>
<reg name="x2" bitsize="64"/>
<reg name="x3" bitsize="64"/>
<reg name="x4" bitsize="64"/>
<reg name="x5" bitsize="64"/>
<reg name="x6" bitsize="64"/>
<reg name="x7" bitsize="64"/>
<reg name="x8" bitsize="64"/>
<reg name="x9" bitsize="64"/>
<reg name="x10" bitsize="64"/>
<reg name="x11" bitsize="64"/>
<reg name="x12" bitsize="64"/>
<reg name="x13" bitsize="64"/>
<reg name="x14" bitsize="64"/>
<reg name="x15" bitsize="64"/>
<reg name="x16" bitsize="64"/>
<reg name="x17" bitsize="64"/>
<reg name="x18" bitsize="64"/>
<reg name="x19" bitsize="64"/>
<reg name="x20" bitsize="64"/>
<reg name="x21" bitsize="64"/>
<reg name="x22" bitsize="64"/>
<reg name="x23" bitsize="64"/>
<reg name="x24" bitsize="64"/>
<reg name="x25" bitsize="64"/>
<reg name="x26" bitsize="64"/>
<reg name="x27" bitsize="64"/>
<reg name="x28" bitsize="64"/>
<reg name="x29" bitsize="64"/>
<reg name="x30" bitsize="64"/>
<reg name="sp" bitsize="64" type="data_ptr"/>
<reg name="pc" bitsize="64" type="code_ptr"/>
<flags id="cpsr_flags" size="4">
<!-- Stack Pointer. -->
<field name="SP" start="0" end="0"/>
<!-- Exception Level. -->
<field name="EL" start="2" end="3"/>
<!-- Execution state. -->
<field name="nRW" start="4" end="4"/>
<!-- FIQ interrupt mask. -->
<field name="F" start="6" end="6"/>
<!-- IRQ interrupt mask. -->
<field name="I" start="7" end="7"/>
<!-- SError interrupt mask. -->
<field name="A" start="8" end="8"/>
<!-- Debug exception mask. -->
<field name="D" start="9" end="9"/>
<!-- ARMv8.5-A: Branch Target Identification BTYPE. -->
<field name="BTYPE" start="10" end="11"/>
<!-- ARMv8.0-A: Speculative Store Bypass. -->
<field name="SSBS" start="12" end="12"/>
<!-- Illegal Execution state. -->
<field name="IL" start="20" end="20"/>
<!-- Software Step. -->
<field name="SS" start="21" end="21"/>
<!-- ARMv8.1-A: Privileged Access Never. -->
<field name="PAN" start="22" end="22"/>
<!-- ARMv8.2-A: User Access Override. -->
<field name="UAO" start="23" end="23"/>
<!-- ARMv8.4-A: Data Independent Timing. -->
<field name="DIT" start="24" end="24"/>
<!-- ARMv8.5-A: Tag Check Override. -->
<field name="TCO" start="25" end="25"/>
<!-- Overflow Condition flag. -->
<field name="V" start="28" end="28"/>
<!-- Carry Condition flag. -->
<field name="C" start="29" end="29"/>
<!-- Zero Condition flag. -->
<field name="Z" start="30" end="30"/>
<!-- Negative Condition flag. -->
<field name="N" start="31" end="31"/>
</flags>
<reg name="cpsr" bitsize="32" type="cpsr_flags"/>
</feature>

View File

@ -1,159 +0,0 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2009-2022 Free Software Foundation, Inc.
Contributed by ARM Ltd.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.aarch64.fpu">
<vector id="v2d" type="ieee_double" count="2"/>
<vector id="v2u" type="uint64" count="2"/>
<vector id="v2i" type="int64" count="2"/>
<vector id="v4f" type="ieee_single" count="4"/>
<vector id="v4u" type="uint32" count="4"/>
<vector id="v4i" type="int32" count="4"/>
<vector id="v8f" type="ieee_half" count="8"/>
<vector id="v8u" type="uint16" count="8"/>
<vector id="v8i" type="int16" count="8"/>
<vector id="v8bf16" type="bfloat16" count="8"/>
<vector id="v16u" type="uint8" count="16"/>
<vector id="v16i" type="int8" count="16"/>
<vector id="v1u" type="uint128" count="1"/>
<vector id="v1i" type="int128" count="1"/>
<union id="vnd">
<field name="f" type="v2d"/>
<field name="u" type="v2u"/>
<field name="s" type="v2i"/>
</union>
<union id="vns">
<field name="f" type="v4f"/>
<field name="u" type="v4u"/>
<field name="s" type="v4i"/>
</union>
<union id="vnh">
<field name="bf" type="v8bf16"/>
<field name="f" type="v8f"/>
<field name="u" type="v8u"/>
<field name="s" type="v8i"/>
</union>
<union id="vnb">
<field name="u" type="v16u"/>
<field name="s" type="v16i"/>
</union>
<union id="vnq">
<field name="u" type="v1u"/>
<field name="s" type="v1i"/>
</union>
<union id="aarch64v">
<field name="d" type="vnd"/>
<field name="s" type="vns"/>
<field name="h" type="vnh"/>
<field name="b" type="vnb"/>
<field name="q" type="vnq"/>
</union>
<reg name="v0" bitsize="128" type="aarch64v" regnum="34"/>
<reg name="v1" bitsize="128" type="aarch64v" />
<reg name="v2" bitsize="128" type="aarch64v" />
<reg name="v3" bitsize="128" type="aarch64v" />
<reg name="v4" bitsize="128" type="aarch64v" />
<reg name="v5" bitsize="128" type="aarch64v" />
<reg name="v6" bitsize="128" type="aarch64v" />
<reg name="v7" bitsize="128" type="aarch64v" />
<reg name="v8" bitsize="128" type="aarch64v" />
<reg name="v9" bitsize="128" type="aarch64v" />
<reg name="v10" bitsize="128" type="aarch64v"/>
<reg name="v11" bitsize="128" type="aarch64v"/>
<reg name="v12" bitsize="128" type="aarch64v"/>
<reg name="v13" bitsize="128" type="aarch64v"/>
<reg name="v14" bitsize="128" type="aarch64v"/>
<reg name="v15" bitsize="128" type="aarch64v"/>
<reg name="v16" bitsize="128" type="aarch64v"/>
<reg name="v17" bitsize="128" type="aarch64v"/>
<reg name="v18" bitsize="128" type="aarch64v"/>
<reg name="v19" bitsize="128" type="aarch64v"/>
<reg name="v20" bitsize="128" type="aarch64v"/>
<reg name="v21" bitsize="128" type="aarch64v"/>
<reg name="v22" bitsize="128" type="aarch64v"/>
<reg name="v23" bitsize="128" type="aarch64v"/>
<reg name="v24" bitsize="128" type="aarch64v"/>
<reg name="v25" bitsize="128" type="aarch64v"/>
<reg name="v26" bitsize="128" type="aarch64v"/>
<reg name="v27" bitsize="128" type="aarch64v"/>
<reg name="v28" bitsize="128" type="aarch64v"/>
<reg name="v29" bitsize="128" type="aarch64v"/>
<reg name="v30" bitsize="128" type="aarch64v"/>
<reg name="v31" bitsize="128" type="aarch64v"/>
<flags id="fpsr_flags" size="4">
<!-- Invalid Operation cumulative floating-point exception bit. -->
<field name="IOC" start="0" end="0"/>
<!-- Divide by Zero cumulative floating-point exception bit. -->
<field name="DZC" start="1" end="1"/>
<!-- Overflow cumulative floating-point exception bit. -->
<field name="OFC" start="2" end="2"/>
<!-- Underflow cumulative floating-point exception bit. -->
<field name="UFC" start="3" end="3"/>
<!-- Inexact cumulative floating-point exception bit.. -->
<field name="IXC" start="4" end="4"/>
<!-- Input Denormal cumulative floating-point exception bit. -->
<field name="IDC" start="7" end="7"/>
<!-- Cumulative saturation bit, Advanced SIMD only. -->
<field name="QC" start="27" end="27"/>
<!-- When AArch32 is supported at any Exception level and AArch32
floating-point is implemented: Overflow condition flag for AArch32
floating-point comparison operations. -->
<field name="V" start="28" end="28"/>
<!-- When AArch32 is supported at any Exception level and AArch32
floating-point is implemented:
Carry condition flag for AArch32 floating-point comparison operations.
-->
<field name="C" start="29" end="29"/>
<!-- When AArch32 is supported at any Exception level and AArch32
floating-point is implemented:
Zero condition flag for AArch32 floating-point comparison operations.
-->
<field name="Z" start="30" end="30"/>
<!-- When AArch32 is supported at any Exception level and AArch32
floating-point is implemented:
Negative condition flag for AArch32 floating-point comparison
operations. -->
<field name="N" start="31" end="31"/>
</flags>
<reg name="fpsr" bitsize="32" type="fpsr_flags"/>
<flags id="fpcr_flags" size="4">
<!-- Flush Inputs to Zero (part of Armv8.7). -->
<field name="FIZ" start="0" end="0"/>
<!-- Alternate Handling (part of Armv8.7). -->
<field name="AH" start="1" end="1"/>
<!-- Controls how the output elements other than the lowest element of the
vector are determined for Advanced SIMD scalar instructions (part of
Armv8.7). -->
<field name="NEP" start="2" end="2"/>
<!-- Invalid Operation floating-point exception trap enable. -->
<field name="IOE" start="8" end="8"/>
<!-- Divide by Zero floating-point exception trap enable. -->
<field name="DZE" start="9" end="9"/>
<!-- Overflow floating-point exception trap enable. -->
<field name="OFE" start="10" end="10"/>
<!-- Underflow floating-point exception trap enable. -->
<field name="UFE" start="11" end="11"/>
<!-- Inexact floating-point exception trap enable. -->
<field name="IXE" start="12" end="12"/>
<!-- Input Denormal floating-point exception trap enable. -->
<field name="IDE" start="15" end="15"/>
<!-- Flush-to-zero mode control bit on half-precision data-processing
instructions. -->
<field name="FZ16" start="19" end="19"/>
<!-- Rounding Mode control field. -->
<field name="RMode" start="22" end="23"/>
<!-- Flush-to-zero mode control bit. -->
<field name="FZ" start="24" end="24"/>
<!-- Default NaN mode control bit. -->
<field name="DN" start="25" end="25"/>
<!-- Alternative half-precision control bit. -->
<field name="AHP" start="26" end="26"/>
</flags>
<reg name="fpcr" bitsize="32" type="fpcr_flags"/>
</feature>

View File

@ -1,27 +0,0 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2008 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.arm.core">
<reg name="r0" bitsize="32"/>
<reg name="r1" bitsize="32"/>
<reg name="r2" bitsize="32"/>
<reg name="r3" bitsize="32"/>
<reg name="r4" bitsize="32"/>
<reg name="r5" bitsize="32"/>
<reg name="r6" bitsize="32"/>
<reg name="r7" bitsize="32"/>
<reg name="r8" bitsize="32"/>
<reg name="r9" bitsize="32"/>
<reg name="r10" bitsize="32"/>
<reg name="r11" bitsize="32"/>
<reg name="r12" bitsize="32"/>
<reg name="sp" bitsize="32" type="data_ptr"/>
<reg name="lr" bitsize="32"/>
<reg name="pc" bitsize="32" type="code_ptr"/>
<reg name="cpsr" bitsize="32" />
</feature>

View File

@ -1,86 +0,0 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2008 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.arm.vfp">
<vector id="neon_uint8x8" type="uint8" count="8"/>
<vector id="neon_uint16x4" type="uint16" count="4"/>
<vector id="neon_uint32x2" type="uint32" count="2"/>
<vector id="neon_float32x2" type="ieee_single" count="2"/>
<union id="neon_d">
<field name="u8" type="neon_uint8x8"/>
<field name="u16" type="neon_uint16x4"/>
<field name="u32" type="neon_uint32x2"/>
<field name="u64" type="uint64"/>
<field name="f32" type="neon_float32x2"/>
<field name="f64" type="ieee_double"/>
</union>
<vector id="neon_uint8x16" type="uint8" count="16"/>
<vector id="neon_uint16x8" type="uint16" count="8"/>
<vector id="neon_uint32x4" type="uint32" count="4"/>
<vector id="neon_uint64x2" type="uint64" count="2"/>
<vector id="neon_float32x4" type="ieee_single" count="4"/>
<vector id="neon_float64x2" type="ieee_double" count="2"/>
<union id="neon_q">
<field name="u8" type="neon_uint8x16"/>
<field name="u16" type="neon_uint16x8"/>
<field name="u32" type="neon_uint32x4"/>
<field name="u64" type="neon_uint64x2"/>
<field name="f32" type="neon_float32x4"/>
<field name="f64" type="neon_float64x2"/>
</union>
<reg name="d0" bitsize="64" type="neon_d"/>
<reg name="d1" bitsize="64" type="neon_d"/>
<reg name="d2" bitsize="64" type="neon_d"/>
<reg name="d3" bitsize="64" type="neon_d"/>
<reg name="d4" bitsize="64" type="neon_d"/>
<reg name="d5" bitsize="64" type="neon_d"/>
<reg name="d6" bitsize="64" type="neon_d"/>
<reg name="d7" bitsize="64" type="neon_d"/>
<reg name="d8" bitsize="64" type="neon_d"/>
<reg name="d9" bitsize="64" type="neon_d"/>
<reg name="d10" bitsize="64" type="neon_d"/>
<reg name="d11" bitsize="64" type="neon_d"/>
<reg name="d12" bitsize="64" type="neon_d"/>
<reg name="d13" bitsize="64" type="neon_d"/>
<reg name="d14" bitsize="64" type="neon_d"/>
<reg name="d15" bitsize="64" type="neon_d"/>
<reg name="d16" bitsize="64" type="neon_d"/>
<reg name="d17" bitsize="64" type="neon_d"/>
<reg name="d18" bitsize="64" type="neon_d"/>
<reg name="d19" bitsize="64" type="neon_d"/>
<reg name="d20" bitsize="64" type="neon_d"/>
<reg name="d21" bitsize="64" type="neon_d"/>
<reg name="d22" bitsize="64" type="neon_d"/>
<reg name="d23" bitsize="64" type="neon_d"/>
<reg name="d24" bitsize="64" type="neon_d"/>
<reg name="d25" bitsize="64" type="neon_d"/>
<reg name="d26" bitsize="64" type="neon_d"/>
<reg name="d27" bitsize="64" type="neon_d"/>
<reg name="d28" bitsize="64" type="neon_d"/>
<reg name="d29" bitsize="64" type="neon_d"/>
<reg name="d30" bitsize="64" type="neon_d"/>
<reg name="d31" bitsize="64" type="neon_d"/>
<reg name="q0" bitsize="128" type="neon_q"/>
<reg name="q1" bitsize="128" type="neon_q"/>
<reg name="q2" bitsize="128" type="neon_q"/>
<reg name="q3" bitsize="128" type="neon_q"/>
<reg name="q4" bitsize="128" type="neon_q"/>
<reg name="q5" bitsize="128" type="neon_q"/>
<reg name="q6" bitsize="128" type="neon_q"/>
<reg name="q7" bitsize="128" type="neon_q"/>
<reg name="q8" bitsize="128" type="neon_q"/>
<reg name="q9" bitsize="128" type="neon_q"/>
<reg name="q10" bitsize="128" type="neon_q"/>
<reg name="q11" bitsize="128" type="neon_q"/>
<reg name="q12" bitsize="128" type="neon_q"/>
<reg name="q13" bitsize="128" type="neon_q"/>
<reg name="q14" bitsize="128" type="neon_q"/>
<reg name="q15" bitsize="128" type="neon_q"/>
<reg name="fpscr" bitsize="32" type="int" group="float"/>
</feature>

View File

@ -1,14 +0,0 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2009-2013 Free Software Foundation, Inc.
Contributed by ARM Ltd.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target>
<architecture>arm</architecture>
<xi:include href="arm-core.xml"/>
<xi:include href="arm-neon.xml"/>
</target>

View File

@ -1,14 +0,0 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2009-2013 Free Software Foundation, Inc.
Contributed by ARM Ltd.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target>
<architecture>aarch64</architecture>
<xi:include href="aarch64-core.xml"/>
<xi:include href="aarch64-fpu.xml"/>
</target>

View File

@ -1,21 +0,0 @@
using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Memory;
namespace Ryujinx.HLE.Debugger
{
internal interface IDebuggableProcess
{
void DebugStop();
void DebugContinue();
void DebugContinue(KThread thread);
bool DebugStep(KThread thread);
KThread GetThread(ulong threadUid);
DebugState GetDebugState();
bool IsThreadPaused(KThread thread);
ulong[] GetThreadUids();
public void DebugInterruptHandler(IExecutionContext ctx);
IVirtualMemoryManager CpuMemory { get; }
void InvalidateCacheRegion(ulong address, ulong size);
}
}

View File

@ -1,6 +0,0 @@
namespace Ryujinx.HLE.Debugger
{
struct BreakInMessage : IMessage
{
}
}

View File

@ -1,12 +0,0 @@
namespace Ryujinx.HLE.Debugger
{
struct CommandMessage : IMessage
{
public string Command;
public CommandMessage(string cmd)
{
Command = cmd;
}
}
}

View File

@ -1,6 +0,0 @@
namespace Ryujinx.HLE.Debugger
{
interface IMessage
{
}
}

View File

@ -1,6 +0,0 @@
namespace Ryujinx.HLE.Debugger
{
struct KillMessage : IMessage
{
}
}

View File

@ -1,6 +0,0 @@
namespace Ryujinx.HLE.Debugger
{
struct SendNackMessage : IMessage
{
}
}

View File

@ -1,18 +0,0 @@
using IExecutionContext = Ryujinx.Cpu.IExecutionContext;
namespace Ryujinx.HLE.Debugger
{
public class ThreadBreakMessage : IMessage
{
public IExecutionContext Context { get; }
public ulong Address { get; }
public int Opcode { get; }
public ThreadBreakMessage(IExecutionContext context, ulong address, int opcode)
{
Context = context;
Address = address;
Opcode = opcode;
}
}
}

View File

@ -1,28 +0,0 @@
using System.Collections.Generic;
using System.IO;
namespace Ryujinx.HLE.Debugger
{
class RegisterInformation
{
public static readonly Dictionary<string, string> Features = new()
{
{ "target64.xml", GetEmbeddedResourceContent("target64.xml") },
{ "target32.xml", GetEmbeddedResourceContent("target32.xml") },
{ "aarch64-core.xml", GetEmbeddedResourceContent("aarch64-core.xml") },
{ "aarch64-fpu.xml", GetEmbeddedResourceContent("aarch64-fpu.xml") },
{ "arm-core.xml", GetEmbeddedResourceContent("arm-core.xml") },
{ "arm-neon.xml", GetEmbeddedResourceContent("arm-neon.xml") },
};
private static string GetEmbeddedResourceContent(string resourceName)
{
Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("Ryujinx.HLE.Debugger.GdbXml." + resourceName);
StreamReader reader = new StreamReader(stream);
string result = reader.ReadToEnd();
reader.Dispose();
stream.Dispose();
return result;
}
}
}

View File

@ -1,109 +0,0 @@
using System.Diagnostics;
using System.Globalization;
namespace Ryujinx.HLE.Debugger
{
class StringStream
{
private readonly string Data;
private int Position;
public StringStream(string s)
{
Data = s;
}
public char ReadChar()
{
return Data[Position++];
}
public string ReadUntil(char needle)
{
int needlePos = Data.IndexOf(needle, Position);
if (needlePos == -1)
{
needlePos = Data.Length;
}
string result = Data.Substring(Position, needlePos - Position);
Position = needlePos + 1;
return result;
}
public string ReadLength(int len)
{
string result = Data.Substring(Position, len);
Position += len;
return result;
}
public string ReadRemaining()
{
string result = Data.Substring(Position);
Position = Data.Length;
return result;
}
public ulong ReadRemainingAsHex()
{
return ulong.Parse(ReadRemaining(), NumberStyles.HexNumber);
}
public ulong ReadUntilAsHex(char needle)
{
return ulong.Parse(ReadUntil(needle), NumberStyles.HexNumber);
}
public ulong ReadLengthAsHex(int len)
{
return ulong.Parse(ReadLength(len), NumberStyles.HexNumber);
}
public ulong ReadLengthAsLEHex(int len)
{
Debug.Assert(len % 2 == 0);
ulong result = 0;
int pos = 0;
while (pos < len)
{
result += ReadLengthAsHex(2) << (4 * pos);
pos += 2;
}
return result;
}
public ulong? ReadRemainingAsThreadUid()
{
string s = ReadRemaining();
return s == "-1" ? null : ulong.Parse(s, NumberStyles.HexNumber);
}
public bool ConsumePrefix(string prefix)
{
if (Data.Substring(Position).StartsWith(prefix))
{
Position += prefix.Length;
return true;
}
return false;
}
public bool ConsumeRemaining(string match)
{
if (Data.Substring(Position) == match)
{
Position += match.Length;
return true;
}
return false;
}
public bool IsEmpty()
{
return Position >= Data.Length;
}
}
}

View File

@ -69,7 +69,7 @@ namespace Ryujinx.HLE.HOS
mode = MemoryManagerMode.SoftwarePageTable; mode = MemoryManagerMode.SoftwarePageTable;
} }
ICpuEngine cpuEngine = isArm64Host && (mode == MemoryManagerMode.HostMapped || mode == MemoryManagerMode.HostMappedUnsafe) && !context.Device.Configuration.EnableGdbStub ICpuEngine cpuEngine = isArm64Host && (mode == MemoryManagerMode.HostMapped || mode == MemoryManagerMode.HostMappedUnsafe)
? new LightningJitEngine(_tickSource) ? new LightningJitEngine(_tickSource)
: new JitEngine(_tickSource); : new JitEngine(_tickSource);

View File

@ -5,7 +5,6 @@ using LibHac.Fs.Shim;
using LibHac.FsSystem; using LibHac.FsSystem;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Cpu; using Ryujinx.Cpu;
using Ryujinx.HLE.Debugger;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Memory;
@ -501,21 +500,5 @@ namespace Ryujinx.HLE.HOS
IsPaused = pause; IsPaused = pause;
} }
internal IDebuggableProcess DebugGetApplicationProcessDebugInterface()
{
lock (KernelContext.Processes)
{
return KernelContext.Processes.Values.FirstOrDefault(x => x.IsApplication)?.DebugInterface;
}
}
internal KProcess DebugGetApplicationProcess()
{
lock (KernelContext.Processes)
{
return KernelContext.Processes.Values.FirstOrDefault(x => x.IsApplication);
}
}
} }
} }

View File

@ -4,7 +4,6 @@ using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.HLE.Loaders.Elf; using Ryujinx.HLE.Loaders.Elf;
using Ryujinx.Memory; using Ryujinx.Memory;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -18,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
private readonly KProcess _owner; private readonly KProcess _owner;
public class Image private class Image
{ {
public ulong BaseAddress { get; } public ulong BaseAddress { get; }
public ulong Size { get; } public ulong Size { get; }
@ -55,15 +54,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
trace.AppendLine($"Process: {_owner.Name}, PID: {_owner.Pid}"); trace.AppendLine($"Process: {_owner.Name}, PID: {_owner.Pid}");
string ThreadName = thread.GetThreadName();
if (!String.IsNullOrEmpty(ThreadName))
{
trace.AppendLine($"Thread ID: {thread.ThreadUid} ({ThreadName})");
} else {
trace.AppendLine($"Thread ID: {thread.ThreadUid}");
}
void AppendTrace(ulong address) void AppendTrace(ulong address)
{ {
if (AnalyzePointer(out PointerInfo info, address, thread)) if (AnalyzePointer(out PointerInfo info, address, thread))
@ -293,7 +283,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return null; return null;
} }
public string GetGuessedNsoNameFromIndex(int index) private string GetGuessedNsoNameFromIndex(int index)
{ {
if ((uint)index > 11) if ((uint)index > 11)
{ {
@ -326,16 +316,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
} }
} }
public List<Image> GetLoadedImages()
{
EnsureLoaded();
lock (_images)
{
return [.. _images];
}
}
private void EnsureLoaded() private void EnsureLoaded()
{ {
if (Interlocked.CompareExchange(ref _loaded, 1, 0) == 0) if (Interlocked.CompareExchange(ref _loaded, 1, 0) == 0)

View File

@ -1,7 +1,6 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Cpu; using Ryujinx.Cpu;
using Ryujinx.HLE.Debugger;
using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.Exceptions;
using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Memory;
@ -12,8 +11,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using ExceptionCallback = Ryujinx.Cpu.ExceptionCallback;
using ExceptionCallbackNoArgs = Ryujinx.Cpu.ExceptionCallbackNoArgs;
namespace Ryujinx.HLE.HOS.Kernel.Process namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
@ -92,8 +89,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public IVirtualMemoryManager CpuMemory => Context.AddressSpace; public IVirtualMemoryManager CpuMemory => Context.AddressSpace;
public HleProcessDebugger Debugger { get; private set; } public HleProcessDebugger Debugger { get; private set; }
public IDebuggableProcess DebugInterface { get; private set; }
protected int debugState = (int)DebugState.Running;
public KProcess(KernelContext context, bool allowCodeMemoryForJit = false) : base(context) public KProcess(KernelContext context, bool allowCodeMemoryForJit = false) : base(context)
{ {
@ -115,7 +110,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
_threads = []; _threads = [];
Debugger = new HleProcessDebugger(this); Debugger = new HleProcessDebugger(this);
DebugInterface = new DebuggerInterface(this);
} }
public Result InitializeKip( public Result InitializeKip(
@ -685,13 +679,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
SetState(newState); SetState(newState);
if (KernelContext.Device.Configuration.DebuggerSuspendOnStart && IsApplication)
{
mainThread.Suspend(ThreadSchedState.ThreadPauseFlag);
debugState = (int)DebugState.Stopped;
Logger.Notice.Print(LogClass.Kernel, $"Application is suspended on start for debugging.");
}
result = mainThread.Start(); result = mainThread.Start();
if (result != Result.Success) if (result != Result.Success)
@ -740,19 +727,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public IExecutionContext CreateExecutionContext() public IExecutionContext CreateExecutionContext()
{ {
ExceptionCallback breakCallback = null;
ExceptionCallbackNoArgs stepCallback = null;
if (KernelContext.Device.Configuration.EnableGdbStub && KernelContext.Device.Debugger != null)
{
breakCallback = KernelContext.Device.Debugger.BreakHandler;
stepCallback = KernelContext.Device.Debugger.StepHandler;
}
return Context?.CreateExecutionContext(new ExceptionCallbacks( return Context?.CreateExecutionContext(new ExceptionCallbacks(
InterruptHandler, InterruptHandler,
breakCallback, null,
stepCallback,
KernelContext.SyscallHandler.SvcCall, KernelContext.SyscallHandler.SvcCall,
UndefinedInstructionHandler)); UndefinedInstructionHandler));
} }
@ -1197,186 +1174,5 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
return Capabilities.IsSvcPermitted(svcId); return Capabilities.IsSvcPermitted(svcId);
} }
private class DebuggerInterface : IDebuggableProcess
{
private Barrier StepBarrier;
private readonly KProcess _parent;
private readonly KernelContext _kernelContext;
private KThread steppingThread;
public DebuggerInterface(KProcess p)
{
_parent = p;
_kernelContext = p.KernelContext;
StepBarrier = new(2);
}
public void DebugStop()
{
if (Interlocked.CompareExchange(ref _parent.debugState, (int)DebugState.Stopping,
(int)DebugState.Running) != (int)DebugState.Running)
{
return;
}
_kernelContext.CriticalSection.Enter();
lock (_parent._threadingLock)
{
foreach (KThread thread in _parent._threads)
{
thread.Suspend(ThreadSchedState.ThreadPauseFlag);
thread.Context.RequestInterrupt();
if (!thread.DebugHalt.WaitOne(TimeSpan.FromMilliseconds(50)))
{
Logger.Warning?.Print(LogClass.Kernel, $"Failed to suspend thread {thread.ThreadUid} in time.");
}
}
}
_parent.debugState = (int)DebugState.Stopped;
_kernelContext.CriticalSection.Leave();
}
public void DebugContinue()
{
if (Interlocked.CompareExchange(ref _parent.debugState, (int)DebugState.Running,
(int)DebugState.Stopped) != (int)DebugState.Stopped)
{
return;
}
_kernelContext.CriticalSection.Enter();
lock (_parent._threadingLock)
{
foreach (KThread thread in _parent._threads)
{
thread.Resume(ThreadSchedState.ThreadPauseFlag);
}
}
_kernelContext.CriticalSection.Leave();
}
public void DebugContinue(KThread target)
{
Interlocked.Exchange(ref _parent.debugState, (int)DebugState.Running);
_kernelContext.CriticalSection.Enter();
lock (_parent._threadingLock)
{
target.Resume(ThreadSchedState.ThreadPauseFlag);
}
_kernelContext.CriticalSection.Leave();
}
public bool DebugStep(KThread target)
{
if (!IsThreadPaused(target))
{
return false;
}
_kernelContext.CriticalSection.Enter();
steppingThread = target;
bool waiting = target.MutexOwner != null || target.WaitingSync || target.WaitingInArbitration;
target.Context.RequestDebugStep();
if (waiting)
{
lock (_parent._threadingLock)
{
foreach (KThread thread in _parent._threads)
{
thread.Resume(ThreadSchedState.ThreadPauseFlag);
}
}
}
else
{
target.Resume(ThreadSchedState.ThreadPauseFlag);
}
_kernelContext.CriticalSection.Leave();
bool stepTimedOut = false;
if (!StepBarrier.SignalAndWait(TimeSpan.FromMilliseconds(2000)))
{
Logger.Warning?.Print(LogClass.Kernel, $"Failed to step thread {target.ThreadUid} in time.");
stepTimedOut = true;
}
_kernelContext.CriticalSection.Enter();
steppingThread = null;
if (waiting)
{
lock (_parent._threadingLock)
{
foreach (KThread thread in _parent._threads)
{
thread.Suspend(ThreadSchedState.ThreadPauseFlag);
}
}
}
else
{
target.Suspend(ThreadSchedState.ThreadPauseFlag);
}
_kernelContext.CriticalSection.Leave();
if (stepTimedOut)
{
return false;
}
StepBarrier.SignalAndWait();
return true;
}
public DebugState GetDebugState()
{
return (DebugState)_parent.debugState;
}
public bool IsThreadPaused(KThread target)
{
return (target.SchedFlags & ThreadSchedState.ThreadPauseFlag) != 0;
}
public ulong[] GetThreadUids()
{
lock (_parent._threadingLock)
{
var threads = _parent._threads.Where(x => !x.TerminationRequested).ToArray();
return threads.Select(x => x.ThreadUid).ToArray();
}
}
public KThread GetThread(ulong threadUid)
{
lock (_parent._threadingLock)
{
var threads = _parent._threads.Where(x => !x.TerminationRequested).ToArray();
return threads.FirstOrDefault(x => x.ThreadUid == threadUid);
}
}
public void DebugInterruptHandler(IExecutionContext ctx)
{
_kernelContext.CriticalSection.Enter();
bool stepping = steppingThread != null;
_kernelContext.CriticalSection.Leave();
if (stepping)
{
StepBarrier.SignalAndWait();
StepBarrier.SignalAndWait();
}
_parent.InterruptHandler(ctx);
}
public IVirtualMemoryManager CpuMemory { get { return _parent.CpuMemory; } }
public void InvalidateCacheRegion(ulong address, ulong size)
{
_parent.Context.InvalidateCacheRegion(address, size);
}
}
} }
} }

View File

@ -1,6 +1,5 @@
using ARMeilleure.State; using ARMeilleure.State;
using Ryujinx.Cpu; using Ryujinx.Cpu;
using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel.Process namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
@ -18,14 +17,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public bool IsAarch32 { get => false; set { } } public bool IsAarch32 { get => false; set { } }
public ulong ThreadUid { get; set; }
public bool Running { get; private set; } = true; public bool Running { get; private set; } = true;
private readonly ulong[] _x = new ulong[32]; private readonly ulong[] _x = new ulong[32];
public ulong DebugPc { get; set; }
public ulong GetX(int index) => _x[index]; public ulong GetX(int index) => _x[index];
public void SetX(int index, ulong value) => _x[index] = value; public void SetX(int index, ulong value) => _x[index] = value;
@ -36,10 +31,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
} }
public void RequestDebugStep()
{
}
public void StopRunning() public void StopRunning()
{ {
Running = false; Running = false;

View File

@ -301,7 +301,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
currentThread.SchedulerWaitEvent.Reset(); currentThread.SchedulerWaitEvent.Reset();
currentThread.ThreadContext.Unlock(); currentThread.ThreadContext.Unlock();
currentThread.DebugHalt.Set();
// Wake all the threads that might be waiting until this thread context is unlocked. // Wake all the threads that might be waiting until this thread context is unlocked.
for (int core = 0; core < CpuCoresCount; core++) for (int core = 0; core < CpuCoresCount; core++)

View File

@ -1,15 +1,12 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Cpu; using Ryujinx.Cpu;
using Ryujinx.HLE.Debugger;
using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.SupervisorCall; using Ryujinx.HLE.HOS.Kernel.SupervisorCall;
using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Common;
using Ryujinx.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics; using System.Numerics;
using System.Text;
using System.Threading; using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel.Threading namespace Ryujinx.HLE.HOS.Kernel.Threading
@ -19,23 +16,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
private const int TlsUserDisableCountOffset = 0x100; private const int TlsUserDisableCountOffset = 0x100;
private const int TlsUserInterruptFlagOffset = 0x102; private const int TlsUserInterruptFlagOffset = 0x102;
// Tls -> ThreadType
private const int TlsThreadTypeOffsetAArch64 = 0x1F8;
private const int TlsThreadTypeOffsetAArch32 = 0x1FC;
// Tls -> ThreadType -> Version
private const int TlsThreadTypeVersionOffsetAArch64 = 0x46;
private const int TlsThreadTypeVersionOffsetAArch32 = 0x26;
// Tls -> ThreadType (Version 0) -> ThreadNamePointer
private const int TlsThreadTypeVersion0ThreadNamePointerOffsetAArch64 = 0x1A8;
private const int TlsThreadTypeVersion0ThreadNamePointerOffsetAArch32 = 0xE8;
// Tls -> ThreadType (Version 1) -> ThreadNamePointer
private const int TlsThreadTypeThreadNamePointerOffsetAArch64 = 0x1A0;
private const int TlsThreadTypeThreadNamePointerOffsetAArch32 = 0xE4;
public const int MaxWaitSyncObjects = 64; public const int MaxWaitSyncObjects = 64;
private ManualResetEvent _schedulerWaitEvent; private ManualResetEvent _schedulerWaitEvent;
@ -134,8 +114,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
private readonly Lock _activityOperationLock = new(); private readonly Lock _activityOperationLock = new();
internal readonly ManualResetEvent DebugHalt = new(false);
public KThread(KernelContext context) : base(context) public KThread(KernelContext context) : base(context)
{ {
WaitSyncObjects = new KSynchronizationObject[MaxWaitSyncObjects]; WaitSyncObjects = new KSynchronizationObject[MaxWaitSyncObjects];
@ -224,10 +202,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
} }
Context.TpidrroEl0 = (long)_tlsAddress; Context.TpidrroEl0 = (long)_tlsAddress;
Context.DebugPc = _entrypoint;
ThreadUid = KernelContext.NewThreadUid(); ThreadUid = KernelContext.NewThreadUid();
Context.ThreadUid = ThreadUid;
HostThread.Name = customThreadStart != null ? $"HLE.OsThread.{ThreadUid}" : $"HLE.GuestThread.{ThreadUid}"; HostThread.Name = customThreadStart != null ? $"HLE.OsThread.{ThreadUid}" : $"HLE.GuestThread.{ThreadUid}";
@ -331,9 +307,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{ {
KernelContext.CriticalSection.Enter(); KernelContext.CriticalSection.Enter();
KThread currentThread = KernelStatic.GetCurrentThread(); if (Owner != null && Owner.PinnedThreads[KernelStatic.GetCurrentThread().CurrentCore] == this)
if (Owner != null && currentThread != null && Owner.PinnedThreads[currentThread.CurrentCore] == this)
{ {
Owner.UnpinThread(this); Owner.UnpinThread(this);
} }
@ -388,7 +362,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{ {
ThreadSchedState state = PrepareForTermination(); ThreadSchedState state = PrepareForTermination();
if (KernelStatic.GetCurrentThread() == this && state != ThreadSchedState.TerminationPending) if (state != ThreadSchedState.TerminationPending)
{ {
KernelContext.Synchronization.WaitFor(new KSynchronizationObject[] { this }, -1, out _); KernelContext.Synchronization.WaitFor(new KSynchronizationObject[] { this }, -1, out _);
} }
@ -1274,7 +1248,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
private void ThreadStart() private void ThreadStart()
{ {
_schedulerWaitEvent.WaitOne(); _schedulerWaitEvent.WaitOne();
DebugHalt.Reset();
KernelStatic.SetKernelContext(KernelContext, this); KernelStatic.SetKernelContext(KernelContext, this);
if (_customThreadStart != null) if (_customThreadStart != null)
@ -1458,84 +1431,5 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{ {
Owner.CpuMemory.Write<ushort>(_tlsAddress + TlsUserInterruptFlagOffset, 0); Owner.CpuMemory.Write<ushort>(_tlsAddress + TlsUserInterruptFlagOffset, 0);
} }
public string GetThreadName()
{
try
{
ulong threadNamePtr = 0;
if (Context.IsAarch32)
{
uint threadTypePtr32 = Owner.CpuMemory.Read<uint>(_tlsAddress + TlsThreadTypeOffsetAArch32);
if (threadTypePtr32 == 0)
{
return "";
}
ushort version = Owner.CpuMemory.Read<ushort>(threadTypePtr32 + TlsThreadTypeVersionOffsetAArch32);
switch (version)
{
case 0x0000:
case 0xFFFF:
threadNamePtr = Owner.CpuMemory.Read<uint>(threadTypePtr32 + TlsThreadTypeVersion0ThreadNamePointerOffsetAArch32);
break;
case 0x0001:
threadNamePtr = Owner.CpuMemory.Read<uint>(threadTypePtr32 + TlsThreadTypeThreadNamePointerOffsetAArch32);
break;
default:
Logger.Warning?.Print(LogClass.Kernel, $"Unknown ThreadType struct version: {version}");
break;
}
}
else
{
ulong threadTypePtr64 = Owner.CpuMemory.Read<ulong>(_tlsAddress + TlsThreadTypeOffsetAArch64);
if (threadTypePtr64 == 0)
{
return "";
}
ushort version = Owner.CpuMemory.Read<ushort>(threadTypePtr64 + TlsThreadTypeVersionOffsetAArch64);
switch (version)
{
case 0x0000:
case 0xFFFF:
threadNamePtr = Owner.CpuMemory.Read<ulong>(threadTypePtr64 + TlsThreadTypeVersion0ThreadNamePointerOffsetAArch64);
break;
case 0x0001:
threadNamePtr = Owner.CpuMemory.Read<ulong>(threadTypePtr64 + TlsThreadTypeThreadNamePointerOffsetAArch64);
break;
default:
Logger.Warning?.Print(LogClass.Kernel, $"Unknown ThreadType struct version: {version}");
break;
}
}
if (threadNamePtr == 0)
{
return "";
}
List<byte> nameBytes = new();
for (int i = 0; i < 0x20; i++)
{
byte b = Owner.CpuMemory.Read<byte>(threadNamePtr + (ulong)i);
if (b == 0)
{
break;
}
nameBytes.Add(b);
}
return Encoding.UTF8.GetString(nameBytes.ToArray());
} catch (InvalidMemoryRegionException)
{
Logger.Warning?.Print(LogClass.Kernel, "Failed to get thread name.");
return "";
} catch (Exception e) {
Logger.Error?.Print(LogClass.Kernel, $"Error getting thread name: {e.Message}");
return "";
}
}
} }
} }

View File

@ -21,21 +21,6 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
return ResultCode.Success; return ResultCode.Success;
} }
[CommandCmif(3)] // 20.0.0+
// CreateLibraryAppletEx(u32, u32, u64) -> object<nn::am::service::ILibraryAppletAccessor>
public ResultCode CreateLibraryAppletEx(ServiceCtx context)
{
AppletId appletId = (AppletId)context.RequestData.ReadInt32();
_ = context.RequestData.ReadInt32(); // libraryAppletMode
_ = context.RequestData.ReadUInt64(); // threadId
MakeObject(context, new ILibraryAppletAccessor(appletId, context.Device.System));
return ResultCode.Success;
}
[CommandCmif(10)] [CommandCmif(10)]
// CreateStorage(u64) -> object<nn::am::service::IStorage> // CreateStorage(u64) -> object<nn::am::service::IStorage>
public ResultCode CreateStorage(ServiceCtx context) public ResultCode CreateStorage(ServiceCtx context)

View File

@ -194,21 +194,6 @@ namespace Ryujinx.HLE
/// </summary> /// </summary>
public Action RefreshInputConfig { internal get; set; } public Action RefreshInputConfig { internal get; set; }
/// <summary>
/// Enables gdbstub to allow for debugging of the guest .
/// </summary>
public bool EnableGdbStub { internal get; set; }
/// <summary>
/// A TCP port to use to expose a gdbstub for a debugger to connect to.
/// </summary>
public ushort GdbStubPort { internal get; set; }
/// <summary>
/// Suspend execution when starting an application
/// </summary>
public bool DebuggerSuspendOnStart { internal get; set; }
/// <summary> /// <summary>
/// The desired hacky workarounds. /// The desired hacky workarounds.
/// </summary> /// </summary>
@ -237,9 +222,6 @@ namespace Ryujinx.HLE
bool multiplayerDisableP2p, bool multiplayerDisableP2p,
string multiplayerLdnPassphrase, string multiplayerLdnPassphrase,
string multiplayerLdnServer, string multiplayerLdnServer,
bool enableGdbStub,
ushort gdbStubPort,
bool debuggerSuspendOnStart,
int customVSyncInterval, int customVSyncInterval,
EnabledDirtyHack[] dirtyHacks = null) EnabledDirtyHack[] dirtyHacks = null)
{ {
@ -266,9 +248,6 @@ namespace Ryujinx.HLE
MultiplayerDisableP2p = multiplayerDisableP2p; MultiplayerDisableP2p = multiplayerDisableP2p;
MultiplayerLdnPassphrase = multiplayerLdnPassphrase; MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
MultiplayerLdnServer = multiplayerLdnServer; MultiplayerLdnServer = multiplayerLdnServer;
EnableGdbStub = enableGdbStub;
GdbStubPort = gdbStubPort;
DebuggerSuspendOnStart = debuggerSuspendOnStart;
Hacks = dirtyHacks ?? []; Hacks = dirtyHacks ?? [];
} }

View File

@ -33,12 +33,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="Debugger\GdbXml\aarch64-core.xml" />
<None Remove="Debugger\GdbXml\aarch64-fpu.xml" />
<None Remove="Debugger\GdbXml\arm-core.xml" />
<None Remove="Debugger\GdbXml\arm-neon.xml" />
<None Remove="Debugger\GdbXml\target64.xml" />
<None Remove="Debugger\GdbXml\target32.xml" />
<None Remove="Homebrew.npdm" /> <None Remove="Homebrew.npdm" />
<None Remove="HOS\Applets\SoftwareKeyboard\Resources\Logo_Ryujinx.png" /> <None Remove="HOS\Applets\SoftwareKeyboard\Resources\Logo_Ryujinx.png" />
<None Remove="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnA.png" /> <None Remove="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnA.png" />
@ -48,12 +42,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Debugger\GdbXml\aarch64-core.xml" />
<EmbeddedResource Include="Debugger\GdbXml\aarch64-fpu.xml" />
<EmbeddedResource Include="Debugger\GdbXml\arm-core.xml" />
<EmbeddedResource Include="Debugger\GdbXml\arm-neon.xml" />
<EmbeddedResource Include="Debugger\GdbXml\target64.xml" />
<EmbeddedResource Include="Debugger\GdbXml\target32.xml" />
<EmbeddedResource Include="Homebrew.npdm" /> <EmbeddedResource Include="Homebrew.npdm" />
<EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Logo_Ryujinx.png" /> <EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Logo_Ryujinx.png" />
<EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnA.png" /> <EmbeddedResource Include="HOS\Applets\SoftwareKeyboard\Resources\Icon_BtnA.png" />

View File

@ -14,7 +14,6 @@ using Ryujinx.HLE.Loaders.Processes;
using Ryujinx.HLE.UI; using Ryujinx.HLE.UI;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
using System.Threading;
namespace Ryujinx.HLE namespace Ryujinx.HLE
{ {
@ -42,7 +41,6 @@ namespace Ryujinx.HLE
public Hid Hid { get; } public Hid Hid { get; }
public TamperMachine TamperMachine { get; } public TamperMachine TamperMachine { get; }
public IHostUIHandler UIHandler { get; } public IHostUIHandler UIHandler { get; }
public Debugger.Debugger Debugger { get; }
public int CpuCoresCount = 4; // Switch has a quad-core Tegra X1 SoC public int CpuCoresCount = 4; // Switch has a quad-core Tegra X1 SoC
@ -74,7 +72,6 @@ namespace Ryujinx.HLE
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, DirtyHacks); Gpu = new GpuContext(Configuration.GpuRenderer, DirtyHacks);
Debugger = Configuration.EnableGdbStub ? new Debugger.Debugger(this, Configuration.GdbStubPort) : null;
System = new HOS.Horizon(this); System = new HOS.Horizon(this);
Statistics = new PerformanceStatistics(this); Statistics = new PerformanceStatistics(this);
Hid = new Hid(this, System.HidStorage); Hid = new Hid(this, System.HidStorage);
@ -176,7 +173,6 @@ namespace Ryujinx.HLE
AudioDeviceDriver.Dispose(); AudioDeviceDriver.Dispose();
FileSystem.Dispose(); FileSystem.Dispose();
Memory.Dispose(); Memory.Dispose();
Debugger?.Dispose();
TitleIDs.CurrentApplication.Value = null; TitleIDs.CurrentApplication.Value = null;
Shared = null; Shared = null;

View File

@ -0,0 +1,9 @@
namespace Ryujinx.Ava.Common.Models.Github
{
public class GithubReleaseAssetJsonResponse
{
public string Name { get; set; }
public string State { get; set; }
public string BrowserDownloadUrl { get; set; }
}
}

View File

@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace Ryujinx.Ava.Common.Models.Github
{
public class GithubReleasesJsonResponse
{
public string Name { get; set; }
public string TagName { get; set; }
public List<GithubReleaseAssetJsonResponse> Assets { get; set; }
}
}

View File

@ -0,0 +1,7 @@
using System.Text.Json.Serialization;
namespace Ryujinx.Ava.Common.Models.Github
{
[JsonSerializable(typeof(GithubReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)]
public partial class GithubReleasesJsonSerializerContext : JsonSerializerContext;
}

View File

@ -338,9 +338,6 @@ namespace Ryujinx.Headless
false, false,
string.Empty, string.Empty,
string.Empty, string.Empty,
options.EnableGdbStub,
options.GdbStubPort,
options.DebuggerSuspendOnStart,
options.CustomVSyncInterval options.CustomVSyncInterval
) )
.Configure( .Configure(

View File

@ -423,17 +423,6 @@ namespace Ryujinx.Headless
[Option("skip-user-profiles-manager", Required = false, Default = false, HelpText = "Enable skips the Profiles Manager popup during gameplay. Select the desired profile before starting the game")] [Option("skip-user-profiles-manager", Required = false, Default = false, HelpText = "Enable skips the Profiles Manager popup during gameplay. Select the desired profile before starting the game")]
public bool SkipUserProfilesManager { get; set; } public bool SkipUserProfilesManager { get; set; }
// Debug
[Option("enable-gdb-stub", Required = false, Default = false, HelpText = "Enables the GDB stub so that a developer can attach a debugger to the emulated process.")]
public bool EnableGdbStub { get; set; }
[Option("gdb-stub-port", Required = false, Default = 55555, HelpText = "Specifies which TCP port the GDB stub listens on.")]
public ushort GdbStubPort { get; set; }
[Option("suspend-on-start", Required = false, Default = false, HelpText = "Suspend execution when starting an application.")]
public bool DebuggerSuspendOnStart { get; set; }
// Values // Values
[Value(0, MetaName = "input", HelpText = "Input to load.", Required = true)] [Value(0, MetaName = "input", HelpText = "Input to load.", Required = true)]

View File

@ -65,8 +65,6 @@
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" /> <PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" /> <PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'" /> <PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64' AND '$(RuntimeIdentifier)' != 'win-arm64'" />
<PackageReference Include="Ryujinx.UpdateClient" />
<PackageReference Include="Ryujinx.Systems.Update.Common" />
<PackageReference Include="securifybv.ShellLink" /> <PackageReference Include="securifybv.ShellLink" />
<PackageReference Include="Sep" /> <PackageReference Include="Sep" />
<PackageReference Include="Silk.NET.Vulkan" /> <PackageReference Include="Silk.NET.Vulkan" />

View File

@ -75,7 +75,6 @@ namespace Ryujinx.Ava.Systems
private readonly long _ticksPerFrame; private readonly long _ticksPerFrame;
private readonly Stopwatch _chrono; private readonly Stopwatch _chrono;
private readonly Stopwatch _playTimer;
private long _ticks; private long _ticks;
private readonly AccountManager _accountManager; private readonly AccountManager _accountManager;
@ -176,7 +175,6 @@ namespace Ryujinx.Ava.Systems
_chrono = new Stopwatch(); _chrono = new Stopwatch();
_ticksPerFrame = Stopwatch.Frequency / TargetFps; _ticksPerFrame = Stopwatch.Frequency / TargetFps;
_playTimer = new Stopwatch();
if (ApplicationPath.StartsWith("@SystemContent")) if (ApplicationPath.StartsWith("@SystemContent"))
{ {
@ -218,10 +216,6 @@ namespace Ryujinx.Ava.Systems
ConfigurationState.Instance.Multiplayer.LdnServer.Event += UpdateLdnServerState; ConfigurationState.Instance.Multiplayer.LdnServer.Event += UpdateLdnServerState;
ConfigurationState.Instance.Multiplayer.DisableP2p.Event += UpdateDisableP2pState; ConfigurationState.Instance.Multiplayer.DisableP2p.Event += UpdateDisableP2pState;
ConfigurationState.Instance.Debug.EnableGdbStub.Event += UpdateEnableGdbStubState;
ConfigurationState.Instance.Debug.GdbStubPort.Event += UpdateGdbStubPortState;
ConfigurationState.Instance.Debug.DebuggerSuspendOnStart.Event += UpdateDebuggerSuspendOnStartState;
_gpuCancellationTokenSource = new CancellationTokenSource(); _gpuCancellationTokenSource = new CancellationTokenSource();
_gpuDoneEvent = new ManualResetEvent(false); _gpuDoneEvent = new ManualResetEvent(false);
} }
@ -568,25 +562,9 @@ namespace Ryujinx.Ava.Systems
Device.Configuration.MultiplayerDisableP2p = e.NewValue; Device.Configuration.MultiplayerDisableP2p = e.NewValue;
} }
private void UpdateEnableGdbStubState(object sender, ReactiveEventArgs<bool> e)
{
Device.Configuration.EnableGdbStub = e.NewValue;
}
private void UpdateGdbStubPortState(object sender, ReactiveEventArgs<ushort> e)
{
Device.Configuration.GdbStubPort = e.NewValue;
}
private void UpdateDebuggerSuspendOnStartState(object sender, ReactiveEventArgs<bool> e)
{
Device.Configuration.DebuggerSuspendOnStart = e.NewValue;
}
public void Stop() public void Stop()
{ {
_isActive = false; _isActive = false;
_playTimer.Stop();
} }
private void Exit() private void Exit()
@ -638,7 +616,7 @@ namespace Ryujinx.Ava.Systems
private void Dispose() private void Dispose()
{ {
if (Device.Processes != null) if (Device.Processes != null)
MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText, _playTimer.Elapsed); MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText);
ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState; ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState;
ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState; ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState;
@ -657,7 +635,6 @@ namespace Ryujinx.Ava.Systems
_gpuCancellationTokenSource.Dispose(); _gpuCancellationTokenSource.Dispose();
_chrono.Stop(); _chrono.Stop();
_playTimer.Stop();
} }
public void DisposeGpu() public void DisposeGpu()
@ -891,7 +868,6 @@ namespace Ryujinx.Ava.Systems
ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText, ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
appMetadata => appMetadata.UpdatePreGame() appMetadata => appMetadata.UpdatePreGame()
); );
_playTimer.Start();
return true; return true;
} }
@ -901,7 +877,6 @@ namespace Ryujinx.Ava.Systems
Device?.System.TogglePauseEmulation(false); Device?.System.TogglePauseEmulation(false);
_viewModel.IsPaused = false; _viewModel.IsPaused = false;
_playTimer.Start();
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI); _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed"); Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
} }
@ -911,7 +886,6 @@ namespace Ryujinx.Ava.Systems
Device?.System.TogglePauseEmulation(true); Device?.System.TogglePauseEmulation(true);
_viewModel.IsPaused = true; _viewModel.IsPaused = true;
_playTimer.Stop();
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]); _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]);
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused"); Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
} }

View File

@ -33,11 +33,19 @@ namespace Ryujinx.Ava.Systems.AppLibrary
/// <summary> /// <summary>
/// Updates <see cref="LastPlayed"/> and <see cref="TimePlayed"/>. Call this after a game ends. /// Updates <see cref="LastPlayed"/> and <see cref="TimePlayed"/>. Call this after a game ends.
/// </summary> /// </summary>
/// <param name="playTime">The active gameplay time this past session.</param> public void UpdatePostGame()
public void UpdatePostGame(TimeSpan playTime)
{ {
DateTime? prevLastPlayed = LastPlayed;
UpdatePreGame(); UpdatePreGame();
TimePlayed += playTime;
if (!prevLastPlayed.HasValue)
{
return;
}
TimeSpan diff = DateTime.UtcNow - prevLastPlayed.Value;
double newTotalSeconds = TimePlayed.Add(diff).TotalSeconds;
TimePlayed = TimeSpan.FromSeconds(Math.Round(newTotalSeconds, MidpointRounding.AwayFromZero));
} }
} }
} }

View File

@ -464,21 +464,6 @@ namespace Ryujinx.Ava.Systems.Configuration
/// </summary> /// </summary>
public bool UseHypervisor { get; set; } public bool UseHypervisor { get; set; }
/// <summary>
/// Enables or disables the GDB stub
/// </summary>
public bool EnableGdbStub { get; set; }
/// <summary>
/// Which TCP port should the GDB stub listen on
/// </summary>
public ushort GdbStubPort { get; set; }
/// <summary>
/// Suspend execution when starting an application
/// </summary>
public bool DebuggerSuspendOnStart { get; set; }
/// <summary> /// <summary>
/// Show toggles for dirty hacks in the UI. /// Show toggles for dirty hacks in the UI.
/// </summary> /// </summary>

View File

@ -156,10 +156,6 @@ namespace Ryujinx.Ava.Systems.Configuration
Multiplayer.LdnPassphrase.Value = cff.MultiplayerLdnPassphrase; Multiplayer.LdnPassphrase.Value = cff.MultiplayerLdnPassphrase;
Multiplayer.LdnServer.Value = cff.LdnServer; Multiplayer.LdnServer.Value = cff.LdnServer;
Debug.EnableGdbStub.Value = shouldLoadFromFile ? cff.EnableGdbStub : Debug.EnableGdbStub.Value; // Get from global config only
Debug.GdbStubPort.Value = shouldLoadFromFile ? cff.GdbStubPort : Debug.GdbStubPort.Value; // Get from global config only
Debug.DebuggerSuspendOnStart.Value = shouldLoadFromFile ? cff.DebuggerSuspendOnStart : Debug.DebuggerSuspendOnStart.Value; // Get from global config only
{ {
Hacks.ShowDirtyHacks.Value = shouldLoadFromFile ? cff.ShowDirtyHacks : Hacks.ShowDirtyHacks.Value; // Get from global config only Hacks.ShowDirtyHacks.Value = shouldLoadFromFile ? cff.ShowDirtyHacks : Hacks.ShowDirtyHacks.Value; // Get from global config only

View File

@ -703,37 +703,6 @@ namespace Ryujinx.Ava.Systems.Configuration
} }
} }
/// <summary>
/// Debug configuration section
/// </summary>
public class DebugSection
{
/// <summary>
/// Enables or disables the GDB stub
/// </summary>
public ReactiveObject<bool> EnableGdbStub { get; private set; }
/// <summary>
/// Which TCP port should the GDB stub listen on
/// </summary>
public ReactiveObject<ushort> GdbStubPort { get; private set; }
/// <summary>
/// Suspend execution when starting an application
/// </summary>
public ReactiveObject<bool> DebuggerSuspendOnStart { get; private set; }
public DebugSection()
{
EnableGdbStub = new ReactiveObject<bool>();
EnableGdbStub.LogChangesToValue(nameof(EnableGdbStub));
GdbStubPort = new ReactiveObject<ushort>();
GdbStubPort.LogChangesToValue(nameof(GdbStubPort));
DebuggerSuspendOnStart = new ReactiveObject<bool>();
DebuggerSuspendOnStart.LogChangesToValue(nameof(DebuggerSuspendOnStart));
}
}
public class HacksSection public class HacksSection
{ {
/// <summary> /// <summary>
@ -832,11 +801,6 @@ namespace Ryujinx.Ava.Systems.Configuration
/// </summary> /// </summary>
public MultiplayerSection Multiplayer { get; private set; } public MultiplayerSection Multiplayer { get; private set; }
/// <summary>
/// The Debug
/// </summary>
public DebugSection Debug { get; private set; }
/// <summary> /// <summary>
/// The Dirty Hacks section /// The Dirty Hacks section
/// </summary> /// </summary>
@ -890,7 +854,6 @@ namespace Ryujinx.Ava.Systems.Configuration
Graphics = new GraphicsSection(); Graphics = new GraphicsSection();
Hid = new HidSection(); Hid = new HidSection();
Multiplayer = new MultiplayerSection(); Multiplayer = new MultiplayerSection();
Debug = new DebugSection();
Hacks = new HacksSection(); Hacks = new HacksSection();
UpdateCheckerType = new ReactiveObject<UpdaterType>(); UpdateCheckerType = new ReactiveObject<UpdaterType>();
FocusLostActionType = new ReactiveObject<FocusLostType>(); FocusLostActionType = new ReactiveObject<FocusLostType>();
@ -930,9 +893,6 @@ namespace Ryujinx.Ava.Systems.Configuration
Multiplayer.DisableP2p, Multiplayer.DisableP2p,
Multiplayer.LdnPassphrase, Multiplayer.LdnPassphrase,
Multiplayer.GetLdnServer(), Multiplayer.GetLdnServer(),
Debug.EnableGdbStub,
Debug.GdbStubPort,
Debug.DebuggerSuspendOnStart,
Graphics.CustomVSyncInterval, Graphics.CustomVSyncInterval,
Hacks.ShowDirtyHacks ? Hacks.EnabledHacks : null); Hacks.ShowDirtyHacks ? Hacks.EnabledHacks : null);
} }

View File

@ -147,9 +147,6 @@ namespace Ryujinx.Ava.Systems.Configuration
MultiplayerDisableP2p = Multiplayer.DisableP2p, MultiplayerDisableP2p = Multiplayer.DisableP2p,
MultiplayerLdnPassphrase = Multiplayer.LdnPassphrase, MultiplayerLdnPassphrase = Multiplayer.LdnPassphrase,
LdnServer = Multiplayer.LdnServer, LdnServer = Multiplayer.LdnServer,
EnableGdbStub = Debug.EnableGdbStub,
GdbStubPort = Debug.GdbStubPort,
DebuggerSuspendOnStart = Debug.DebuggerSuspendOnStart,
ShowDirtyHacks = Hacks.ShowDirtyHacks, ShowDirtyHacks = Hacks.ShowDirtyHacks,
DirtyHacks = Hacks.EnabledHacks.Select(it => it.Pack()).ToArray(), DirtyHacks = Hacks.EnabledHacks.Select(it => it.Pack()).ToArray(),
}; };
@ -327,9 +324,6 @@ namespace Ryujinx.Ava.Systems.Configuration
}, },
} }
]; ];
Debug.EnableGdbStub.Value = false;
Debug.GdbStubPort.Value = 55555;
Debug.DebuggerSuspendOnStart.Value = false;
} }
private static GraphicsBackend DefaultGraphicsBackend() private static GraphicsBackend DefaultGraphicsBackend()

View File

@ -4,26 +4,42 @@ using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Systems.Update.Client;
using Ryujinx.Systems.Update.Common;
using System; using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Runtime.InteropServices;
using System.Text.Json.Serialization;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.Systems namespace Ryujinx.Ava.Systems
{ {
internal static partial class Updater internal static partial class Updater
{ {
private static VersionResponse _versionResponse; private static string CreateUpdateQueryUrl()
{
#pragma warning disable CS8524
var os = RunningPlatform.CurrentOS switch
#pragma warning restore CS8524
{
OperatingSystemType.MacOS => "mac",
OperatingSystemType.Linux => "linux",
OperatingSystemType.Windows => "win"
};
private static UpdateClient CreateUpdateClient() var arch = RunningPlatform.Architecture switch
=> UpdateClient.Builder() {
.WithServerEndpoint("https://update.ryujinx.app") // This is the default, and doesn't need to be provided; it's here for transparency. Architecture.Arm64 => "arm",
.WithLogger((format, args, caller) => Architecture.X64 => "amd64",
Logger.Info?.Print( _ => null
LogClass.Application, };
args.Length is 0 ? format : format.Format(args),
caller: caller) if (arch is null)
); return null;
var rc = ReleaseInformation.IsCanaryBuild ? "canary" : "stable";
return $"https://update.ryujinx.app/latest/query?os={os}&arch={arch}&rc={rc}";
}
public static async Task<Optional<(Version Current, Version Incoming)>> CheckVersionAsync(bool showVersionUpToDate = false) public static async Task<Optional<(Version Current, Version Incoming)>> CheckVersionAsync(bool showVersionUpToDate = false)
{ {
@ -41,31 +57,39 @@ namespace Ryujinx.Ava.Systems
return default; return default;
} }
using UpdateClient updateClient = CreateUpdateClient(); if (CreateUpdateQueryUrl() is not {} updateUrl)
try
{ {
_versionResponse = await updateClient.QueryLatestAsync(ReleaseInformation.IsCanaryBuild Logger.Error?.Print(LogClass.Application, "Could not determine URL for updates.");
? ReleaseChannel.Canary
: ReleaseChannel.Stable);
}
catch (Exception e)
{
Logger.Error?.Print(LogClass.Application, $"An error occurred when requesting for updates ({e.GetType().AsFullNamePrettyString()}): {e.Message}");
_running = false; _running = false;
return default; return default;
} }
if (_versionResponse == null) Logger.Info?.Print(LogClass.Application, $"Checking for updates from {updateUrl}.");
// Get latest version number from update.ryujinx.app API
using HttpClient jsonClient = ConstructHttpClient();
try
{ {
// logging is done via the UpdateClient library UpdaterResponse response =
await jsonClient.GetFromJsonAsync(updateUrl, UpdaterResponseJsonContext.Default.UpdaterResponse);
_buildVer = response.Tag;
_buildUrl = response.DownloadUrl;
_changelogUrlFormat = response.ReleaseUrlFormat;
}
catch (Exception e)
{
Logger.Error?.Print(LogClass.Application, $"An error occurred when parsing JSON response from API ({e.GetType().AsFullNamePrettyString()}): {e.Message}");
_running = false; _running = false;
return default; return default;
} }
// If build URL not found, assume no new update is available. // If build URL not found, assume no new update is available.
if (_versionResponse.ArtifactUrl is null or "") if (_buildUrl is null or "")
{ {
if (showVersionUpToDate) if (showVersionUpToDate)
{ {
@ -75,7 +99,7 @@ namespace Ryujinx.Ava.Systems
if (userResult is UserResult.Ok) if (userResult is UserResult.Ok)
{ {
OpenHelper.OpenUrl(_versionResponse.ReleaseUrlFormat.Format(currentVersion)); OpenHelper.OpenUrl(_changelogUrlFormat.Format(currentVersion));
} }
} }
@ -87,7 +111,7 @@ namespace Ryujinx.Ava.Systems
} }
if (!Version.TryParse(_versionResponse.Version, out Version newVersion)) if (!Version.TryParse(_buildVer, out Version newVersion))
{ {
Logger.Error?.Print(LogClass.Application, Logger.Error?.Print(LogClass.Application,
$"Failed to convert the received {RyujinxApp.FullAppName} version from the update server!"); $"Failed to convert the received {RyujinxApp.FullAppName} version from the update server!");
@ -103,5 +127,17 @@ namespace Ryujinx.Ava.Systems
return (currentVersion, newVersion); return (currentVersion, newVersion);
} }
[JsonSerializable(typeof(UpdaterResponse))]
partial class UpdaterResponseJsonContext : JsonSerializerContext;
public class UpdaterResponse
{
[JsonPropertyName("tag")] public string Tag { get; set; }
[JsonPropertyName("download_url")] public string DownloadUrl { get; set; }
[JsonPropertyName("web_url")] public string ReleaseUrl { get; set; }
[JsonIgnore] public string ReleaseUrlFormat => ReleaseUrl.Replace(Tag, "{0}");
}
} }
} }

View File

@ -5,11 +5,13 @@ using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar; using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models.Github;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Utilities;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -34,12 +36,16 @@ namespace Ryujinx.Ava.Systems
private static readonly string _updatePublishDir = Path.Combine(_updateDir, "publish"); private static readonly string _updatePublishDir = Path.Combine(_updateDir, "publish");
private const int ConnectionCount = 4; private const int ConnectionCount = 4;
private static string _buildVer;
private static string _buildUrl;
private static long _buildSize; private static long _buildSize;
private static bool _updateSuccessful; private static bool _updateSuccessful;
private static bool _running; private static bool _running;
private static readonly string[] _windowsDependencyDirs = []; private static readonly string[] _windowsDependencyDirs = [];
private static string _changelogUrlFormat = null;
public static async Task BeginUpdateAsync(bool showVersionUpToDate = false) public static async Task BeginUpdateAsync(bool showVersionUpToDate = false)
{ {
if (_running) if (_running)
@ -66,7 +72,7 @@ namespace Ryujinx.Ava.Systems
if (userResult is UserResult.Ok) if (userResult is UserResult.Ok)
{ {
OpenHelper.OpenUrl(_versionResponse.ReleaseUrlFormat.Format(currentVersion)); OpenHelper.OpenUrl(_changelogUrlFormat.Format(currentVersion));
} }
} }
@ -86,7 +92,7 @@ namespace Ryujinx.Ava.Systems
// GitLab instance is located in Ukraine. Connection times will vary across the world. // GitLab instance is located in Ukraine. Connection times will vary across the world.
buildSizeClient.Timeout = TimeSpan.FromSeconds(10); buildSizeClient.Timeout = TimeSpan.FromSeconds(10);
HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_versionResponse.ArtifactUrl), HttpCompletionOption.ResponseHeadersRead); HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead);
_buildSize = message.Content.Headers.ContentRange.Length.Value; _buildSize = message.Content.Headers.ContentRange.Length.Value;
} }
@ -116,7 +122,7 @@ namespace Ryujinx.Ava.Systems
switch (shouldUpdate) switch (shouldUpdate)
{ {
case UserResult.Yes: case UserResult.Yes:
await UpdateRyujinx(_versionResponse.ArtifactUrl); await UpdateRyujinx(_buildUrl);
break; break;
// Secondary button maps to no, which in this case is the show changelog button. // Secondary button maps to no, which in this case is the show changelog button.
case UserResult.No: case UserResult.No:

57
src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml Executable file → Normal file
View File

@ -14,7 +14,8 @@
Command="{Binding ToggleFavorite}" Command="{Binding ToggleFavorite}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuToggleFavorite}" Header="{ext:Locale GameListContextMenuToggleFavorite}"
Icon="{ext:Icon fa-solid fa-star}" /> Icon="{ext:Icon fa-solid fa-star}"
ToolTip.Tip="{ext:Locale GameListContextMenuToggleFavoriteToolTip}" />
<MenuItem <MenuItem
Command="{Binding CreateApplicationShortcut}" Command="{Binding CreateApplicationShortcut}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
@ -40,64 +41,71 @@
Command="{Binding OpenApplicationCompatibility}" Command="{Binding OpenApplicationCompatibility}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuShowCompatEntry}" Header="{ext:Locale GameListContextMenuShowCompatEntry}"
Icon="{ext:Icon fa-solid fa-database}" Icon="{ext:Icon mdi-gamepad}"
ToolTip.Tip="{ext:Locale GameListContextMenuShowCompatEntryToolTip}"/> ToolTip.Tip="{ext:Locale GameListContextMenuShowCompatEntryToolTip}"/>
<MenuItem <MenuItem
Command="{Binding OpenApplicationData}" Command="{Binding OpenApplicationData}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuShowGameData}" Header="{ext:Locale GameListContextMenuShowGameData}"
Icon="{ext:Icon fa-solid fa-chart-line}" /> Icon="{ext:Icon mdi-chart-line}"
ToolTip.Tip="{ext:Locale GameListContextMenuShowGameDataToolTip}"/>
<Separator /> <Separator />
<MenuItem <MenuItem
Command="{Binding OpenUserSaveDirectory}" Command="{Binding OpenUserSaveDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenUserSaveDirectory}" Header="{ext:Locale GameListContextMenuOpenUserSaveDirectory}"
Icon="{ext:Icon fa-solid fa-sd-card}" Icon="{ext:Icon mdi-folder-account}"
IsEnabled="{Binding OpenUserSaveDirectoryEnabled}" /> IsEnabled="{Binding OpenUserSaveDirectoryEnabled}"
ToolTip.Tip="{ext:Locale GameListContextMenuOpenUserSaveDirectoryToolTip}" />
<MenuItem <MenuItem
Command="{Binding OpenDeviceSaveDirectory}" Command="{Binding OpenDeviceSaveDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenDeviceSaveDirectory}" Header="{ext:Locale GameListContextMenuOpenDeviceSaveDirectory}"
Icon="{ext:Icon fa-solid fa-hard-drive}" IsEnabled="{Binding OpenDeviceSaveDirectoryEnabled}"
IsEnabled="{Binding OpenDeviceSaveDirectoryEnabled}" /> ToolTip.Tip="{ext:Locale GameListContextMenuOpenDeviceSaveDirectoryToolTip}" />
<MenuItem <MenuItem
Command="{Binding OpenBcatSaveDirectory}" Command="{Binding OpenBcatSaveDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenBcatSaveDirectory}" Header="{ext:Locale GameListContextMenuOpenBcatSaveDirectory}"
Icon="{ext:Icon fa-solid fa-box-archive}" IsEnabled="{Binding OpenBcatSaveDirectoryEnabled}"
IsEnabled="{Binding OpenBcatSaveDirectoryEnabled}" /> ToolTip.Tip="{ext:Locale GameListContextMenuOpenBcatSaveDirectoryToolTip}" />
<Separator /> <Separator />
<MenuItem <MenuItem
Command="{Binding OpenTitleUpdateManager}" Command="{Binding OpenTitleUpdateManager}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuManageTitleUpdates}" Header="{ext:Locale GameListContextMenuManageTitleUpdates}"
Icon="{ext:Icon fa-solid fa-code-compare}" /> Icon="{ext:Icon fa-solid fa-code-compare}"
ToolTip.Tip="{ext:Locale GameListContextMenuManageTitleUpdatesToolTip}" />
<MenuItem <MenuItem
Command="{Binding OpenDownloadableContentManager}" Command="{Binding OpenDownloadableContentManager}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuManageDlc}" Header="{ext:Locale GameListContextMenuManageDlc}"
Icon="{ext:Icon fa-solid fa-download}" /> Icon="{ext:Icon fa-solid fa-download}"
ToolTip.Tip="{ext:Locale GameListContextMenuManageDlcToolTip}" />
<MenuItem <MenuItem
Command="{Binding OpenCheatManager}" Command="{Binding OpenCheatManager}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuManageCheat}" Header="{ext:Locale GameListContextMenuManageCheat}"
Icon="{ext:Icon fa-solid fa-code}" /> Icon="{ext:Icon fa-solid fa-code}"
ToolTip.Tip="{ext:Locale GameListContextMenuManageCheatToolTip}" />
<MenuItem <MenuItem
Command="{Binding OpenModManager}" Command="{Binding OpenModManager}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuManageMod}" Header="{ext:Locale GameListContextMenuManageMod}"
Icon="{ext:Icon fa-solid fa-sliders}" /> Icon="{ext:Icon mdi-view-module}"
ToolTip.Tip="{ext:Locale GameListContextMenuManageModToolTip}" />
<Separator /> <Separator />
<MenuItem <MenuItem
Command="{Binding OpenModsDirectory}" Command="{Binding OpenModsDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenModsDirectory}" Header="{ext:Locale GameListContextMenuOpenModsDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" /> Icon="{ext:Icon mdi-folder-file}"
ToolTip.Tip="{ext:Locale GameListContextMenuOpenModsDirectoryToolTip}" />
<MenuItem <MenuItem
Command="{Binding OpenSdModsDirectory}" Command="{Binding OpenSdModsDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenSdModsDirectory}" Header="{ext:Locale GameListContextMenuOpenSdModsDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" Icon="{ext:Icon mdi-folder-file}"
ToolTip.Tip="{ext:Locale GameListContextMenuOpenSdModsDirectoryToolTip}" /> ToolTip.Tip="{ext:Locale GameListContextMenuOpenSdModsDirectoryToolTip}" />
<Separator /> <Separator />
<MenuItem <MenuItem
@ -105,37 +113,40 @@
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuTrimXCI}" Header="{ext:Locale GameListContextMenuTrimXCI}"
IsEnabled="{Binding TrimXCIEnabled}" IsEnabled="{Binding TrimXCIEnabled}"
Icon="{ext:Icon fa-solid fa-scissors}"
ToolTip.Tip="{ext:Locale GameListContextMenuTrimXCIToolTip}" /> ToolTip.Tip="{ext:Locale GameListContextMenuTrimXCIToolTip}" />
<MenuItem Header="{ext:Locale GameListContextMenuCacheManagement}" Icon="{ext:Icon fa-solid fa-memory}"> <MenuItem Header="{ext:Locale GameListContextMenuCacheManagement}" Icon="{ext:Icon mdi-cached}">
<MenuItem <MenuItem
Command="{Binding PurgePtcCache}" Command="{Binding PurgePtcCache}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuCacheManagementPurgePptc}" Header="{ext:Locale GameListContextMenuCacheManagementPurgePptc}"
Icon="{ext:Icon fa-solid fa-arrow-rotate-right}" Icon="{ext:Icon mdi-refresh}"
ToolTip.Tip="{ext:Locale GameListContextMenuCacheManagementPurgePptcToolTip}" /> ToolTip.Tip="{ext:Locale GameListContextMenuCacheManagementPurgePptcToolTip}" />
<MenuItem <MenuItem
Command="{Binding NukePtcCache}" Command="{Binding NukePtcCache}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuCacheManagementNukePptc}" Header="{ext:Locale GameListContextMenuCacheManagementNukePptc}"
Icon="{ext:Icon fa-solid fa-trash-can}" /> Icon="{ext:Icon mdi-delete-alert}"
ToolTip.Tip="{ext:Locale GameListContextMenuCacheManagementNukePptcToolTip}" />
<MenuItem <MenuItem
Command="{Binding PurgeShaderCache}" Command="{Binding PurgeShaderCache}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuCacheManagementPurgeShaderCache}" Header="{ext:Locale GameListContextMenuCacheManagementPurgeShaderCache}"
Icon="{ext:Icon fa-solid fa-trash-can}" /> Icon="{ext:Icon mdi-delete-alert}"
ToolTip.Tip="{ext:Locale GameListContextMenuCacheManagementPurgeShaderCacheToolTip}" />
<MenuItem <MenuItem
Command="{Binding OpenPtcDirectory}" Command="{Binding OpenPtcDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuCacheManagementOpenPptcDirectory}" Header="{ext:Locale GameListContextMenuCacheManagementOpenPptcDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" /> Icon="{ext:Icon mdi-folder-arrow-up-down}"
ToolTip.Tip="{ext:Locale GameListContextMenuCacheManagementOpenPptcDirectoryToolTip}" />
<MenuItem <MenuItem
Command="{Binding OpenShaderCacheDirectory}" Command="{Binding OpenShaderCacheDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuCacheManagementOpenShaderCacheDirectory}" Header="{ext:Locale GameListContextMenuCacheManagementOpenShaderCacheDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" /> Icon="{ext:Icon mdi-folder-arrow-up-down}"
ToolTip.Tip="{ext:Locale GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip}" />
</MenuItem> </MenuItem>
<MenuItem Header="{ext:Locale GameListContextMenuExtractData}" Icon="{ext:Icon fa-solid fa-file-export}"> <MenuItem Header="{ext:Locale GameListContextMenuExtractData}">
<MenuItem <MenuItem
Command="{Binding ExtractApplicationExeFs}" Command="{Binding ExtractApplicationExeFs}"
CommandParameter="{Binding}" CommandParameter="{Binding}"

View File

@ -310,15 +310,10 @@ namespace Ryujinx.Ava.UI.ViewModels
private void TotalTimePlayed_Recalculated(Optional<TimeSpan> ts) private void TotalTimePlayed_Recalculated(Optional<TimeSpan> ts)
{ {
if (ts.HasValue)
{
var formattedPlayTime = ValueFormatUtils.FormatTimeSpan(ts.Value);
LocaleManager.Instance.SetDynamicValues(LocaleKeys.GameListLabelTotalTimePlayed, formattedPlayTime);
ShowTotalTimePlayed = formattedPlayTime != string.Empty;
return;
}
ShowTotalTimePlayed = ts.HasValue; ShowTotalTimePlayed = ts.HasValue;
if (ts.HasValue)
LocaleManager.Instance.SetDynamicValues(LocaleKeys.GameListLabelTotalTimePlayed, ValueFormatUtils.FormatTimeSpan(ts.Value));
} }
public bool ShowTotalTimePlayed public bool ShowTotalTimePlayed
@ -339,6 +334,7 @@ namespace Ryujinx.Ava.UI.ViewModels
_listSelectedApplication = value; _listSelectedApplication = value;
if (_listSelectedApplication != null && ListAppContextMenu == null) if (_listSelectedApplication != null && ListAppContextMenu == null)
ListAppContextMenu = new ApplicationContextMenu(); ListAppContextMenu = new ApplicationContextMenu();
else if (_listSelectedApplication == null && ListAppContextMenu != null) else if (_listSelectedApplication == null && ListAppContextMenu != null)
ListAppContextMenu = null!; ListAppContextMenu = null!;
@ -1692,8 +1688,8 @@ namespace Ryujinx.Ava.UI.ViewModels
RendererHostControl.Focus(); RendererHostControl.Focus();
}); });
public static void UpdateGameMetadata(string titleId, TimeSpan playTime) public static void UpdateGameMetadata(string titleId)
=> ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => appMetadata.UpdatePostGame(playTime)); => ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => appMetadata.UpdatePostGame());
public void RefreshFirmwareStatus() public void RefreshFirmwareStatus()
{ {

View File

@ -71,10 +71,6 @@ namespace Ryujinx.Ava.UI.ViewModels
private string _ldnPassphrase; private string _ldnPassphrase;
[ObservableProperty] private string _ldnServer; [ObservableProperty] private string _ldnServer;
private bool _enableGDBStub;
private ushort _gdbStubPort;
private bool _debuggerSuspendOnStart;
public SettingsHacksViewModel DirtyHacks { get; } public SettingsHacksViewModel DirtyHacks { get; }
private readonly bool _isGameRunning; private readonly bool _isGameRunning;
@ -391,36 +387,6 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool IsInvalidLdnPassphraseVisible { get; set; } public bool IsInvalidLdnPassphraseVisible { get; set; }
public bool EnableGdbStub
{
get => _enableGDBStub;
set
{
_enableGDBStub = value;
ConfigurationState.Instance.Debug.EnableGdbStub.Value = _enableGDBStub;
}
}
public ushort GDBStubPort
{
get => _gdbStubPort;
set
{
_gdbStubPort = value;
ConfigurationState.Instance.Debug.GdbStubPort.Value = _gdbStubPort;
}
}
public bool DebuggerSuspendOnStart
{
get => _debuggerSuspendOnStart;
set
{
_debuggerSuspendOnStart = value;
ConfigurationState.Instance.Debug.DebuggerSuspendOnStart.Value = _debuggerSuspendOnStart;
}
}
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this() public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
{ {
_virtualFileSystem = virtualFileSystem; _virtualFileSystem = virtualFileSystem;
@ -714,16 +680,10 @@ namespace Ryujinx.Ava.UI.ViewModels
FsGlobalAccessLogMode = config.System.FsGlobalAccessLogMode; FsGlobalAccessLogMode = config.System.FsGlobalAccessLogMode;
OpenglDebugLevel = (int)config.Logger.GraphicsDebugLevel.Value; OpenglDebugLevel = (int)config.Logger.GraphicsDebugLevel.Value;
// Multiplayer
MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value; MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value;
DisableP2P = config.Multiplayer.DisableP2p; DisableP2P = config.Multiplayer.DisableP2p;
LdnPassphrase = config.Multiplayer.LdnPassphrase; LdnPassphrase = config.Multiplayer.LdnPassphrase;
LdnServer = config.Multiplayer.LdnServer; LdnServer = config.Multiplayer.LdnServer;
// Debug
EnableGdbStub = config.Debug.EnableGdbStub.Value;
GDBStubPort = config.Debug.GdbStubPort.Value;
DebuggerSuspendOnStart = config.Debug.DebuggerSuspendOnStart.Value;
} }
public void SaveSettings(bool global = false) public void SaveSettings(bool global = false)
@ -840,18 +800,12 @@ namespace Ryujinx.Ava.UI.ViewModels
config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode; config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode;
config.Logger.GraphicsDebugLevel.Value = (GraphicsDebugLevel)OpenglDebugLevel; config.Logger.GraphicsDebugLevel.Value = (GraphicsDebugLevel)OpenglDebugLevel;
// Multiplayer
config.Multiplayer.LanInterfaceId.Value = _networkInterfaces[NetworkInterfaceList[NetworkInterfaceIndex]]; config.Multiplayer.LanInterfaceId.Value = _networkInterfaces[NetworkInterfaceList[NetworkInterfaceIndex]];
config.Multiplayer.Mode.Value = (MultiplayerMode)MultiplayerModeIndex; config.Multiplayer.Mode.Value = (MultiplayerMode)MultiplayerModeIndex;
config.Multiplayer.DisableP2p.Value = DisableP2P; config.Multiplayer.DisableP2p.Value = DisableP2P;
config.Multiplayer.LdnPassphrase.Value = LdnPassphrase; config.Multiplayer.LdnPassphrase.Value = LdnPassphrase;
config.Multiplayer.LdnServer.Value = LdnServer; config.Multiplayer.LdnServer.Value = LdnServer;
// Debug
config.Debug.EnableGdbStub.Value = EnableGdbStub;
config.Debug.GdbStubPort.Value = GDBStubPort;
config.Debug.DebuggerSuspendOnStart.Value = DebuggerSuspendOnStart;
// Dirty Hacks // Dirty Hacks
config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix; config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix;
config.Hacks.DisableNifmIsAnyInternetRequestAccepted.Value = config.Hacks.DisableNifmIsAnyInternetRequestAccepted.Value =

68
src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml Executable file → Normal file
View File

@ -32,23 +32,27 @@
Command="{Binding OpenFile}" Command="{Binding OpenFile}"
Header="{ext:Locale MenuBarFileOpenFromFile}" Header="{ext:Locale MenuBarFileOpenFromFile}"
Icon="{ext:Icon fa-solid fa-file}" Icon="{ext:Icon fa-solid fa-file}"
IsEnabled="{Binding EnableNonGameRunningControls}" /> IsEnabled="{Binding EnableNonGameRunningControls}"
ToolTip.Tip="{ext:Locale LoadApplicationFileTooltip}" />
<MenuItem <MenuItem
Command="{Binding OpenFolder}" Command="{Binding OpenFolder}"
Header="{ext:Locale MenuBarFileOpenUnpacked}" Header="{ext:Locale MenuBarFileOpenUnpacked}"
Icon="{ext:Icon fa-solid fa-folder-open}" Icon="{ext:Icon fa-solid fa-folder}"
IsEnabled="{Binding EnableNonGameRunningControls}" /> IsEnabled="{Binding EnableNonGameRunningControls}"
ToolTip.Tip="{ext:Locale LoadApplicationFolderTooltip}" />
<MenuItem <MenuItem
Command="{Binding LoadDlcFromFolder}" Command="{Binding LoadDlcFromFolder}"
Header="{ext:Locale MenuBarFileLoadDlcFromFolder}" Header="{ext:Locale MenuBarFileLoadDlcFromFolder}"
Icon="{ext:Icon fa-solid fa-download}" Icon="{ext:Icon fa-solid fa-download}"
IsEnabled="{Binding EnableNonGameRunningControls}" /> IsEnabled="{Binding EnableNonGameRunningControls}"
ToolTip.Tip="{ext:Locale LoadDlcFromFolderTooltip}" />
<MenuItem <MenuItem
Command="{Binding LoadTitleUpdatesFromFolder}" Command="{Binding LoadTitleUpdatesFromFolder}"
Header="{ext:Locale MenuBarFileLoadTitleUpdatesFromFolder}" Header="{ext:Locale MenuBarFileLoadTitleUpdatesFromFolder}"
Icon="{ext:Icon fa-solid fa-code-compare}" Icon="{ext:Icon fa-solid fa-code-compare}"
IsEnabled="{Binding EnableNonGameRunningControls}" /> IsEnabled="{Binding EnableNonGameRunningControls}"
<MenuItem Header="{ext:Locale MenuBarFileOpenApplet}" IsEnabled="{Binding IsAppletMenuActive}" Icon="{ext:Icon fa-solid fa-microchip}"> ToolTip.Tip="{ext:Locale LoadTitleUpdatesFromFolderTooltip}" />
<MenuItem Header="{ext:Locale MenuBarFileOpenApplet}" IsEnabled="{Binding IsAppletMenuActive}" Icon="{ext:Icon mdi-launch}">
<MenuItem <MenuItem
Name="MiiAppletMenuItem" Name="MiiAppletMenuItem"
Header="{ext:Locale MenuBarFileOpenAppletOpenMiiApplet}" Header="{ext:Locale MenuBarFileOpenAppletOpenMiiApplet}"
@ -59,20 +63,21 @@
<MenuItem <MenuItem
Command="{Binding OpenRyujinxFolder}" Command="{Binding OpenRyujinxFolder}"
Header="{ext:Locale MenuBarFileOpenEmuFolder}" Header="{ext:Locale MenuBarFileOpenEmuFolder}"
Icon="{ext:Icon fa-solid fa-folder-closed}" /> ToolTip.Tip="{ext:Locale OpenRyujinxFolderTooltip}" />
<MenuItem <MenuItem
Command="{Binding OpenScreenshotsFolder}" Command="{Binding OpenScreenshotsFolder}"
Header="{ext:Locale MenuBarFileOpenScreenshotsFolder}" Header="{ext:Locale MenuBarFileOpenScreenshotsFolder}"
Icon="{ext:Icon fa-solid fa-desktop}" /> ToolTip.Tip="{ext:Locale OpenScreenshotFolderTooltip}"/>
<MenuItem <MenuItem
Command="{Binding OpenLogsFolder}" Command="{Binding OpenLogsFolder}"
Header="{ext:Locale MenuBarFileOpenLogsFolder}" Header="{ext:Locale MenuBarFileOpenLogsFolder}"
Icon="{ext:Icon fa-solid fa-file-lines}" /> ToolTip.Tip="{ext:Locale OpenRyujinxLogsTooltip}" />
<Separator /> <Separator />
<MenuItem <MenuItem
Name="CloseRyujinxMenuItem" Name="CloseRyujinxMenuItem"
Header="{ext:Locale MenuBarFileExit}" Header="{ext:Locale MenuBarFileExit}"
Icon="{ext:Icon fa-solid fa-power-off}" /> Icon="{ext:Icon fa-solid fa-xmark}"
ToolTip.Tip="{ext:Locale ExitTooltip}" />
</MenuItem> </MenuItem>
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarOptions}"> <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarOptions}">
<MenuItem <MenuItem
@ -128,7 +133,7 @@
Name="ChangeLanguageMenuItem" Name="ChangeLanguageMenuItem"
Padding="0" Padding="0"
Header="{ext:Locale MenuBarOptionsChangeLanguage}" Header="{ext:Locale MenuBarOptionsChangeLanguage}"
Icon="{ext:Icon fa-solid fa-globe}" Icon="{ext:Icon fa-solid fa-language}"
Classes="withCheckbox"> Classes="withCheckbox">
</MenuItem> </MenuItem>
<MenuItem <MenuItem
@ -141,14 +146,16 @@
Padding="0" Padding="0"
Header="{ext:Locale MenuBarOptionsSettings}" Header="{ext:Locale MenuBarOptionsSettings}"
Icon="{ext:Icon fa-solid fa-gear}" Icon="{ext:Icon fa-solid fa-gear}"
ToolTip.Tip="{ext:Locale OpenSettingsTooltip}"
Classes="withCheckbox"> Classes="withCheckbox">
</MenuItem> </MenuItem>
<MenuItem <MenuItem
Command="{Binding ManageProfiles}" Command="{Binding ManageProfiles}"
Padding="0" Padding="0"
Header="{ext:Locale MenuBarOptionsManageUserProfiles}" Header="{ext:Locale MenuBarOptionsManageUserProfiles}"
Icon="{ext:Icon fa-solid fa-user}" Icon="{ext:Icon mdi-account}"
IsEnabled="{Binding EnableNonGameRunningControls}" IsEnabled="{Binding EnableNonGameRunningControls}"
ToolTip.Tip="{ext:Locale OpenProfileManagerTooltip}"
Classes="withCheckbox"> Classes="withCheckbox">
</MenuItem> </MenuItem>
</MenuItem> </MenuItem>
@ -176,34 +183,35 @@
Header="{ext:Locale MenuBarOptionsStopEmulation}" Header="{ext:Locale MenuBarOptionsStopEmulation}"
Icon="{ext:Icon fa-solid fa-stop}" Icon="{ext:Icon fa-solid fa-stop}"
InputGesture="Escape" InputGesture="Escape"
IsEnabled="{Binding IsGameRunning}" /> IsEnabled="{Binding IsGameRunning}"
<MenuItem Command="{Binding SimulateWakeUpMessage}" Header="{ext:Locale MenuBarOptionsSimulateWakeUpMessage}" Icon="{ext:Icon fa-solid fa-sun}" /> ToolTip.Tip="{ext:Locale StopEmulationTooltip}" />
<MenuItem Command="{Binding SimulateWakeUpMessage}" Header="{ext:Locale MenuBarOptionsSimulateWakeUpMessage}" />
<Separator /> <Separator />
<MenuItem <MenuItem
Command="{Binding OpenAmiiboWindow}" Command="{Binding OpenAmiiboWindow}"
AttachedToVisualTree="ScanAmiiboMenuItem_AttachedToVisualTree" AttachedToVisualTree="ScanAmiiboMenuItem_AttachedToVisualTree"
Header="{ext:Locale MenuBarActionsScanAmiibo}" Header="{ext:Locale MenuBarActionsScanAmiibo}"
Icon="{ext:Icon fa-solid fa-cube}" Icon="{ext:Icon mdi-cube-scan}"
InputGesture="Ctrl + A" InputGesture="Ctrl + A"
IsEnabled="{Binding IsAmiiboRequested}" /> IsEnabled="{Binding IsAmiiboRequested}" />
<MenuItem <MenuItem
Command="{Binding OpenBinFile}" Command="{Binding OpenBinFile}"
AttachedToVisualTree="ScanBinAmiiboMenuItem_AttachedToVisualTree" AttachedToVisualTree="ScanBinAmiiboMenuItem_AttachedToVisualTree"
Header="{ext:Locale MenuBarActionsScanAmiiboBin}" Header="{ext:Locale MenuBarActionsScanAmiiboBin}"
Icon="{ext:Icon fa-solid fa-cube}" Icon="{ext:Icon mdi-cube-scan}"
IsVisible="{Binding CanScanAmiiboBinaries}" IsVisible="{Binding CanScanAmiiboBinaries}"
InputGesture="Ctrl + B" InputGesture="Ctrl + B"
IsEnabled="{Binding IsAmiiboBinRequested}" /> IsEnabled="{Binding IsAmiiboBinRequested}" />
<MenuItem <MenuItem
Command="{Binding TakeScreenshot}" Command="{Binding TakeScreenshot}"
Header="{ext:Locale MenuBarFileToolsTakeScreenshot}" Header="{ext:Locale MenuBarFileToolsTakeScreenshot}"
Icon="{ext:Icon fa-solid fa-camera}" Icon="{ext:Icon mdi-monitor-screenshot}"
InputGesture="{Binding ScreenshotKey}" InputGesture="{Binding ScreenshotKey}"
IsEnabled="{Binding IsGameRunning}" /> IsEnabled="{Binding IsGameRunning}" />
<MenuItem <MenuItem
Command="{Binding HideUi}" Command="{Binding HideUi}"
Header="{ext:Locale MenuBarFileToolsHideUi}" Header="{ext:Locale MenuBarFileToolsHideUi}"
Icon="{ext:Icon fa-solid fa-eye-slash}" Icon="{ext:Icon mdi-eye-off}"
InputGesture="{Binding ShowUiKey}" InputGesture="{Binding ShowUiKey}"
IsEnabled="{Binding IsGameRunning}" /> IsEnabled="{Binding IsGameRunning}" />
<MenuItem <MenuItem
@ -214,12 +222,12 @@
</MenuItem> </MenuItem>
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarActions}" IsVisible="{Binding EnableNonGameRunningControls}"> <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarActions}" IsVisible="{Binding EnableNonGameRunningControls}">
<MenuItem Header="{ext:Locale MenuBarActionsInstallKeys}" Icon="{ext:Icon fa-solid fa-key}"> <MenuItem Header="{ext:Locale MenuBarActionsInstallKeys}" Icon="{ext:Icon fa-solid fa-key}">
<MenuItem Command="{Binding InstallKeysFromFile}" Header="{ext:Locale MenuBarFileActionsInstallKeysFromFile}" Icon="{ext:Icon fa-solid fa-file-code}" /> <MenuItem Command="{Binding InstallKeysFromFile}" Header="{ext:Locale MenuBarFileActionsInstallKeysFromFile}" Icon="{ext:Icon mdi-file-cog}" />
<MenuItem Command="{Binding InstallKeysFromFolder}" Header="{ext:Locale MenuBarFileActionsInstallKeysFromFolder}" Icon="{ext:Icon fa-solid fa-folder-closed}" /> <MenuItem Command="{Binding InstallKeysFromFolder}" Header="{ext:Locale MenuBarFileActionsInstallKeysFromFolder}" Icon="{ext:Icon mdi-folder-cog}" />
</MenuItem> </MenuItem>
<MenuItem Header="{ext:Locale MenuBarActionsInstallFirmware}" Icon="{ext:Icon fa-solid fa-floppy-disk}"> <MenuItem Header="{ext:Locale MenuBarActionsInstallFirmware}" Icon="{ext:Icon fa-solid fa-download}">
<MenuItem Command="{Binding InstallFirmwareFromFile}" Header="{ext:Locale MenuBarActionsInstallFirmwareFromFile}" Icon="{ext:Icon fa-solid fa-file-code}" /> <MenuItem Command="{Binding InstallFirmwareFromFile}" Header="{ext:Locale MenuBarActionsInstallFirmwareFromFile}" Icon="{ext:Icon mdi-file-cog}" />
<MenuItem Command="{Binding InstallFirmwareFromFolder}" Header="{ext:Locale MenuBarActionsInstallFirmwareFromDirectory}" Icon="{ext:Icon fa-solid fa-folder-closed}" /> <MenuItem Command="{Binding InstallFirmwareFromFolder}" Header="{ext:Locale MenuBarActionsInstallFirmwareFromDirectory}" Icon="{ext:Icon mdi-folder-cog}" />
</MenuItem> </MenuItem>
<MenuItem Header="{ext:Locale MenuBarActionsManageFileTypes}" IsVisible="{Binding ManageFileTypesVisible}"> <MenuItem Header="{ext:Locale MenuBarActionsManageFileTypes}" IsVisible="{Binding ManageFileTypesVisible}">
<MenuItem Name="InstallFileTypesMenuItem" Header="{ext:Locale MenuBarActionsInstallFileTypes}" IsEnabled="{Binding AreMimeTypesRegistered, Converter={x:Static BoolConverters.Not}}" /> <MenuItem Name="InstallFileTypesMenuItem" Header="{ext:Locale MenuBarActionsInstallFileTypes}" IsEnabled="{Binding AreMimeTypesRegistered, Converter={x:Static BoolConverters.Not}}" />
@ -240,34 +248,36 @@
<MenuItem <MenuItem
Name="AboutWindowMenuItem" Name="AboutWindowMenuItem"
Header="{ext:Locale MenuBarHelpAbout}" Header="{ext:Locale MenuBarHelpAbout}"
Icon="{ext:Icon fa-solid fa-circle-info}" /> Icon="{ext:Icon fa-solid fa-circle-info}"
ToolTip.Tip="{ext:Locale OpenAboutTooltip}" />
<MenuItem <MenuItem
Name="UpdateMenuItem" Name="UpdateMenuItem"
IsEnabled="{Binding CanUpdate}" IsEnabled="{Binding CanUpdate}"
Header="{ext:Locale MenuBarHelpCheckForUpdates}" Header="{ext:Locale MenuBarHelpCheckForUpdates}"
Icon="{ext:Icon fa-solid fa-rotate}" /> Icon="{ext:Icon mdi-update}"
ToolTip.Tip="{ext:Locale CheckUpdatesTooltip}" />
<MenuItem <MenuItem
Name="CompatibilityListMenuItem" Name="CompatibilityListMenuItem"
Header="{ext:Locale CompatibilityListOpen}" Header="{ext:Locale CompatibilityListOpen}"
Icon="{ext:Icon fa-solid fa-database}"/> Icon="{ext:Icon mdi-gamepad}"/>
<Separator /> <Separator />
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelpFaqAndGuides}" Icon="{ext:Icon fa-solid fa-question}" > <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelpFaqAndGuides}" Icon="{ext:Icon fa-solid fa-question}" >
<MenuItem <MenuItem
Name="FaqMenuItem" Name="FaqMenuItem"
Header="{ext:Locale MenuBarHelpFaq}" Header="{ext:Locale MenuBarHelpFaq}"
Icon="{ext:Icon fa-brands fa-gitlab}" Icon="{ext:Icon fa-github}"
CommandParameter="https://git.ryujinx.app/ryubing/ryujinx/-/wikis/FAQ-&amp;-Troubleshooting" CommandParameter="https://git.ryujinx.app/ryubing/ryujinx/-/wikis/FAQ-&amp;-Troubleshooting"
ToolTip.Tip="{ext:Locale MenuBarHelpFaqTooltip}" /> ToolTip.Tip="{ext:Locale MenuBarHelpFaqTooltip}" />
<MenuItem <MenuItem
Name="SetupGuideMenuItem" Name="SetupGuideMenuItem"
Header="{ext:Locale MenuBarHelpSetup}" Header="{ext:Locale MenuBarHelpSetup}"
Icon="{ext:Icon fa-brands fa-gitlab}" Icon="{ext:Icon fa-github}"
CommandParameter="https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Setup-&amp;-Configuration-Guide" CommandParameter="https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Setup-&amp;-Configuration-Guide"
ToolTip.Tip="{ext:Locale MenuBarHelpSetupTooltip}" /> ToolTip.Tip="{ext:Locale MenuBarHelpSetupTooltip}" />
<MenuItem <MenuItem
Name="LdnGuideMenuItem" Name="LdnGuideMenuItem"
Header="{ext:Locale MenuBarHelpMultiplayer}" Header="{ext:Locale MenuBarHelpMultiplayer}"
Icon="{ext:Icon fa-brands fa-gitlab}" Icon="{ext:Icon fa-github}"
CommandParameter="https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Multiplayer-(LDN-Local-Wireless)-Guide" CommandParameter="https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Multiplayer-(LDN-Local-Wireless)-Guide"
ToolTip.Tip="{ext:Locale MenuBarHelpMultiplayerTooltip}" /> ToolTip.Tip="{ext:Locale MenuBarHelpMultiplayerTooltip}" />
</MenuItem> </MenuItem>

View File

@ -64,7 +64,6 @@
MinWidth="200" MinWidth="200"
Height="6" Height="6"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="0, 0, 5, 0"
Foreground="{DynamicResource SystemAccentColorLight2}" Foreground="{DynamicResource SystemAccentColorLight2}"
IsVisible="{Binding StatusBarVisible}" IsVisible="{Binding StatusBarVisible}"
Maximum="{Binding StatusBarProgressMaximum}" Maximum="{Binding StatusBarProgressMaximum}"
@ -236,6 +235,7 @@
Minimum="0" Minimum="0"
SmallChange="0.01" SmallChange="0.01"
TickFrequency="0.05" TickFrequency="0.05"
ToolTip.Tip="{ext:Locale AudioVolumeTooltip}"
Value="{Binding Volume}" /> Value="{Binding Volume}" />
</Grid> </Grid>
</Flyout> </Flyout>

View File

@ -49,7 +49,8 @@
<TextBlock <TextBlock
Margin="10,0" Margin="10,0"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{ext:Locale IconSize}" /> Text="{ext:Locale IconSize}"
ToolTip.Tip="{ext:Locale IconSizeTooltip}" />
<controls:SliderScroll <controls:SliderScroll
Width="150" Width="150"
Height="35" Height="35"
@ -60,6 +61,7 @@
Maximum="4" Maximum="4"
Minimum="1" Minimum="1"
TickFrequency="1" TickFrequency="1"
ToolTip.Tip="{ext:Locale IconSizeTooltip}"
Value="{Binding GridSizeScale}" /> Value="{Binding GridSizeScale}" />
<CheckBox <CheckBox
Margin="0" Margin="0"

View File

@ -33,7 +33,6 @@
Width="250" /> Width="250" />
<ComboBox SelectedIndex="{Binding AudioBackend}" <ComboBox SelectedIndex="{Binding AudioBackend}"
Width="350" Width="350"
ToolTip.Tip="{ext:Locale AudioBackendTooltip}"
HorizontalContentAlignment="Left"> HorizontalContentAlignment="Left">
<ComboBoxItem> <ComboBoxItem>
<TextBlock Text="{ext:Locale SettingsTabSystemAudioBackendDummy}" /> <TextBlock Text="{ext:Locale SettingsTabSystemAudioBackendDummy}" />
@ -52,8 +51,10 @@
<StackPanel Margin="10,0,0,0" Orientation="Horizontal"> <StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" <TextBlock VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemAudioVolume}" Text="{ext:Locale SettingsTabSystemAudioVolume}"
ToolTip.Tip="{ext:Locale AudioVolumeTooltip}"
Width="250" /> Width="250" />
<ui:NumberBox Value="{Binding Volume}" <ui:NumberBox Value="{Binding Volume}"
ToolTip.Tip="{ext:Locale AudioVolumeTooltip}"
Width="350" Width="350"
SmallChange="1" SmallChange="1"
LargeChange="10" LargeChange="10"
@ -65,6 +66,7 @@
<StackPanel Margin="10,0,0,0" Orientation="Horizontal"> <StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<controls:SliderScroll Value="{Binding Volume}" <controls:SliderScroll Value="{Binding Volume}"
Margin="250,0,0,0" Margin="250,0,0,0"
ToolTip.Tip="{ext:Locale AudioVolumeTooltip}"
Minimum="0" Minimum="0"
Maximum="100" Maximum="100"
SmallChange="1" SmallChange="1"

View File

@ -1,66 +0,0 @@
<UserControl
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsDebugView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:helper="clr-namespace:Ryujinx.Common.Helper;assembly=Ryujinx.Common"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
mc:Ignorable="d"
x:DataType="viewModels:SettingsViewModel">
<Design.DataContext>
<viewModels:SettingsViewModel />
</Design.DataContext>
<ScrollViewer
Name="DebugPage"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<Border Classes="settings">
<StackPanel
Margin="10"
HorizontalAlignment="Stretch"
Orientation="Vertical"
Spacing="10">
<TextBlock Classes="h1" Text="{ext:Locale SettingsTabDebugTitle}" />
<TextBlock Foreground="{DynamicResource SecondaryTextColor}" Text="{ext:Locale SettingsTabDebugNote}" />
<StackPanel
Margin="10,0,0,0"
HorizontalAlignment="Stretch"
Orientation="Vertical">
<CheckBox IsChecked="{Binding EnableGdbStub}">
<TextBlock Text="{ext:Locale SettingsTabDebugEnableGDBStub}"
ToolTip.Tip="{ext:Locale SettingsTabDebugGDBStubToggleTooltip}" />
</CheckBox>
</StackPanel>
<StackPanel
Margin="10,0,0,0"
Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{ext:Locale SettingsTabDebugGDBStubPort}"
Width="250" />
<ui:NumberBox Value="{Binding GDBStubPort}"
Width="350"
SmallChange="1"
LargeChange="10"
SimpleNumberFormat="F0"
SpinButtonPlacementMode="Inline"
Minimum="1024"
Maximum="65535" />
</StackPanel>
<StackPanel
Margin="10,0,0,0"
HorizontalAlignment="Stretch"
Orientation="Vertical">
<CheckBox IsChecked="{Binding DebuggerSuspendOnStart}">
<TextBlock Text="{ext:Locale SettingsTabDebugSuspendOnStart}"
ToolTip.Tip="{ext:Locale SettingsTabDebugSuspendOnStartTooltip}" />
</CheckBox>
</StackPanel>
</StackPanel>
</Border>
</ScrollViewer>
</UserControl>

View File

@ -1,13 +0,0 @@
using Avalonia.Controls;
namespace Ryujinx.Ava.UI.Views.Settings
{
public partial class SettingsDebugView : UserControl
{
public SettingsDebugView()
{
InitializeComponent();
}
}
}

View File

@ -285,10 +285,12 @@
Spacing="10"> Spacing="10">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" <TextBlock VerticalAlignment="Center"
ToolTip.Tip="{ext:Locale ShaderDumpPathTooltip}"
Text="{ext:Locale SettingsTabGraphicsShaderDumpPath}" Text="{ext:Locale SettingsTabGraphicsShaderDumpPath}"
Width="250" /> Width="250" />
<TextBox Text="{Binding ShaderDumpPath}" <TextBox Text="{Binding ShaderDumpPath}"
Width="350" /> Width="350"
ToolTip.Tip="{ext:Locale ShaderDumpPathTooltip}" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -40,6 +40,7 @@
Width="250" /> Width="250" />
<ComboBox <ComboBox
SelectedIndex="{Binding Region}" SelectedIndex="{Binding Region}"
ToolTip.Tip="{ext:Locale RegionTooltip}"
HorizontalContentAlignment="Left" HorizontalContentAlignment="Left"
Width="350"> Width="350">
<ComboBoxItem> <ComboBoxItem>
@ -71,9 +72,11 @@
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemSystemLanguage}" Text="{ext:Locale SettingsTabSystemSystemLanguage}"
ToolTip.Tip="{ext:Locale LanguageTooltip}"
Width="250" /> Width="250" />
<ComboBox <ComboBox
SelectedIndex="{Binding Language}" SelectedIndex="{Binding Language}"
ToolTip.Tip="{ext:Locale LanguageTooltip}"
HorizontalContentAlignment="Left" HorizontalContentAlignment="Left"
Width="350"> Width="350">
<ComboBoxItem> <ComboBoxItem>
@ -138,6 +141,7 @@
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemSystemTimeZone}" Text="{ext:Locale SettingsTabSystemSystemTimeZone}"
ToolTip.Tip="{ext:Locale TimezoneTooltip}"
Width="250" /> Width="250" />
<AutoCompleteBox <AutoCompleteBox
Name="TimeZoneBox" Name="TimeZoneBox"
@ -148,6 +152,7 @@
SelectionChanged="TimeZoneBox_OnSelectionChanged" SelectionChanged="TimeZoneBox_OnSelectionChanged"
Text="{Binding Path=TimeZone, Mode=OneWay}" Text="{Binding Path=TimeZone, Mode=OneWay}"
TextChanged="TimeZoneBox_OnTextChanged" TextChanged="TimeZoneBox_OnTextChanged"
ToolTip.Tip="{ext:Locale TimezoneTooltip}"
ValueMemberBinding="{Binding Mode=OneWay, Converter={x:Static helpers:TimeZoneConverter.Instance}}" /> ValueMemberBinding="{Binding Mode=OneWay, Converter={x:Static helpers:TimeZoneConverter.Instance}}" />
</StackPanel> </StackPanel>
<StackPanel <StackPanel
@ -158,11 +163,13 @@
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemSystemTime}" Text="{ext:Locale SettingsTabSystemSystemTime}"
ToolTip.Tip="{ext:Locale TimeTooltip}"
Width="250"/> Width="250"/>
<DatePicker <DatePicker
VerticalAlignment="Center" VerticalAlignment="Center"
IsEnabled="{Binding !MatchSystemTime}" IsEnabled="{Binding !MatchSystemTime}"
SelectedDate="{Binding CurrentDate}" SelectedDate="{Binding CurrentDate}"
ToolTip.Tip="{ext:Locale TimeTooltip}"
Width="350" /> Width="350" />
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}"/> <TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}"/>
</StackPanel> </StackPanel>
@ -176,7 +183,8 @@
ClockIdentifier="24HourClock" ClockIdentifier="24HourClock"
IsEnabled="{Binding !MatchSystemTime}" IsEnabled="{Binding !MatchSystemTime}"
SelectedTime="{Binding CurrentTime}" SelectedTime="{Binding CurrentTime}"
Width="350" /> Width="350"
ToolTip.Tip="{ext:Locale TimeTooltip}" />
<TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}"/> <TextBlock Classes="globalConfigMarker" IsVisible="{Binding IsGameTitleNotNull}"/>
</StackPanel> </StackPanel>
<StackPanel <StackPanel
@ -281,7 +289,6 @@
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{ext:Locale SettingsTabSystemDramSize}" Text="{ext:Locale SettingsTabSystemDramSize}"
ToolTip.Tip="{ext:Locale DRamTooltip}"
Width="250" /> Width="250" />
<ComboBox <ComboBox
SelectedIndex="{Binding DramSize}" SelectedIndex="{Binding DramSize}"

View File

@ -213,13 +213,13 @@ namespace Ryujinx.Ava.UI.Windows
} }
} }
public async void Application_Opened(object sender, ApplicationOpenedEventArgs args) public void Application_Opened(object sender, ApplicationOpenedEventArgs args)
{ {
if (args.Application != null) if (args.Application != null)
{ {
ViewModel.SelectedIcon = args.Application.Icon; ViewModel.SelectedIcon = args.Application.Icon;
await ViewModel.LoadApplication(args.Application); ViewModel.LoadApplication(args.Application).Wait();
} }
args.Handled = true; args.Handled = true;

View File

@ -46,7 +46,6 @@
<settings:SettingsAudioView Name="AudioPage" /> <settings:SettingsAudioView Name="AudioPage" />
<settings:SettingsNetworkView Name="NetworkPage" /> <settings:SettingsNetworkView Name="NetworkPage" />
<settings:SettingsLoggingView Name="LoggingPage" /> <settings:SettingsLoggingView Name="LoggingPage" />
<settings:SettingsDebugView Name="DebugPage" />
<settings:SettingsHacksView Name="HacksPage" /> <settings:SettingsHacksView Name="HacksPage" />
</Grid> </Grid>
<ui:NavigationView <ui:NavigationView
@ -101,10 +100,6 @@
Content="{ext:Locale SettingsTabLogging}" Content="{ext:Locale SettingsTabLogging}"
Tag="LoggingPage" Tag="LoggingPage"
IconSource="Document" /> IconSource="Document" />
<ui:NavigationViewItem
Content="{ext:Locale SettingsTabDebug}"
Tag="DebugPage"
IconSource="Star" />
<ui:NavigationViewItem <ui:NavigationViewItem
IsVisible="{Binding ShowDirtyHacks}" IsVisible="{Binding ShowDirtyHacks}"
Content="Dirty Hacks" Content="Dirty Hacks"

View File

@ -98,9 +98,6 @@ namespace Ryujinx.Ava.UI.Windows
case "LoggingPage": case "LoggingPage":
NavPanel.Content = LoggingPage; NavPanel.Content = LoggingPage;
break; break;
case "DebugPage":
NavPanel.Content = DebugPage;
break;
case nameof(HacksPage): case nameof(HacksPage):
HacksPage.DataContext = ViewModel; HacksPage.DataContext = ViewModel;
NavPanel.Content = HacksPage; NavPanel.Content = HacksPage;